一、图像梯度

1.1 Sobel算子

Sobel算子
dst=cv2.Sobel(src,ddepth,ds,dy,ksize)
释义:
ddepth:图像的深度(-1)
dx和dy分别表示水平和竖直方向
ksize:是Sobel算子的大小(3×3...)

def cv_show(img,name):
    cv2.imshow(name,img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

#cv2.CV_64F:位数更多,可以是负数了
#x=1,y=0 :算水平的(左右结构)右减左
soblex=cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
#convertScaleAbs:算负数的绝对值
soblex=cv2.convertScaleAbs(soblex)
cv_show(soblex,'test')

#cv2.CV_64F:位数更多,可以是负数了
#x=0,y=1 :算竖直的(上下结构)下减上
sobley=cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)
#convertScaleAbs:算负数的绝对值
sobley=cv2.convertScaleAbs(sobley)
cv_show(sobley,'test')

#图像融合显示
soblexy=cv2.addWeighted(soblex,0.5,sobley,0.5,0)
soblexy=cv2.convertScaleAbs(soblexy)
cv_show(soblexy,'test')

同时计算水平和竖直
不建议直接计算,不如分开计算再融合效果好

soblexy=cv2.Sobel(img,cv2.CV_64F,1,1,ksize=3)
soblexy=cv2.convertScaleAbs(soblexy)
cv_show(soblexy,'test')

1.2 Scharr算子

整体计算方式与Sobel算子一致,只不过核中数变大,边缘检测更细

 

1.3 laplacian算子

二阶导(一阶导的变化率),对变化更敏感,对噪音点敏感,但噪音点不是边界。

1.4 三个算子差异对对比

#三个算子差异对比
scharrx=cv2.Scharr(img,cv2.CV_64F,1,0)
scharry=cv2.Scharr(img,cv2.CV_64F,0,1)
scharrx=cv2.convertScaleAbs(scharrx)
scharry=cv2.convertScaleAbs(scharry)
scharrxy=cv2.addWeighted(scharrx,0.5,scharry,0.5,0)

laplacian=cv2.Laplacian(img,cv2.CV_64F)
laplacian=cv2.convertScaleAbs(laplacian)

res=np.hstack((soblexy,scharrxy,laplacian))
cv_show(res,'test')
#Scharr算子区分的边缘比Soble算子更多,laplacian算子检测出的噪音点更多

Scharr算子区分的边缘比Soble算子更多,laplacian算子检测出的噪音点更多

1.5 Canny边缘检测

        使用高斯滤波器,平滑图像,滤除噪声
        计算图像中每个像素点的梯度强度和方向
        应用非极大值抑制,以消除边缘检测带来的杂散效应
        应用双阈值检测来确定真实的和潜在的边缘(对边界候选值再进行过滤,找到真实的边界)
        通过抑制孤立的弱边缘最终完成边缘检测(抛弃弱边缘,留主边缘)

1.5.1 高斯滤波器

1.5.2 梯度和方向(采用的Sobel算子)

 

1.5.3 非极大值抑制

 方法一:

 方法二:

1.5.4 双阈值检测

 代码实现:

#minvalues,maxvalues分别为两个阈值,阈值越大,过滤的边缘越多,展示的越少
canny1=cv2.Canny(img,80,150)
canny2=cv2.Canny(img,50,100)
res=np.hstack((canny1,canny2))
cv_show(res,'test')

二、图像金字塔

2.1 高斯金字塔

2.1.1 向下采样(缩小)

 2.1.2 向上采样(放大)

 代码实现:

#下采样
down=cv2.pyrDown(img)
cv_show(down,'down')


#上采样
up=cv2.pyrUp(img)
cv_show(up,'up')
print(up.shape)

2.2  拉普拉斯金字塔

 原始图像-(原始图像.Down).Up

代码实现:

#拉普拉斯金字塔
#原始图像-(原始图像.Down).Up
down=cv2.pyrDown(img)
down_up=cv2.pyrUp(down)
lapla=img-down_up
lapla_inv=img-lapla
cv_show(lapla,'lapla')

三、图像轮廓

cv2.findContours(img,mode,method)
mode:轮廓检索模式
    RETR_EXTERNAL:只检测最外面的轮廓
    RETR_LIST:检索所有轮廓,并将其保存到一条链表中
    RETR_CCOMP:检索所有轮廓,并将它们组织为两层,顶层是各部分的外部边界,二层是空洞的边界
    RETR_TREE(最常用,最好用):检索所有轮廓,并重构嵌套轮廓的整个层次
method:轮廓逼近方法
    CHAIN_APPROX_NONE:以Freeman链码的方式输出轮廓,所有其他方法输出多边形(顶点的序列)
    CHAIN_APPROX_SIMPLE:压缩水平的,垂直和斜的部分,也就是,函数只保留它们的终点部分

3.1 绘制轮廓

#先将图像转换成灰度图
img=cv2.imread('pic.jpg')
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#转为二值图
#图像阈值:超过127取255,否则取0
ret,thresh=cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
cv_show(thresh,'test')

#三个返回值分别是:之前版本openCV返回值有img,最新版没有了,只有两个返回值
#contours:轮廓(array)  hierarchy:轮廓之间的关系(列表)(层级)
contours,hierarchy=cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
print(contours[0])#打印出第一个轮廓的所有点的坐标, 更改此处的0,为0--(总轮廓数-1),可打印出相应轮廓所有点的坐标
print(hierarchy) #打印出相应轮廓之间的关系

#绘制轮廓(注:注意复制原图,drawContours会保存图像)(新版openCV修改了此BUG)
new_thresh=thresh.copy()
#传入参数,图像、轮廓坐标、索引(-1为所有轮廓坐标)、颜色模式、线条厚度
res=cv2.drawContours(new_thresh,contours,-1,(0,0,255),5)
cv_show(res,'res')

3.1 轮廓特征

3.1.1 面积

#轮廓特征
#面积
cnt=contours[0]
cv2.contourArea(cnt)

3.1.2 周长

#周长(True表示闭合的)
cv2.arcLength(cnt,True)

3.2 轮廓近似

#轮廓近似
img=cv2.imread('pic.jpg')
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret,thresh=cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
contours,hierarchy=cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
cnt=contours[0]
draw_img=img.copy()
res=cv2.drawContours(draw_img,[cnt],-1,(0,0,255),5)
cv_show(res,'res')

#近似值,一般为周长的十分之一
epsilon=0.1*cv2.arcLength(cnt,True)
#近似后新轮廓坐标,cnt:原轮廓坐标,epslion:近似值
approx=cv2.approxPolyDP(cnt,epsilon,True)
draw_img=img.copy()
res=cv2.drawContours(draw_img,[approx],-1,(0,0,255),5)
cv_show(res,'res')

3.3 外接矩形

#外接矩形
#通过原始轮廓信息计算返回一个四个值:x,y,w,h
x,y,w,h=cv2.boundingRect(cnt)
#cv2.rectangle:通过x,y,w,h绘制轮廓的函数
img=cv2.rectangle(draw_img,(x,y),(x+w,y+h),(0,255,0),2)
cv_show(img,'test')

#原轮廓面积与外接矩形占比
area=cv2.contourArea(cnt)#原轮廓面积
new_area=w*h
extent=float(area)/new_area

3.4 外接圆

#外接圆
#通过原始轮廓计算返回外接圆的参数
x,y,radius=cv2.minEnclosingCircle(cnt)
#设置圆心坐标
center=(int(x),int(y))
#转成int型
radius=int(radius)
#绘制
img=cv2.circle(draw_img,center,radius,(0,255,0),2)
cv_show(img,'img')
Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐