形态学操作and图像梯度和Canny边缘检测


形态学


形态学操作一般情况下对二值化图像进行操作。需要输入两个参数,一个是原始图像,第二个为核,它是用来决定操作的性质的


 1、腐蚀操作

卷积核沿着图像滑动,如果与卷积核对应的原图像的所有像素值都是 1 ,那么中心元素就保持原来的像素值,否则就变为零

使用函数 cv2.erode( img , kernel , iterations )

        kernel : 核

        iterations :迭代次数,次数越多腐蚀越多

import cv2
import numpy as np
img = cv2.imread('kh.jpg')
kernel = np.ones((5,5),np.uint8)

erosion = cv2.erode(img,kernel,iterations = 3)    #腐蚀操作

res = np.hstack((img,erosion))
cv2.imshow('pic',res)


2、膨胀

与腐蚀相反,与卷积核对应的原图像的像素值中只要有一个是 1,中心元素的像素值就是 1。所以这个操作会增加图像中的白色区域。一般在去噪声时先用腐蚀再用膨胀

使用函数 cv2.dilate( img, kernel, iterations )        迭代次数越多越膨胀

import cv2
import numpy as np
img = cv2.imread('kh.jpg')
kernel = np.ones((5,5),np.uint8)

dilat = cv2.dilate(img,kernel,iterations = 3)    膨胀

res = np.hstack((erosion,dilat))
cv2.imshow('pic',res)


3、开运算与闭运算

开:先腐蚀再膨胀        常被用来去除噪声

闭:先膨胀再腐蚀        常被用来填充前景物体中的小洞或小黑点。

使用函数 cv2.morphologyEx( img , option , kernel)

        option:选择方式

                option = cv2.MORPH_OPEN          开

                option = cv2.MORPH_CLOSE         闭

开运算

import cv2
import numpy as np
img = cv2.imread('kh.jpg')
kernel = np.ones((5,5),np.uint8)

open = cv2.morphologyEx(img,cv2.MORPH_OPEN,kernel)    #开

res = np.hstack((img ,open))
cv2.imshow('open',res)
cv2.waitKey(0)
cv2.destroyAllWindows()

 闭运算

img = cv2.imread('kh.jpg')
kernel = np.ones((5,5),np.uint8)
close= cv2.morphologyEx(img,cv2.MORPH_CLOSE,kernel)

res = np.hstack((img ,close))
cv2.imshow('close',res)
cv2.waitKey(0)
cv2.destroyAllWindows()


4、梯度运算

梯度 = 膨胀  - 腐蚀

选择 cv2.MORPH_GRADIENT
img = cv2.imread('kh.jpg')
kernel = np.ones((5,5),np.uint8)

td= cv2.morphologyEx(img,cv2.MORPH_GRADIENT,kernel)

res = np.hstack((img ,td))
cv2.imshow('td',res)


5、礼帽与黑帽

        礼帽 =原始输入 - 开运算结果        选择:cv2.MORPH_TOPHAT

        黑帽 = 闭运算结果 - 原始输入         选择:cv2.MORPH_BLACKHAT

礼帽

img = cv2.imread('kh.jpg')
kernel = np.ones((5,5),np.uint8)

td= cv2.morphologyEx(img,cv2.MORPH_TOPHAT,kernel)

res = np.hstack((img ,td))
cv2.imshow('top',res)

 黑帽:

td= cv2.morphologyEx(img,cv2.MORPH_BLACKHAT,kernel)   #黑帽



图像梯度

梯度简单来说就是求偏导

1、Soble算子

3x3 Soble 滤波器卷积核如下

 使用函数 cv2.Sobel( img , depth , dx, dy, ksize)

        depth :图像的深度,指定-1,表示输入输出一样,但小于0边界会舍弃

                这两种边界都想检测到,最好的的办法就是将输出的数据类型设置的更高,取绝对值然后再把它转回到cv2.CV_8U

                cv2.CV_64F 输出图像的深度(数据类型)

        dx 和 dy 分别表示水平和竖直方向导数阶数

        ksize : Sobel 算子的大小,

                如果 ksize=-1,会使用 3x3 的 Scharr 滤波器,它的的效果要 比 3x3 的 Sobel 滤波器好

import cv2
import numpy as np
img = cv2.imread('kb.jpg')

sobel = cv2.Sobel(img,-1,1,0,ksize=3) ##参数1,0表示在x方向求一阶导数,最大可以求2阶导数

res = np.hstack((img ,sobel))
cv2.imshow('Sobel',res)
cv2.waitKey(0)
cv2.destroyAllWindows()


显示边界

img = cv2.imread('kb.jpg')

sobel = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3) #参数1,0表示在x方向求一阶导数,最大可以求2阶导数
sobel= cv2.convertScaleAbs(sobel)

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

res = np.hstack((img,sobel))
cv2.imshow('Sobel',res)


 求总和 G = | X方向梯度值 |  +   | Y方向梯度值 |

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


 不建议直接求和,应先求出x y各方向梯度再求和效果好

原图,分开求和,直接求和        效果如图


2、Scharr 算子 和 Laplacian 算子


3x3 的 Scharr 滤波器卷积核如下

 能够捕捉到更丰富的梯度信息

使用函数 cv2.Scharr( img , cv2.CV_64F, dx ,dy )        #用法和Sobel差不多


拉普拉斯滤波器使用的卷积核

 使用函数 cv2.Laplacian( img , cv2.CV64F )        #不用分别求梯度


三种算法差异

import cv2
import numpy as np
img = cv2.imread('op.jpg',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)
sobelxy = cv2.addWeighted(sobelx,0.5,sobely,0.5,0)

scharrx = cv2.Scharr(img,cv2.CV_64F,1,0)
scharrx = cv2.convertScaleAbs(scharrx)
scharry = cv2.Scharr(img,cv2.CV_64F,0,1)
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))
cv2.imshow('compare',res)
cv2.waitKey(0)
cv2.destroyAllWindows()

                 sobel                                           scharr                                          laplacian


Canny 边缘检测


1、使用高斯滤波器去除噪声


 2、计算图像梯度强度和方向

梯度的方向一般总是与边界垂直。梯度方向被归为四类:垂直,水平,和两个对角线


3、应用非极大值抑制

相当于找局部像素点最大值 ,中点的梯度方向为线条方向,局部的最大值肯定分布在这条线 ,就是相交的两点和C点比较,判断中点灰度与这两个点灰度大小即可判断中点是否为其邻域内的局部最大灰度,若中点不是局部极大值,排除此点为边缘,对应的灰度值置为0


4、双阈值检测

 minVal 和maxVal 指定越小,得到边界越丰富,反之越少


5、边缘检测效果

只需要一个函数 cv2.Canny( img,minVal,maxVal ) 即可完成
import cv2
import numpy as np
img = cv2.imread('op.jpg',0)

v1 = cv2.Canny(img,150,200)
v2 = cv2.Canny(img,80,130)

res = np.hstack((v1,v2))
cv2.imshow('compare',res)
cv2.waitKey(0)
cv2.destroyAllWindows()

 对人物

对物体 

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

onlywishes

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值