使用Numpy和Opencv完成图像的基本数据分析(Part IV)

简介: 使用Numpy和Opencv完成图像的基本数据分析第四部分,主要包含阈值法、边缘检测、线型检测等操作

图像
       本文是使用python进行图像基本处理系列的第四部分,在本人之前的文章里介绍了一些非常基本的图像分析操作,见文章《使用Numpy和Opencv完成图像的基本数据分析Part I》、《使用Numpy和Opencv完成图像的基本数据分析 Part II》及《使用Numpy和Opencv完成图像的基本数据分析 Part III》,下面我们将继续介绍一些有关图像处理的好玩内容。
       本文介绍的内容基本反映了我本人学习的图像处理课程中的内容,并不会加入任何工程项目中的图像处理内容,本文目的是尝试实现一些基本图像处理技术的基础知识,出于这个原因,本文继续使用 SciKit-Image,numpy数据包执行大多数的操作,此外,还会时不时的使用其他类型的工具库,比如图像处理中常用的OpenCV等:
       本系列分为四个部分,分别为part I、part II、part III及part IV。刚开始想把这个系列分成两个部分,但由于内容丰富且各种处理操作获得的结果是令人着迷,因此不得不把它分成四个部分。系列所有的源代码地址:GitHub-Image-Processing-Python。现在,让我们开始吧!

阈值

大津法|OTSU

       阈值处理是图像处理中非常基本的操作。将灰度图像转换为单色是常见的图像处理任务。而且,一个好的算法总是以良好的基础开始!
       OTSU阈值处理是一种简单而有效的全局自动阈值处理方法,用于二值化灰度图像,比如前景(foreground)背景(background)。在图像处理中,OTSU阈值处理方法(1979)完全基于对图像直方图执行的计算,该算法假设图像由两个基本类组成——前景和背景。当取最佳阈值时,前景和背景两部分之间的差别应该是最大的,在OTSU算法中所采用的衡量差别的标准就是较为常见的最大类间方差。前景和背景之间的类间方差如果越大,就说明构成图像的两个部分之间的差别越大,当部分目标被错分为背景或部分背景被错分为目标,都会导致两部分差别变小,当所取阈值的分割使类间方差最大时就意味着错分概率最小 然后,它计算最小阈值,最小化这两个类的类方差的加权。
       目前,OTSU阈值法被广泛应用于医学成像、低级计算机视觉的许多应用中,该算法有很多优点和假设。
        OTSU阈值法的数学公式在我的个人主页上有所介绍,在那里详细解释了OTSU阈值法背后的数学原理。

算法

       如果我们把一个简单的数学融入到简单的步进算法中,上述的解释就会演变成:

  • 计算每个强度等级的直方图和概率。
  • 设置初始μi。
  • 从阈值 t=0逐步到t=L-1:

    • 更新:wi和μi
    • 计算:σ2b(t)

       期望阈值对应于σ2b(t)的最大值。

import numpy as np
import imageio
import matplotlib.pyplot as plt

pic = imageio.imread('img/potato.jpeg')
plt.figure(figsize=(7,7))
plt.axis('off')
plt.imshow(pic);

2

def otsu_threshold(im):

    # Compute histogram and probabilities of each intensity level
    pixel_counts = [np.sum(im == i) for i in range(256)]

    # Initialization
    s_max = (0,0)
    
    for threshold in range(256):

        # update
        w_0 = sum(pixel_counts[:threshold])
        w_1 = sum(pixel_counts[threshold:])

        mu_0 = sum([i * pixel_counts[i] for i in range(0,threshold)]) / w_0 if w_0 > 0 else 0       
        mu_1 = sum([i * pixel_counts[i] for i in range(threshold, 256)]) / w_1 if w_1 > 0 else 0

        # calculate - inter class variance
        s = w_0 * w_1 * (mu_0 - mu_1) ** 2

        if s > s_max[1]:
            s_max = (threshold, s)
            
            
    return s_max[0]
def threshold(pic, threshold):
    return ((pic > threshold) * 255).astype('uint8')

gray = lambda rgb : np.dot(rgb[... , :3] , [0.21 , 0.72, 0.07]) 

plt.figure(figsize=(7,7))
plt.imshow(threshold(gray(pic), otsu_threshold(pic)), cmap='Greys')
plt.axis('off');

3


       从上图可以看出,分离效果不错,但看起来并不是很好。如果假设直方图具有 双峰分布( bimodal distribution),并且假设在两个峰之间具有深且尖锐的波谷,则OTSU阈值法能够表现出相对良好的性能  。
       因此,假设图像的前景区域与背景区域差别比较小,则直方图不再呈现双峰分布,并且前景与背景强度的差异与平均差异相比较大,或图像被加性噪声严重破坏时,灰度直方图两峰之间的波谷值会降低,其尖锐性也会大打折扣。
       结论:由OTSU阈值法确定的某些可能不正确的阈值将导致分割错误,但我们可以进一步 改进该方法

K均值聚类|KMeans Clustering

       k-均值聚类是矢量量化的一种方法,最初是应用于信号处理中,目前常用于数据挖掘中的聚类分析。在OTSU阈值法中,我们找到了最小化内插像素方差的阈值。因此,我们可以不从灰度图像中寻找合适的阈值,而可以在彩色空间中去寻找聚类,通过这样的处理,最终演变为 K-均值聚类技术。

from sklearn import cluster

import matplotlib.pyplot as plt
# load image
pic = imageio.imread('img/purple.jpg') 

plt.figure(figsize=(7,7))
plt.imshow(pic)
plt.axis('off');

4


       为了对图像进行聚类,需要将其转换为二维数组。 
x, y, z = pic.shape
pic_2d = pic.reshape(x*y, z)

       接下来,我们使用scikit-learn中的集群方法来创建集群。我们将n_clusters设置为5,表明最终会形成五个簇。最终的聚类效果会在生成的图像中展示,从图中可以看到,已经将其划分为具有不同颜色的五个部分。
       将聚类簇的个数设置为5是为了演示例子,我们同样可以更改群集的数量,通过设置不同的集群数来进行对比实验,以可视化的方式验证具有不同颜色的图像,以最终确定,选择多少的群集数量才是比较合适的。

%%time

# fit on the image with cluster five
kmeans_cluster = cluster.KMeans(n_clusters=5)
kmeans_cluster.fit(pic_2d)

cluster_centers = kmeans_cluster.cluster_centers_
cluster_labels = kmeans_cluster.labels_
Wall time: 16.2 s

       一旦形成了簇,我们就可以使用簇中心和标签重新创建图像,以显示具有分组模式的图像。

plt.figure(figsize=(7,7))
plt.imshow(cluster_centers[cluster_labels].reshape(x, y, z))
plt.axis('off');

5

线型检测

霍夫变换|Hough Transform

       霍夫变换是图像处理中比较流行的一种技术。如果我们能用数学形式表示出某个形状,那么它久可以用来检测出任何形状。即使图像形状被稍微扭曲或者被破坏,它也可以从中检测出形状。在通过代码实现该算法之前,我们不会过于深入地分析霍夫变换的基本原理,而是还提供一些资源来使得读者能够更详细地理解它。
       霍夫变换的数学公式可以在我的主页查看,并且,主页上也详细解释了霍夫变换算法背后的数学原理。

6

where
ρ = distance from origin to the line. [-Dmax, Dmax]
Dmax is the diagonal length of the image.

θ = angle from origin to the line. [-90° to 90°]

算法

  • 拐角或边缘检测
  • ρ范围和θ范围创建

    • ρ:-Dmax ~Dmax;
    • θ:-90~90;
  • 霍夫累加器

    • 二维数组的行数等于ρvalues的数量,列数等于θ的数量;
  • 在累加器中投票

    • 对于每个边缘点和每个θ值,找到最接近的ρvalue并在累加器中递增该索引;
  • 峰值检测

    • 累加器中的局部最大值表示输入图像中最突出线条的参数;
def hough_line(img):
    # Rho and Theta ranges
    thetas = np.deg2rad(np.arange(-90.0, 90.0))
    width, height = img.shape
    diag_len = int(np.ceil(np.sqrt(width * width + height * height)))   # Dmax
    rhos = np.linspace(-diag_len, diag_len, diag_len * 2.0)

    # Cache some resuable values
    cos_t = np.cos(thetas)
    sin_t = np.sin(thetas)
    num_thetas = len(thetas)

    # Hough accumulator array of theta vs rho
    accumulator = np.zeros((2 * diag_len, num_thetas), dtype=np.uint64)
    y_idxs, x_idxs = np.nonzero(img)  # (row, col) indexes to edges

    # Vote in the hough accumulator
    for i in range(len(x_idxs)):
        x = x_idxs[i]
        y = y_idxs[i]
        
        for t_idx in range(num_thetas):
            # Calculate rho. diag_len is added for a positive index
            rho = round(x * cos_t[t_idx] + y * sin_t[t_idx]) + diag_len
            accumulator[rho, t_idx] += 1
    return accumulator, thetas, rhos

边缘检测

       边缘检测是一种用于查找图像内对象边界的图像处理技术,其工作原理是检测亮度的不连续性。常见的边缘检测算法包括

  • 索贝尔算子(Sobel)
  • 卡尼算子(Canny)
  • 普鲁伊特算子(Prewitt)
  • 罗伯茨算子(Roberts)
  • 模糊逻辑方法(fuzzy logic)

       在这里,我们介绍一种最流行的方法,即  Canny 边缘检测(Canny Edge Detection)

Canny边缘检测

       该方法是一种能够检测图像中宽范围边缘的多级边缘检测操作。一般而言,Canny边缘检测算法可以分解为以下5个步骤:

  • 1.应用高斯滤波器;
  • 2.找到强度梯度;
  • 3.应用非最大抑制;
  • 4.应用双重阈值;
  • 5.通过滞后跟踪边缘;

       以上是Canny边缘检测的算法概述,有关更全面的概述,请查看本文末尾给定链接。由于本文的长度限定,本文在此处不展示完整的实现代码,而是直观地概述该代码的相关算法。
        Canny边缘检测的处理过程可以在此查看,同样,该链接将重定向回我的个人主页,主页上详细解释了Canny边缘检测算法背后的数学知识。
       以上是关于Python中基本图像处理最后的第4部分,整个系列的源代码可在此处访问

相关

作者信息

Mohammed Innat,机器学习和数据科学研究者
本文由阿里云云栖社区组织翻译。
文章原标题《Basic Image Data Analysis Using Numpy and OpenCV – Part 4》,译者:海棠,审校:Uncle_LLD。
文章为简译,更为详细的内容,请查看原文

相关文章
|
2月前
|
计算机视觉
Opencv学习笔记(三):图像二值化函数cv2.threshold函数详解
这篇文章详细介绍了OpenCV库中的图像二值化函数`cv2.threshold`,包括二值化的概念、常见的阈值类型、函数的参数说明以及通过代码实例展示了如何应用该函数进行图像二值化处理,并展示了运行结果。
547 0
Opencv学习笔记(三):图像二值化函数cv2.threshold函数详解
|
3月前
|
算法 计算机视觉
opencv图像形态学
图像形态学是一种基于数学形态学的图像处理技术,它主要用于分析和修改图像的形状和结构。
56 4
|
3天前
|
计算机视觉 Python
PIL图像转换为Numpy数组:技术与案例详解
本文介绍了如何将PIL图像转换为Numpy数组,以便利用Numpy进行数学运算和向量化操作。首先简要介绍了PIL和Numpy的基本功能,然后详细说明了转换过程,包括导入库、打开图像文件、使用`np.array()`或`np.asarray()`函数进行转换,并通过打印数组形状验证转换结果。最后,通过裁剪、旋转和缩放等案例展示了转换后的应用,以及如何将Numpy数组转换回PIL图像。此外,还介绍了处理base64编码图像的完整流程。
17 4
|
1月前
|
机器学习/深度学习 数据采集 数据挖掘
解锁 Python 数据分析新境界:Pandas 与 NumPy 高级技巧深度剖析
Pandas 和 NumPy 是 Python 中不可或缺的数据处理和分析工具。本文通过实际案例深入剖析了 Pandas 的数据清洗、NumPy 的数组运算、结合两者进行数据分析和特征工程,以及 Pandas 的时间序列处理功能。这些高级技巧能够帮助我们更高效、准确地处理和分析数据,为决策提供支持。
46 2
|
3月前
|
存储 计算机视觉
Opencv的基本操作(一)图像的读取显示存储及几何图形的绘制
本文介绍了使用OpenCV进行图像读取、显示和存储的基本操作,以及如何绘制直线、圆形、矩形和文本等几何图形的方法。
Opencv的基本操作(一)图像的读取显示存储及几何图形的绘制
|
2月前
|
机器学习/深度学习 数据采集 算法
探索Python科学计算的边界:NumPy、Pandas与SciPy在大规模数据分析中的高级应用
【10月更文挑战第5天】随着数据科学和机器学习领域的快速发展,处理大规模数据集的能力变得至关重要。Python凭借其强大的生态系统,尤其是NumPy、Pandas和SciPy等库的支持,在这个领域占据了重要地位。本文将深入探讨这些库如何帮助科学家和工程师高效地进行数据分析,并通过实际案例来展示它们的一些高级应用。
64 0
探索Python科学计算的边界:NumPy、Pandas与SciPy在大规模数据分析中的高级应用
|
2月前
|
数据采集 数据挖掘 API
Python数据分析加速器:深度挖掘Pandas与NumPy的高级功能
在Python数据分析的世界里,Pandas和NumPy无疑是两颗璀璨的明星,它们为数据科学家和工程师提供了强大而灵活的工具集,用于处理、分析和探索数据。今天,我们将一起深入探索这两个库的高级功能,看看它们如何成为数据分析的加速器。
48 1
|
2月前
|
数据挖掘 索引 Python
Python数据分析篇--NumPy--进阶
Python数据分析篇--NumPy--进阶
22 0
|
2月前
|
数据挖掘 索引 Python
Python数据分析篇--NumPy--入门
Python数据分析篇--NumPy--入门
41 0
|
4月前
|
算法 计算机视觉 Python
python利用opencv进行相机标定获取参数,并根据畸变参数修正图像附有全部代码(流畅无痛版)
该文章详细介绍了使用Python和OpenCV进行相机标定以获取畸变参数,并提供了修正图像畸变的全部代码,包括生成棋盘图、拍摄标定图像、标定过程和畸变矫正等步骤。
python利用opencv进行相机标定获取参数,并根据畸变参数修正图像附有全部代码(流畅无痛版)