canny边缘检测
canny边缘检测算法是John F.Canny于1986年开发出来的一个多边缘检测算法,也被很多人认为是边缘检测的最优算法,最优边缘检测的三个主要标准是:
低错误率:标识出尽可能多的实际边缘,同时尽可能的减少噪声产生的误报。
高定位性:标识出的边缘要与图像中的实际边缘尽可能接近。
最小响应:图像中的边缘只能标注一次。
Canny边缘检测的一般步骤:
去噪:边缘检测容易受到噪声影响,在进行边缘检测前通常需要先进行去噪,一般用高斯滤波去除噪声。
计算梯度:对平滑后的图像采用sobel算子计算梯度和方向。
非极大值抑制:在获取了梯度和方向后,遍历图像,去除所有不是边界的点。
实现方法:逐个遍历像素点,判断当前像素点是否是周围像素点中具有相同方向梯度的最大值。如果是,保留该点;否则,它被抑制。
import cv2
import numpy as np
img = cv2.imread('./dog.jpg')
#cv2.Canny(image, threshold1, threshold2[, edges[, apertureSize[, L2gradient]]])
dog1=cv2.Canny(img,100,200)
dog2=cv2.Canny(img,110,210)
dog3=cv2.Canny(img,130,150)
cv2.imshow('img',img)
cv2.imshow('dog',np.vstack((dog1,dog2,dog3)))
cv2.waitKey(0)
cv2.destroyAllWindows()
查找轮廓
图像轮廓是具有相同颜色或灰度的连续的曲线,轮廓在形状分析和物体检测和识别中很有用。
轮廓的作用:
用于图形分析
物体的识别和检测
注意点:
为了检测的准确性,需要先对图像进行二值化或Canny操作。
画轮廓时会修改输入图像,如果之后像继续使用原始图像,应该将原始图像储存到其他变量中。
#findContours(image,mode,method[,contours[,hierarchy[,offset]]])
###mode 查找轮廓的方式
#####RETR_EXTERAL=0,表示只检测外围轮廓
#####RETR_LIST=1,检测的轮廓不建立等级关系,即检测所有轮廓,较为常用。
#####RETR_CCOMP=2,每层最多两级,从小到大,从里到外。
#####RETR_TREE=3,按照树型存储轮廓,从大到小,从右到左
###method 轮廓近似方法也叫ApproximationMode
#####CHAIN_APPROX_NONE 保存所有轮廓上的点
#####CHAIN_APPROX_SIMPLE,只保存角点,比如四边形,只保留四边形的4个角,存储信息少,比较常用
###返回contour和hierarchy即轮廓和层级
import cv2
import numpy as np
#读取图片
img=cv2.imread('./cat.jpg')
#变成单通道的黑白图片
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#二值化,注意有两个返回值,阈值和结果
ret,binary=cv2.threshold(gray,160,255,cv2.THRESH_BINARY)
#查找轮廓,新版本返回两个结果,分别是轮廓和层级
contours, hierarchy=cv2.findContours(binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
# #contour是list 不是ndarry,里面放的是ndarry表示一个contour
# print(type(contours))
# print(contours)
# print(hierarchy)
# cv2.imshow('img',img)
# cv2.imshow('gray',gray)
# cv2.imshow('binary',binary)
cv2.waitKey(0)
cv2.destroyAllWindows()
绘制轮廓
import cv2
import numpy as np
#读取图片
img=cv2.imread('./cat.jpg')
#变成单通道的黑白图片
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#二值化,注意有两个返回值,阈值和结果
ret,binary=cv2.threshold(gray,160,255,cv2.THRESH_BINARY)
#查找轮廓,新版本返回两个结果,分别是轮廓和层级
contours, hierarchy=cv2.findContours(binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
###########################################################################################
#绘制轮廓会直接修改原图。
#如果想保持原图不变,建议copy一份
#image 要绘制的轮廓图像
#contours 轮廓点
#contourIdx 要绘制的轮廓编号,-1表示绘制所有轮廓
#color 轮廓的颜色,如(0,0,255)表示红色
#thickness线宽,-1表示全填充
img_copy=img.copy()
cv2.drawContours(img_copy,contours,-1,(0,0,255),1)
##########################################################################################
cv2.imshow('img',img)
cv2.imshow('img_copy',img_copy)
# cv2.imshow('gray',gray)
cv2.imshow('binary',binary)
cv2.waitKey(0)
cv2.destroyAllWindows()
腐蚀操作
import cv2
import numpy as np
#导入图片
img=cv2.imread('./big.jpg')
#滤波
filt1=cv2.bilateralFilter(img,21,sigmaColor=50,sigmaSpace=500)
#二值化操作是对灰度图像操作,把dog变成灰度图像。
gray=cv2.cvtColor(filt1,cv2.COLOR_BGR2GRAY)
#滤波
filt12=cv2.bilateralFilter(gray,21,sigmaColor=50,sigmaSpace=500)
#自适应阈值二值化只有一个返回值。
bina=cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,49,0)
#定义核
kernel=np.ones((3,3),np.uint8)
dst=cv2.erode(bina,kernel,iterations=1)
cv2.imshow('img',img)
cv2.imshow('dst',dst)
cv2.imshow('big2',np.vstack((gray,bina)))
cv2.waitKey(0)
cv2.destroyAllWindows()
获取形态学卷积核
opencv提供了获取卷积核的api,不需要我们手工创建卷积核。
#getStructuringElement(shape,ksize[,anchor])
###shape是指卷积核的形状,注意不是指长宽,是指卷积核中1形成的形状。
#####MORPH_RECT卷积核中的1是矩形,常用。
#####MORPH_ELLIPSE 椭圆
#####MORPH_CROSS 十字
import cv2
import numpy as np
###################获取卷积核###########################
#矩形
#kernel=cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))
#椭圆
#kernel=cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5))
#十字
kernel=cv2.getStructuringElement(cv2.MORPH_CROSS,(5,5))
print(kernel)
########################################################
#导入图片
img=cv2.imread('./big.jpg')
#变成灰度图像。
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#自适应阈值二值化只有一个返回值。
bina=cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,49,0)
#腐蚀
dst=cv2.erode(bina,kernel,iterations=1)
cv2.imshow('dst',dst)
cv2.imshow('big2',np.vstack((gray,bina)))
cv2.waitKey(0)
cv2.destroyAllWindows()
开运算和闭运算
开运算
##################################################################################################
#开运算和闭运算都是腐蚀和膨胀的基本应用
#开运算=腐蚀+膨胀
#morphologyEx(img,MORPH_OPEN,kernel)
###MORPH_OPEN 表示形态学的开运算
###kernel 如果噪点比较多,会选择大一点的kernel,如果噪点比较小,可以选择小点的kernel。
##################################################################################################
import cv2
import numpy as np
#开运算=腐蚀+膨胀
#开运算提供了另一种去除噪声的思路
img=cv2.imread('./xhx.jpg')
kernel=cv2.getStructuringElement(cv2.MORPH_RECT,(3,3))
# #先腐蚀
# dst=cv2.erode(img,kernel,iterations=2)
# #膨胀
# dst=cv2.dilate(dst,kernel,iterations=2)
#调用opencv提供的api
dst=cv2.morphologyEx(img,cv2.MORPH_OPEN,kernel,iterations=2)
cv2.imshow('img',np.hstack((img,dst)))
cv2.waitKey(0)
cv2.destroyAllWindows()
闭运算
#闭运算=膨胀+腐蚀
import cv2
import numpy as np
#开运算=腐蚀+膨胀
#闭运算可以去除图形内部的噪声
img=cv2.imread('./xh.jpg')
kernel=cv2.getStructuringElement(cv2.MORPH_RECT,(3,3))
#调用opencv提供的api
dst=cv2.morphologyEx(img,cv2.MORPH_CLOSE,kernel,iterations=2)
cv2.imshow('img',np.hstack((img,dst)))
cv2.waitKey(0)
cv2.destroyAllWindows()
膨胀操作
膨胀是腐蚀的相反操作,基本原理是只要保证卷积核的锚点是非零值,周边无论是0还是非0值,都会变成非零值
import cv2
import numpy as np
#导入图片
img=cv2.imread('./xhx.jpg')
#获取卷积核
kernel=cv2.getStructuringElement(cv2.MORPH_CROSS,(5,5))
#膨胀
dst=cv2.dilate(img,kernel,iterations=1)
cv2.imshow('big2',np.vstack((img,dst)))
cv2.waitKey(0)
cv2.destroyAllWindows()
形态学梯度和顶帽黑帽操作
梯度=原图-腐蚀
#腐蚀之后原图边缘变小了,原图-腐蚀就可以得到腐蚀掉的部分,即边缘
import cv2
import numpy as np
img=cv2.imread('./xh.jpg')
kernel=cv2.getStructuringElement(cv2.MORPH_RECT,(3,3))
#调用opencv提供的api
dst=cv2.morphologyEx(img,cv2.MORPH_GRADIENT,kernel,iterations=1)
cv2.imshow('img',np.hstack((img,dst)))
cv2.waitKey(0)
cv2.destroyAllWindows()
顶帽=原图-开运算
#开运算的效果是去除图像外的噪点,原图-开运算就得到了去掉的噪点。
import cv2
import numpy as np
img=cv2.imread('./xh.jpg')
kernel=cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))
#调用opencv提供的api
dst=cv2.morphologyEx(img,cv2.MORPH_TOPHAT,kernel,iterations=3)
cv2.imshow('img',np.hstack((img,dst)))
cv2.waitKey(0)
cv2.destroyAllWindows()
黑帽=原图-闭运算
#闭运算可以将图形内部的噪点去掉,那么原图-闭运算的结果就是图形内部的噪点
import cv2
import numpy as np
img=cv2.imread('./xh.jpg')
kernel=cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))
#调用opencv提供的api
dst=cv2.morphologyEx(img,cv2.MORPH_BLACKHAT,kernel,iterations=3)
cv2.imshow('img',np.hstack((img,dst)))
cv2.waitKey(0)
cv2.destroyAllWindows()
标签:kernel,img,dst,cv2,形态学,OpenCV,import,np,操作
From: https://blog.csdn.net/m0_66464341/article/details/139707948