图像膨胀|图像腐蚀
import numpy as np
import matplotlib.pyplot as plt
import cv2
## a.图像的二值化 ,这里没有做阈值处理
src = cv2.imread('lina.jpg', 0)
ret2,th2 = cv2.threshold(src,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
## b.设置卷积核5*5
kernel = np.ones((3, 3), np.uint8)
## c.图像的腐蚀,默认迭代次数
erosion = cv2.erode(th2, kernel)
## 图像膨胀
fatten = cv2.dilate(th2,kernel)
## 效果展示
imgs = [src,th2,erosion,fatten]
titles= ['original','binaryzation','after erosion','after fatten']
for i in range(4):
plt.subplot(2,2,i+1)
plt.imshow(imgs[i],cmap='gray');plt.title(titles[i])
plt.show()
图像轮廓
#图形的轮廓
import numpy as np
import matplotlib.pyplot as plt
import cv2
from skimage import measure,draw
src = cv2.imread('lina.jpg', 0)
ret2,img = cv2.threshold(src,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
#检测所有图形的轮廓
contours = measure.find_contours(img, 0.5)
#绘制轮廓
fig, axes = plt.subplots(1,2,figsize=(8,8))
ax0, ax1= axes.ravel()
ax0.imshow(img,plt.cm.gray)
ax0.set_title('original image')
rows,cols=img.shape
ax1.axis([0,rows,cols,0])
for n, contour in enumerate(contours):
ax1.plot(contour[:, 1], contour[:, 0], linewidth=2)
ax1.axis('image')
ax1.set_title('contours')
plt.show()
图像边缘检测
https://blog.csdn.net/qq_40962368/article/details/81416954
sobel算子
# Sobel边缘检测算子
import numpy as np
import matplotlib.pyplot as plt
import cv2
#解决中文显示问题
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False
img = cv2.imread('lina.jpg', 0)
x = cv2.Sobel(img, cv2.CV_16S, 1, 0,ksize=3)
y = cv2.Sobel(img, cv2.CV_16S, 0, 1,ksize=3)
#cv2.CV_64F表示64位浮点数即64float。CV_16S是16位short型
#这里不使用numpy.float64,因为可能会发生溢出现象。用cv的数据则会自动
#第三和第四个参数分别是对X和Y方向的导数(即dx,dy),对于图像来说就是差分,这里1表示对X求偏导(差分),0表示不对Y求导(差分)。其中,X还可以求2次导。
#注意:对X求导就是检测X方向上是否有边缘。
XY = cv2.Sobel(img, cv2.CV_64F, 1, 1, ksize=3)
#这里对两个方向同时进行检测,则会过滤掉仅仅只是x或者y方向上的边缘
# cv2.convertScaleAbs(src[, dst[, alpha[, beta]]])
# 可选参数alpha是伸缩系数,beta是加到结果上的一个值,结果返回uint类型的图像
Scale_absX = cv2.convertScaleAbs(x) # convert 转换 scale 缩放
Scale_absY = cv2.convertScaleAbs(y)
Scale_absXY = cv2.convertScaleAbs(XY)
result = cv2.addWeighted(Scale_absX, 0.5, Scale_absY, 0.5, 0)
# cv2.imshow('img', img)
# cv2.imshow('Scale_absX', Scale_absX)
# cv2.imshow('Scale_absY', Scale_absY)
# cv2.imshow('result', result)
# cv2.waitKey(0)
# cv2.destroyAllWindows()
imgs = [img,Scale_absX,Scale_absY,result]
titles = ['img','Scale_absX','Scale_absY','result']
for i in range(4):
plt.subplot(2,2,i+1)
plt.imshow(imgs[i],cmap='gray');plt.title(titles[i],fontsize=9)
plt.axis('off')
plt.show()
plt.imshow(Scale_absXY,'gray');plt.axis('off');
plt.title('对两个方向同时进行检测,滤掉仅仅只是x或者y方向上的边缘')
plt.show()
Sobel函数求完导数后会有负值,还有会大于255的值。而原图像是uint8,即8位无符号数,所以Sobel建立的图像位数不够,会有截断。因此要使用16位有符号的数据类型,即cv2.CV_16S。处理完图像后,再使用cv2.convertScaleAbs()函数将其转回原来的uint8格式,否则图像无法显示。
拉普拉斯算子、canny算子
# 拉普拉斯算子
import numpy as np
import matplotlib.pyplot as plt
import cv2
img = cv2.imread('lina.jpg', 0)
laplacian = cv2.Laplacian(img, cv2.CV_16S, ksize=3)
dst = cv2.convertScaleAbs(laplacian)
plt.subplot(121);plt.imshow(dst,'gray');plt.title('laplacian')
#canny算子
blur = cv2.GaussianBlur(img, (3, 3), 0) # 用高斯滤波处理原图像降噪
canny = cv2.Canny(blur, 50,150) # 50是最小阈值,150是最大阈值
plt.subplot(122);plt.imshow(canny,'gray');plt.title('canny')
plt.show()