1.cv2.erode(src, kernel, iteration)
参数说明:src表示的是输入图片,kernel表示的是方框的大小,iteration表示迭代的次数
腐蚀操作原理:存在一个kernel,比如(3, 3),在图像中不断的平移,在这个9方框中,哪一种颜色所占的比重大,9个方格中将都是这种颜色
代码:
1.读取带有毛刺的图片
2.使用cv2.erode进行腐蚀操作,比较不同的kernel对结果的影响
3.读取圆的图片
4.使用cv2.erode进行腐蚀操作,比较不同的迭代次数对结果的影响
import cv2 import numpy as np # 1.读取带有毛刺的图片 img = cv2.imread('dige.png') cv2.imshow('img', img) cv2.waitKey(0) cv2.destroyAllWindows()
# 2.比较不同的kernel最终的腐蚀效果 kernel = np.ones((3, 3), np.uint8) erosion_1 = cv2.erode(img, kernel, iterations=1) kernel_1 = np.ones((6, 6), np.uint8) erosion_2 = cv2.erode(img, kernel_1, iterations=1) cv2.imshow('erosion', np.hstack((erosion_1, erosion_2))) cv2.waitKey(0) cv2.destroyAllWindows()
# 3.读取圆的图片 pie = cv2.imread('pie.png') cv2.imshow('pie', pie) cv2.waitKey(0) cv2.destroyAllWindows()
# 4.比较不同的迭代次数对最终结果的影响 kernel = np.ones((20, 20), np.uint8) erosion_1 = cv2.erode(pie, kernel, iterations=1) erosion_2 = cv2.erode(pie, kernel, iterations=2) erosion_3 = cv2.erode(pie, kernel, iterations=3) imgs = np.hstack((erosion_1, erosion_2, erosion_3)) cv2.imshow('pie', imgs) cv2.waitKey(0) cv2.destroyAllWindows()
1.cv2.morphologyEx(src, op, kernel) 进行各类形态学的变化
参数说明:src传入的图片,op进行变化的方式, kernel表示方框的大小
2.op = cv2.MORPH_OPEN 进行开运算,指的是先进行腐蚀操作,再进行膨胀操作
3. op = cv2.MORPH_CLOSE 进行闭运算, 指的是先进行膨胀操作,再进行腐蚀操作
开运算:表示的是先进行腐蚀,再进行膨胀操作
闭运算:表示先进行膨胀操作,再进行腐蚀操作
代码:
第一步:使用cv2.imread载入图片
第二步:使用cv2.morphologyEx进行形态学的变化,使用的op = cv2.MORPH_OPEN进行开运算
第三步:使用cv2.morphologyEx进行形态学的变化,使用的op = cv2.MORPH_CLOSE 进行闭运算
import cv2 import numpy as np # 1.读取图片 img = cv2.imread('dige.png') cv2.imshow('img', img) cv2.waitKey(0) cv2.destroyAllWindows()
# 2. cv2.MORPH_OPEN 先进行腐蚀操作,再进行膨胀操作 kernel = np.ones((5, 5), np.uint8) opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel) cv2.imshow('opening', opening) cv2.waitKey(0) cv2.destroyAllWindows()
# 3. cv2.MORPH_CLOSE 先进行膨胀,再进行腐蚀操作 kernel = np.ones((5, 5), np.uint8) closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel) cv2.imshow('closing', closing) cv2.waitKey(0) cv2.destroyAllWindows()
1.op = cv2.GRADIENT 用于梯度运算-膨胀图像-腐蚀后的图像
梯度运算:表示的是将膨胀以后的图像 - 腐蚀后的图像,获得了最终的边缘轮廓
代码:
第一步:读取pie图片
第二步:进行腐蚀和膨胀操作
第三步:将膨胀的图像 - 腐蚀的图像,获得相减得图像
第四步:使用cv2.morphologyEx(src, cv2.GRADIENT, kernel) 获得梯度运算的图片的操作
第五步:绘制第三步和第四步生成的图片
import cv2 import numpy as np # 第一步:读取图片 pie = cv2.imread('pie.png')
# 第二步:绘制腐蚀和膨胀图片 kernel = np.ones((5, 5), np.uint8) erosion = cv2.erode(pie, kernel, iterations=2) dilate = cv2.dilate(pie, kernel, iterations=2) # 第三步:相减获得对应的图片 decrease = dilate - erosion print(decrease.shape) cv2.imshow('pie', pie) cv2.waitKey(0) cv2.destroyAllWindows() # 第四步:使用cv2.MORPH_GRADIENT获得梯度运算的图片 gradient = cv2.morphologyEx(pie, cv2.MORPH_GRADIENT, kernel, iterations=2) # 第五步:绘制两者的图片 cv2.imshow('gradient', np.hstack((decrease, gradient))) cv2.waitKey(0) cv2.destroyAllWindows()
先开后闭还是先闭后开
1.op = cv2.TOPHAT 礼帽:原始图片-开运算后的图片
2. op=cv2.BLACKHAT 黑帽: 闭运算后的图片-原始图片
礼帽:表示的是原始图像-开运算(先腐蚀再膨胀)以后的图像
黑帽:表示的是闭运算(先膨胀再腐蚀)后的图像 - 原始图像
代码:
第一步:读取图片
第二步:使用cv2.MOPRH_TOPHAT获得礼帽图片
第三步:使用cv2.MOPRH_BLACKHAT获得黑帽图片
import cv2 import numpy as np # 第一步读入当前图片 img = cv2.imread('dige.png') cv2.imshow('img', img) cv2.waitKey(0) cv2.destroyAllWindows()
# 第二步:使用cv2.MORPH_TOPHAT获得礼帽图片 kernel = np.ones((3, 3), np.uint8) tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel) cv2.imshow('tophat', tophat) cv2.waitKey(0) cv2.destroyAllWindows()
# 第三步:使用cv2.MORPH_BLACKHAT获得黑帽图片 kernel = np.ones((3, 3), np.uint8) blackhat = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel) cv2.imshow('blackhat', blackhat) cv2.waitKey(0) cv2.destroyAllWindows()
1.cv2.Sobel(src, ddepth, dx, dy, ksize) 进行sobel算子计算
参数说明:src表示当前图片,ddepth表示图片深度,这里使用cv2.CV_64F使得结果可以是负值, dx表示x轴方向,dy表示y轴方向, ksize表示移动方框的大小
2.cv2.convertScalerAbs(src) 将像素点进行绝对值计算
参数说明: src表示当前图片
sobel算子:分为x轴方向和y轴方向上的,x轴方向上的算子如图中的Gx,将sober算子在图中进行平移,当前位置的像素值等于sobel算子与(当前位置与周边位置8个点)进行对应位置相乘并相加操作,作为当前位置的像素点,y轴方向的算子如Gy, 对于x轴方向上,即左右两边的比较,
计算方程为:x轴: p3 - p1 + 2 * p6 - 2 * p4 + p9 - p7, 右边的像素值减去左边的像素值
代码:
第一步:载入原始图片
第二步:使用cv2.Sobel(src, cv2.CV_64F, 1, 0, ksize=3) 对x轴方向进行sobel算子相乘操作
第三步:由于会出现负值的情况,因此使用cv2.convertScalerAbs() 转换为绝对值的形式
第四步:计算y轴方向上的sobel算子
第五步:使用cv2.addWeighted 将x轴方向的sobel算子的结果和y轴方向上的sobel算子的结果结合
第六步:使用cv2.Sobel(src, cv2.CV_64F, 1, 1, ksize=3) 直接获得x轴和y轴方向上的sobel算子结合
第七步:对这两个步骤获得的sobel算子作图
import cv2 import numpy as np # 第一步:加载图片 img = cv2.imread('pie.png') cv2.imshow('original', img) cv2.waitKey(0) cv2.destroyAllWindows()
# 第二步:对x轴方向上进行sobel算子相乘操作 x_sobel = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3) cv2.imshow('x_sobel', x_sobel) cv2.waitKey(0) cv2.destroyAllWindows()
# 第三步:因为右侧像素减去左边像素,存在负值的情况,因此使用cv2.convertScaleAbs取绝对值操作 x_sobel = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3) x_sobel = cv2.convertScaleAbs(x_sobel) cv2.imshow('x_sobel', x_sobel) cv2.waitKey(0) cv2.destroyAllWindows()
# 第四步:计算y轴的sobel算子 y_sobel = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3) y_sobel = cv2.convertScaleAbs(y_sobel) cv2.imshow('y_sobel', y_sobel) cv2.waitKey(0) cv2.destroyAllWindows()
# 第五步:并使用cv2.addweighted进行合并 xy_sobel = cv2.addWeighted(x_sobel, 0.5, y_sobel, 0.5, 0) # 第六步: 直接使用cv2.sobel 进行计算 xy_sobel_direct = cv2.Sobel(img, cv2.CV_64F, 1, 1, ksize=3) # 第七步:画图比较分步合并和一步到位的结果差异 cv2.imshow('imgs', np.hstack((xy_sobel, xy_sobel_direct))) cv2.waitKey(0) cv2.destroyAllWindows()
从图中我们可以看出x和y轴各自求,再做合并比直接求得的结果,轮廓更加的明显
1. cv2.Scharr(src,ddepth, dx, dy), 使用Scharr算子进行计算
参数说明:src表示输入的图片,ddepth表示图片的深度,通常使用-1, 这里使用cv2.CV_64F允许结果是负值, dx表示x轴方向算子,dy表示y轴方向算子
2.cv2.laplacian(src, ddepth) 使用拉普拉斯算子进行计算
参数说明: src表示输入的图片,ddepth表示图片的深度,这里使用cv2.CV_64F允许结果是负值
scharr算子, 从图中我们可以看出scharr算子,比sobel算子在比例上要更大,因此这样的好处是scharr算子获得的结果能体现出更多的边缘梯度的细节
laplacian 算子,从图中可以看出当前点的位置与周围4个点位置之差, 即周围四个点之和 - 4*当前位置像素点,这种算法容易受到噪声点的干扰,不存在x和y轴的计算过程
代码:
第一步: 载入图片,使用cv2.IMREAD_GRAYSCALE,读入的图片为灰度图
第二步:使用cv2.Sobel获得合并的sobel算子运算结果
第三步:使用cv2.Scharr获得合并的scharr算子梯度运算结果
第四步:使用cv2.laplacian算子获得拉普拉斯算子梯度运算结果
第五步:对3个结果进行最终的画图操作
import cv2 import numpy as np # 第一步读取图片 lena = cv2.imread('lena.jpg', cv2.IMREAD_GRAYSCALE) cv2.imshow('lena', lena) cv2.waitKey(0) cv2.destroyAllWindows()
# 第二步:使用cv2.sobel进行sobel算子计算 sobel_x = cv2.Sobel(lena, cv2.CV_64F, 1, 0) sobel_y = cv2.Sobel(lena, cv2.CV_64F, 0, 1) sobel_x = cv2.convertScaleAbs(sobel_x) sobel_y = cv2.convertScaleAbs(sobel_y) sobel_xy = cv2.addWeighted(sobel_x, 0.5, sobel_y, 0.5, 0) # 第三步:使用cv2.scharr进行scharr算子计算 scharr_x = cv2.Scharr(lena, cv2.CV_64F, 1, 0) scharr_y = cv2.Scharr(lena, cv2.CV_64F, 0, 1) scharr_x = cv2.convertScaleAbs(scharr_x) scharr_y = cv2.convertScaleAbs(scharr_y) scharr_xy = cv2.addWeighted(scharr_x, 0.5, scharr_y, 0.5, 0) # 第四步: 使用cv2.laplacian 拉普拉斯算子计算 lapkacian = cv2.Laplacian(lena, cv2.CV_64F) lapkacian = cv2.convertScaleAbs(lapkacian) # 第五步: 对三种结果进行画图 cv2.imshow('imgs', np.hstack((sobel_xy, scharr_xy, lapkacian))) cv2.waitKey(0) cv2.destroyAllWindows()
可以看出使用sobel算子的轮廓要更清晰,scharr算子的轮廓的细节更多,laplacian获得的结果边缘信息较浅