opencv学习笔记02——图像处理
图像阈值
#src:输入图,只能是单通道图像,通常来说都是灰度图
#dst:输出图
#thresh:阈值
#maxval:当像素值超过了阈值(或者小于阈值),根据type来决定,所赋予的值
#type:二值化操作的类型,包含了一下五种类型:cv2.Thresh_BINARY;cv2.THRESH_BINARY_INV;THRESH_TRUNC;THRESH_TOZERO;THRESH_TOZERO_INV
cv2.Thresh_BINARY:超过阈值的部分取maxval(最大值),否则取0
cv2.THRESH_BINARY_INV:cv2.Thresh_BINARY的反转
cv2.THRESH_TRUNC:大于阈值的部分取阈值,否则不变
cv2.THRESH_TOZERO:大于阈值部分不变,否则取0
cv2.THRESH_TOZERO_INV:cv2.THRESH_TOZERO的反转
ret,dst = cv2.threshold(src,thresh,maxval,type)
示例
#读取灰度图
img_cat = cv2.imread('C:/Users/nic/Desktop/opencv/picture/cat.JPG',cv2.IMREAD_GRAYSCALE)
ret,thresh1 = cv2.threshold(img_cat,127,255,cv2.THRESH_BINARY)
ret,thresh2 = cv2.threshold(img_cat,127,255,cv2.THRESH_BINARY_INV)
ret,thresh3 = cv2.threshold(img_cat,127,255,cv2.THRESH_TRUNC)
ret,thresh4 = cv2.threshold(img_cat,127,255,cv2.THRESH_TOZERO)
ret,thresh5 = cv2.threshold(img_cat,127,255,cv2.THRESH_TOZERO_INV)
titles = ['Original Image' , 'BINARY','BINARY_INV','TRUNC','TOZERO','TOZERO_INV']
images = [img_cat,thresh1,thresh2,thresh3,thresh4,thresh5]
for i in range(6):
plt.subplot(2,3,i+1),plt.imshow(images[i],'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()
输出结果

图像平滑
1.均值滤波
矩阵内积:
两个相同矩阵对于位置数乘积的和
均值滤波原理:
图像由许多像素构成,在进行处理时会计算某个局部区域的所有 pixels 之和并取其 average 值之后再将其 average 分配到中间的那个 pixel 的位置上。这种操作能够有效降低图像中的 noise 水平。
代码:
#(3,3)即为在3*3的小范围内的像素值取平均滤波
blur = cv2.blur(img,(3,3))
cv_show('new',blur)
before:

after:

2.方框滤波
和均值滤波基本相同,但存在normalize
#boxFilter和blur一样,都是取均值进行处理,但区别在于,boxFilter可以不进行归一化处理(只把范围内的像素点值相加,但不除以像素点个数)
#如果normalize=True,则进行归一化处理
#如歌normalize=False,则不进行归一化处理(当越界时,取255)
box = cv2.boxFilter(img,-1,(3,3),normalize=True)
cv_show('new',box)
before:

当normalize=True:

当normalize=False:

3.高斯滤波
卷积核中的参数遵循高斯分布等价于赋予中心区域附近的像素点获得更高的权重系数
#1代表高斯分布的标准差,标准差越大图像越模糊
aussion = cv2.GaussianBlur(img,(5,5),1)
cv_show('gaussion',aussion)
4.中值滤波
从小到大进行排序,找中间的值,把中间值赋给中间位置的像素点
#medianBlur
median = cv2.medianBlur(img,5)
cv_show('median',median)
5.拼接
#horizotal水平 vertical垂直
res = np.vstack((blur,aussion,median))
res = np.hstack((blur,aussion,median))
cv_show('all_image',res)
所有滤波结果
均值 高斯 中值

形态学转换
腐蚀操作
通常用于去除图像中的噪声、分割连通区域、减小目标物体的尺寸等
腐蚀操作遍历所有像素点,将其替换为结构元素中最小的像素点
周围区域内的每一个点如果成为背景元素,则该中心点也会被标记成背景元素。这有助于缩减或去除二值图像中的目标区域。
#创建结构元素(3x3 方框形)
kernel = np.ones((3,3),np.uint8)
#iterations迭代次数
erosion = cv2.erode(img,kernel,iterations=1)
膨胀操作
膨胀
kernel = np.ones((3,3),np.uint8)
dilate = cv2.dilate(img,kernel,iterations=1)
腐蚀和膨胀的结果

开运算与闭运算
开运算首先执行腐蚀操作(corrosion),随后执行膨胀操作(dilation)。该运算主要用于去除图像中的噪声、细小的干扰物体或分离连通的区域。
闭运算首先执行膨胀操作,并随后执行腐蚀操作;其主要作用是填平图像中孤立的空洞区域,并连接被分离的物体区域。
#open and close
opening = cv2.morphologyEx(img,cv2.MORPH_OPEN,kernel)
closing = cv2.morphologyEx(img,cv2.MORPH_CLOSE,kernel)
结果

梯度运算
梯度就是膨胀-腐蚀
膨胀大了一圈,腐蚀小了一圈,二者相减及为轮廓信息
#gradient
gradient = cv2.morphologyEx(img,cv2.MORPH_GRADIENT,kernel)

顶帽(礼帽)和黑帽
礼帽 = 原始图像 - 开运算结果 剩余原始图像的毛刺
黑猫 = 闭运算结果 -原始图像
采用礼帽技术和黑帽技术进行图像处理时,能够增强图像中微小的明暗细节,并且也能识别背景中的明亮或黑暗区域。
#tophat and blackhat
tophat = cv2.morphologyEx(img,cv2.MORPH_TOPHAT,kernel)
blackhat = cv2.morphologyEx(img,cv2.MORPH_BLACKHAT,kernel)
礼帽 黑帽

图像梯度
sobel算子

Gx表示在该像素点周围沿着x轴方向的差分值。具体而言,在一个3×3像素阵列中,在x轴方向上计算右侧减左侧的数值差异:当右侧呈现白色而左侧呈现黑色时,则结果为正值;反之则为负值。
Gy即为在3*3阵列中,在y方向上,下-上
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)

相较于原图而言,
观察到梯度只能计算左侧部分,
由于Gx是右减左的操作,
右侧轮廓值被设定为零,
因此右侧轮廓无法呈现出来,
为了获得完整的边缘检测结果,则需将所有低于零的数值转换为其绝对值。
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
#取绝对值
sobelx = cv2.convertScaleAbs(sobelx)
采用取绝对值的方法可以让原本在截断过程中丢失的部分恢复为正值,并有助于更好地提取轮廓特征

sobelx和sobely相结合
将获取的x梯度与y梯度按权重进行结合
sobelxy = cv2.addWeighted(sobelx,0.5,sobely,0.5,0)
输出为

sobelx和sobely可以直接进行计算
但不建议这样做,建议对x,y分开计算再结合
sobelxy = cv2.Sobel(img,cv2.CV_64F,1,1,ksize=3)
输出为

如果是girl则为

Scharr算子

基于相同的理论基础,在规模更大的数据集上运行该算法后发现,在结果差异的变化上表现出更高的敏感性,并且能够更全面地捕捉梯度信息
scharrx = cv2.Scharr(img,cv2.CV_64F,1,0)
scharrx = cv2.convertScaleAbs(scharrx)
scharry = cv2.Sobel(img,cv2.CV_64F,0,1)
scharry = cv2.convertScaleAbs(scharry)
scharrxy = cv2.addWeighted(scharrx,0.5,scharrx,0.5,0)
#stack
res = np.hstack((scharrx,scharry,scharrxy))
cv_show('all_image',res)
相比于sobel算子可以捕捉到更多的梯度信息
scharrx scharry scharrxy

Laplacion算子

相比前两个不需要x或y,他是用一个像素点与四周相比
laplacion = cv2.Laplacian(img,cv2.CV_64F)
laplacion = cv2.convertScaleAbs(laplacion)
cv_show('all_image',laplacion)
laplacion算子效果不太明显,所以建议与其他工具相结合使用

