显然这种处理元素间权值的方式更加合理一些。图像是2维的,所以我们需要使用2维的高斯函数,比如OpenCV中默认的3×3的高斯卷积核:
参数3 σx值越大,模糊效果越明显。高斯滤波相比均值滤波效率要慢,但可以有效消除高斯噪声,能保留更多的图像细节,所以经常被称为最有用的滤波器。
中值又叫中位数,是所有数排序后取中间的值。中值滤波就是用区域内的中值来代替本像素值,所以那种孤立的斑点,如0或255很容易消除掉,适用于去除椒盐噪声和斑点噪声。中值是一种非线性操作,效率相比前面几种线性滤波要慢。
模糊操作基本都会损失掉图像细节信息,尤其前面介绍的线性滤波器,图像的边缘信息很难保留下来。然而,边缘(edge)信息是图像中很重要的一个特征,所以这才有了双边滤波。用cv2.bilateralFilter()
函数实现:
cv2.GaussianBlur()
,然后均值滤波cv2.blur()
。
cv2.bilateralFilter()
。
学习使用Canny获取图像的边缘。
Canny边缘检测方法常被誉为边缘检测的最优方法:
cv2.Canny()
进行边缘检测,参数2、3表示最低、高阈值,下面来解释下具体原理。
Canny边缘提取的具体步骤如下:
计算图像梯度的方向:首先使用Sobel算子计算两个方向上的梯度G_x和G_y,然后算出梯度的方向:arctan(G_y/G_x)
Canny推荐的高低阈值比在2:1到3:1之间。
学习常用形态学操作:腐蚀膨胀,开运算和闭运算。
形态学操作其实就是改变物体的形状,比如腐蚀就是"变瘦",膨胀就是"变胖",
形态学操作一般作用于二值化图,来连接相邻的元素或分离成独立的元素。腐蚀和膨胀是针对图片中的白色部分!
腐蚀的效果是把图片"变瘦",其原理是在原图的小区域内取局部最小值。因为是二值化图,只有0和255,所以小区域内有一个是0该像素点就为0:
这样原图中边缘地方就会变成0,达到了瘦身目的;OpenCV中用cv2.erode()
函数进行腐蚀,只需要指定核的大小就行:
这个核也叫结构元素,因为形态学操作其实也是应用卷积来实现的。结构元素可以是矩形/椭圆/十字形,可以用
cv2.getStructuringElement()
来生成不同形状的结构元素,比如:
膨胀与腐蚀相反,取的是局部最大值,效果是把图片"变胖":
开运算:先腐蚀后膨胀,其作用是:分离物体,消除小区域。这类形态学操作用cv2.morphologyEx()
函数实现。
闭运算:先膨胀后腐蚀,消除/"闭合"物体里面的小黑洞。
dilation - erosion
,这样会得到物体的轮廓:
src - opening
closing - src
学习如何寻找并绘制轮廓。
轮廓是一系列相连的点组成的曲线,代表了物体的基本外形。轮廓是连续的,边缘并不全都连续
寻找轮廓的操作一般用于二值化图,所以通常会使用阈值分割或Canny边缘检测先得到二值图。
寻找轮廓是针对白色物体的,一定要保证物体是白色,而背景是黑色,不然很多人在寻找轮廓时会找到图片最外面的一个框。
函数有3个返回值,image还是原来的二值化图片,hierarchy是轮廓间的层级关系,这两个暂时不用理会。我们主要看 contours,它就是找到的轮廓了,以数组形式存储,记录了每条轮廓的所有像素点的坐标(x,y)。
轮廓找出来后,为了方便观看,可以像前面图中那样用红色画出来:cv2.drawContours()
其中参数2就是得到的contours,参数3表示要绘制哪一条轮廓,-1表示绘制所有轮廓,参数4是颜色(B/G/R通道,所以(0,0,255)表示红色),参数5是线宽,之前在绘制图形中介绍过。
一般情况下,我们会首先获得要操作的轮廓,再进行轮廓绘制及分析:
学习计算轮廓特征,如面积、周长、最小外接矩形等。
在计算轮廓特征之前,我们先用上一节的代码把轮廓找到:
注意轮廓特征计算的结果并不等同于像素点的个数,而是根据几何方法算出来的,所以有小数。
参数2表示轮廓是否封闭,显然我们的轮廓是封闭的,所以是True。
矩可以理解为图像的各类几何特征,详情请参考:[Image Moments]
形状的外接矩形有两种,外接矩形表示不考虑旋转并且能包含整个轮廓的矩形;最小外接矩,考虑了旋转。
外接圆跟外接矩形一样,找到一个能包围物体的最小圆:
cv2.matchShapes()
可以检测两个形状之间的相似度,返回值越小,越相似。
图中有3条轮廓,我们用A/B/C表示:
可以看到BC相似程度比AB高很多,并且图形的旋转或缩放并没有影响。其中,参数3是匹配方法,详情可参考:ShapeMatchModes,参数4是OpenCV的预留参数,暂时没有实现,可以不用理会。
学习计算并绘制直方图,直方图均衡化等。
直方图就是图像中每个像素值的个数统计
有几个术语先来了解一下:
其实Matplotlib自带了一个计算并绘制直方图的功能,不需要用到上面的函数:
一副效果好的图像通常在直方图上的分布比较均匀,直方图均衡化就是用来改善图像的全局亮度和对比度。其实从观感上就可以发现,前面那幅图对比度不高,偏灰白。对均衡化算法感兴趣的同学可参考:维基百科:直方图均衡化
可以看到均衡化后图片的亮度和对比度效果明显好于原图。
直方图均衡化是应用于整幅图片的,而自适应均衡化,它在每一个小区域内(默认8×8)进行直方图均衡化。当然,如果有噪点的话,噪点会被放大,需要对小区域内的对比度进行了限制,所以这个算法全称叫:对比度受限的自适应直方图均衡化
学习使用模板匹配在图像中寻找物体。
模板匹配就是用来在大图中找小图,也就是说在一副图像中寻找另外一张模板图像的位置:
用cv2.matchTemplate()
实现模板匹配。首先我们来读入图片和模板:
前面我们是找最大匹配的点,所以只能匹配一次。我们可以设定一个匹配阈值来匹配多次:
学习使用霍夫变换识别出图像中的直线和圆。
OpenCV中用cv2.HoughLines()
在二值图上实现霍夫变换,函数返回的是一组直线的(r,θ)数据:
前面的方法又称为标准霍夫变换,它会计算图像中的每一个点,计算量比较大,另外它得到的是整一条线(r和θ),并不知道原图中直线的端点。所以提出了统计概率霍夫直线变换(Probabilistic Hough Transform),是一种改进的霍夫变换:
前面几个参数跟之前的一样,有两个可选参数:
minLineLength
:最短长度阈值,比这个长度短的线会被排除
maxLineGap
:同一直线两点之间的最大距离
霍夫圆变换跟直线变换类似,只不过线是用(r,θ)表示,圆是用(x_center,y_center,r)来表示,从二维变成了三维,数据量变大了很多;所以一般使用霍夫梯度法减少计算量,对该算法感兴趣的同学可参考:Circle Hough Transform
也就是-absinα^2从pi/2到0的定积分,(注意交换积分区域)
如果计算扇形面积,就从扇形的终止边对应的角β到起始边对应的角α的积分..
这个虽然不是求扇形面积,但相当于扇形与三角形的组合..
若为左侧情况(红色+蓝色),下面半椭圆面积pi*ab/2,蓝色就是三角形,算出点的坐标用底*高/2就可以解决..剩下两块对称的红色扇形,做-absinα^2从0到α的定积分的2倍(α就是红蓝交界线和水平x轴的夹角)..
右侧情况要不相当于pi*ab-左侧情况计算结果,要不相当于扇形面积-三角形面积..