OpenCv入门笔记(3)

图像梯度-Sobel算子

 

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBALeadjumilg==,size_20,color_FFFFFF,t_70,g_se,x_16

图中黑色部分像素值为0,白色部分像素值为255,则黑白交界处边缘处就存在梯度。

但是在像素点层面上如何进行梯度的计算呢?

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkAt5p2O6aKW,size_20,color_FFFFFF,t_70,g_se,x_16

 

在进行梯度计算时要考虑两个方向:水平和竖直

dst = cv2.Sobel(src, ddepth, dx, dy, ksize)    
ddepth:图像的深度
dx和dy分别表示水平和竖直方向
ksize是Sobel算子的大小,代表指定的核的大小。

img=cv2.imread('pie.png',cv2.IMREAD_GRAYSCALE)
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)

cv_show(sobelx,'sobelx')

白到黑是整数,黑到白就是负数了,所有的负数都会被截断成0,所以要取绝对值。

第一次检测的结果(只有边界上会有梯度):

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBALeadjumilg==,size_20,color_FFFFFF,t_70,g_se,x_16

 

但是只有左半部分,没有右半部分。 因为右边相减是负数,被截断成了0,黑色显示不出来。

sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
sobelx = cv2.convertScaleAbs(sobelx)
sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)
sobely = cv2.convertScaleAbs(sobely)  
sob=np.hstack((sobelx,sobely))
cv_show(sob,"sob")

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBALeadjumilg==,size_20,color_FFFFFF,t_70,g_se,x_16

 

在进行了取绝对值操作后,我们可以看到下边的效果图中右半部分显出来了。

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

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBALeadjumilg==,size_20,color_FFFFFF,t_70,g_se,x_16

 可以看出,sobelx与sobely分开算效果更加完美。

图像梯度-Scharr算子

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBALeadjumilg==,size_20,color_FFFFFF,t_70,g_se,x_16

图像梯度-laplacian算子

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBALeadjumilg==,size_12,color_FFFFFF,t_70,g_se,x_16

 不同算子的差异(代码):

img = cv2.imread('lena.jpg',cv2.IMREAD_GRAYSCALE)

sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)

sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)

sobelx = cv2.convertScaleAbs(sobelx)   

sobely = cv2.convertScaleAbs(sobely)  

sobelxy = cv2.addWeighted(sobelx,0.5,sobely,0.5,0)  

 

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((sobelxy,scharrxy,laplacian))

cv_show(res,'res')

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBALeadjumilg==,size_20,color_FFFFFF,t_70,g_se,x_16

 

 从左到右分别是Sobel、Scharr、Laplacian不同算子的效果图。

可以看出Scharr要比Sobel显示的边缘更加多,而Laplacian就显示的更加少了。

 

Canny边缘检测

使用高斯滤波器,以平滑图像,滤除噪声。

 

计算图像中每个像素点的梯度强度和方向。

 

应用非极大值(Non-Maximum Suppression)抑制,以消除边缘检测带来的杂散响应。

应用双阈值(Double-Threshold)检测来确定真实的和潜在的边缘。

通过抑制孤立的弱边缘最终完成边缘检测。

1:高斯滤波器

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBALeadjumilg==,size_20,color_FFFFFF,t_70,g_se,x_16

 2.梯度和方向

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBALeadjumilg==,size_20,color_FFFFFF,t_70,g_se,x_16

  3.非极大值抑制

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBALeadjumilg==,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBALeadjumilg==,size_20,color_FFFFFF,t_70,g_se,x_16 4.双阈值检测

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBALeadjumilg==,size_20,color_FFFFFF,t_70,g_se,x_16

 img=cv2.imread("lena.jpg",cv2.IMREAD_GRAYSCALE)

v1=cv2.Canny(img,80,150)

v2=cv2.Canny(img,50,100)

res = np.hstack((v1,v2))

cv_show(res,'res')

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBALeadjumilg==,size_20,color_FFFFFF,t_70,g_se,x_16

 

 可以通过改变最大值和最小值来进行调整参数。

 

图像金字塔

高斯金字塔

拉普拉斯金字塔

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBALeadjumilg==,size_20,color_FFFFFF,t_70,g_se,x_16

 高斯金字塔:向下采样方法(缩小)

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBALeadjumilg==,size_20,color_FFFFFF,t_70,g_se,x_16

 高斯金字塔:向上采样方法(放大)

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBALeadjumilg==,size_20,color_FFFFFF,t_70,g_se,x_16

 

img=cv2.imread("AM.png")
print (img.shape)
up=cv2.pyrUp(img)
print (up.shape)
down=cv2.pyrDown(img)
print (down.shape)


(442, 340, 3)
(884, 680, 3)
(221, 170, 3)
pyrUp()放大图像,空白的像素点补0.
pyrDown()缩小图像,将奇数行和列去掉。
放大缩小后会比原图像模糊,因为有像素值丢失。
拉普拉斯金字塔

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBALeadjumilg==,size_20,color_FFFFFF,t_70,g_se,x_16

 

down=cv2.pyrDown(img)
down_up=cv2.pyrUp(down)
l_1=img-down_up
cv_show(l_1,'l_1')

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

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBALeadjumilg==,size_20,color_FFFFFF,t_70,g_se,x_16

 

 

img = cv2.imread('contours.png')
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)
#传入绘制图像,轮廓,轮廓索引,颜色模式,线条厚度
# 注意需要copy,要不原图会变。。。
draw_img = img.copy()
res = cv2.drawContours(draw_img, contours, -1, (0, 0, 255), 2)#-1表示显示所有轮廓,123表示第123个轮廓
cv_show(res,'res')

轮廓特征:
cnt = contours[0]
#面积
cv2.contourArea(cnt)
#周长,True表示闭合的
cv2.arcLength(cnt,True)
轮廓近似:
轮廓近似,用最少的线来代替,在几个点之间的直线,如果能用更少的点来表示,就采用更少的点。

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBALeadjumilg==,size_20,color_FFFFFF,t_70,g_se,x_16

 

 

epsilon = 0.15*cv2.arcLength(cnt,True) #主要进行调参的函数
approx = cv2.approxPolyDP(cnt,epsilon,True)

draw_img = img.copy()
res = cv2.drawContours(draw_img, [approx], -1, (0, 0, 255), 2)
cv_show(res,'res')

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBALeadjumilg==,size_19,color_FFFFFF,t_70,g_se,x_16

 

 图中白色的是原图像,红色的是轮廓近似。

边界矩形

img = cv2.imread('contours.png')

 

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)

binary, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

cnt = contours[0]

x,y,w,h = cv2.boundingRect(cnt)

img = cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)

cv_show(img,'img')

 

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBALeadjumilg==,size_20,color_FFFFFF,t_70,g_se,x_16

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值