阈值与平滑处理与腐蚀

图像阈值

ret, dst = cv2.threshold(src, thresh, maxval, type)
src: 输入图,只能输入单通道图像,通常来说为灰度图

dst: 输出图

thresh: 阈值

maxval: 当像素值超过了阈值(或者小于阈值,根据type来决定),所赋予的值

type:二值化操作的类型,包含以下5种类型: cv2.THRESH_BINARY; cv2.THRESH_BINARY_INV; cv2.THRESH_TRUNC; cv2.THRESH_TOZERO;cv2.THRESH_TOZERO_INV

cv2.THRESH_BINARY 超过阈值部分取maxval(最大值),否则取0

cv2.THRESH_BINARY_INV THRESH_BINARY的反转

cv2.THRESH_TRUNC 大于阈值部分设为阈值,否则不变

cv2.THRESH_TOZERO 大于阈值部分不改变,否则设为0

cv2.THRESH_TOZERO_INV THRESH_TOZERO的反转

ret, thresh1 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY)
ret, thresh2 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY_INV)
ret, thresh3 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TRUNC)
ret, thresh4 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TOZERO)
ret, thresh5 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TOZERO_INV)

titles = ['Original Image', 'BINARY', 'BINARY_INV', 'TRUNC', 'TOZERO', 'TOZERO_INV']
images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]

for i in range(6):
    plt.subplot(2, 3, i + 1), plt.imshow(images[i], 'gray')
    plt.title(titles[i])
    plt.xticks([]), plt.yticks([])
plt.show()

在这里插入图片描述

图像平滑

1 均值滤波

# 均值滤波
# 简单的平均卷积操作
blur = cv2.blur(img, (3, 3))

cv2.imshow('blur', blur)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述
均值滤波相当于 简单的平均卷积操作
上面代码则相当于与 用一个三乘三的元素都为1的数组来和 三乘以三的像素点数组进行 矩阵相乘
得到的结果除以9 即为这九个点的像素值

可用于处理椒盐滤波

2 方框滤波

# 方框滤波
# 基本和均值一样,可以选择归一化
box = cv2.boxFilter(img,-1,(3,3), normalize=True)  

cv2.imshow('box', box)
cv2.waitKey(0)
cv2.destroyAllWindows()


# 方框滤波
# 基本和均值一样,可以选择归一化,容易越界
box = cv2.boxFilter(img,-1,(3,3), normalize=False)  
#越界直接取255 
cv2.imshow('box', box)
cv2.waitKey(0)
cv2.destroyAllWindows()
#normalize=False 
#这时是3乘以3的像素点相加的值作为这九个点的像素值 
#没有进行平均化

3 高斯滤波

# 高斯滤波
# 高斯模糊的卷积核里的数值是满足高斯分布,相当于更重视中间的
aussian = cv2.GaussianBlur(img, (5, 5), 1)  

cv2.imshow('aussian', aussian)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述
在这里插入图片描述
相当于是三乘以三的像素点矩阵
乘 有权值的三乘三矩阵
并且高斯比较重视离他比较近的点 轻视离它比较远的点
在这里插入图片描述

4 中值滤波

# 中值滤波
# 相当于用中值代替
median = cv2.medianBlur(img, 5)  # 中值滤波

cv2.imshow('median', median)
cv2.waitKey(0)
cv2.destroyAllWindows()

腐蚀操作

相当于对图像进行侵蚀
腐蚀原理:

腐蚀:局部最小值(与膨胀相反);

①定义一个卷积核B,核可以是任何的形状和大小,且拥有一个单独定义出来的参考点 - 锚点(anchorpoint);

通常和为带参考点的正方形或者圆盘,可将核称为模板或掩膜;

②将核乙与图像甲进行卷积,计算核乙覆盖区域的像素点最小值;

③将这个最小值赋值给参考点指定的像素;

因此,图像中的高亮区域逐渐减小。

kernel = np.ones((3,3),np.uint8) 
erosion = cv2.erode(img,kernel,iterations = 1)
#进行一次迭代
cv2.imshow('erosion', erosion)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

膨胀操作

与腐蚀操作相反

kernel = np.ones((3,3),np.uint8) 
img_dilate = cv2.dilate(erosion,kernel,iterations = 1)

cv2.imshow('dilate', dige_dilate)
cv2.waitKey(0)
cv2.destroyAllWindows()

开运算与闭运算

# 开:先腐蚀,再膨胀
img = cv2.imread('dige.png')

kernel = np.ones((5,5),np.uint8) 
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)

cv2.imshow('opening', opening)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 闭:先膨胀,再腐蚀
img = cv2.imread('dige.png')

kernel = np.ones((5,5),np.uint8) 
closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)

cv2.imshow('closing', closing)
cv2.waitKey(0)
cv2.destroyAllWindows()

梯度

# 梯度=膨胀-腐蚀
pie = cv2.imread('pie.png')
kernel = np.ones((7,7),np.uint8) 
gradient = cv2.morphologyEx(pie, cv2.MORPH_GRADIENT, kernel)

礼帽与黑帽

#礼帽
img = cv2.imread('dige.png')
tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)
cv2.imshow('tophat', tophat)
cv2.waitKey(0)
cv2.destroyAllWindows()

#黑帽
img = cv2.imread('dige.png')
blackhat  = cv2.morphologyEx(img,cv2.MORPH_BLACKHAT, kernel)
cv2.imshow('blackhat ', blackhat )
cv2.waitKey(0)
cv2.destroyAllWindows()

图像梯度-Sobel算子

在这里插入图片描述

Gx 为x方向上的梯度
在这里插入图片描述
即用 p3-p1+p6-p4+p9-p7 这样就能表示出来左右之间的梯度
(Sobel 算子 和高斯相似 给离的近的点进行加权)

dst = cv2.Sobel(src, ddepth, dx, dy, ksize)

ddepth:图像的深度
dx和dy分别表示水平和竖直方向
ksize是Sobel算子的大小

sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
#cv2.CV_64F 是可以表示负数的一种数据类型
#dx=1 表示计算x方向上的梯度
cv_show(sobelx,'sobelx')

若 梯度算下来为负数则会产生截断 也就是负数最后当0处理
再在这个⚪ 作为原图的时候 x梯度结果是左边的半月牙 因为右边都当0了

#不建议一起计算xy的梯度 因为一起计算可能会影响效果
#可以分别计算再求和
sobelxy = cv2.addWeighted(sobelx,0.5,sobely,0.5,0)
cv_show(sobelxy,'sobelxy')

图像梯度-Scharr算子
对于边界更为敏感 (加权力度更大)
在这里插入图片描述

图像梯度-laplacian算子
在这里插入图片描述
不经常单独使用 因拉普拉斯对于噪音点太过敏感

Canny边缘检测

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

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

3 应用非极大值抑制,以消除边缘检测带来的杂散效应
(例如 相机中的人脸检测若有多个框都可以被识别成是人脸
,若一个框里面人脸的可能性最大,则选取它作为人脸)

4应用双阈值检测确定真实的和潜在的边缘

5通过抑制孤立的若边缘最终完成边缘检测

1高斯滤波器

在这里插入图片描述
2梯度和方向
在这里插入图片描述
3非极大值抑制
在这里插入图片描述
计算c点与上边交点设为 a 下边交点设为 b
若c点值梯度幅值 比 a与b 的梯度幅值都大 则c 可以保留下来
否则c点会被抑制掉

简化操作
在这里插入图片描述
离a点最近的两个点连成的方向
与 这八个方向哪一个更接近 则得到连线 计算a 点前后的梯度幅值 若比他们大则保留
注: 梯度方向与边缘方向是垂直的

双阈值
在这里插入图片描述

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

v1=cv2.Canny(img,80,150)
# 指定minvalue:80 和 maxvalue:150
v2=cv2.Canny(img,50,100)
# 检测出来的边界更加丰富

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

图像金字塔

高斯金字塔
拉普拉斯金字塔
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
上采样和下采样都会丢失图像的信息

# 上采样 
up=cv2.pyrUp(img)
#up方向是由大到小的方向
cv_show(up,'up')
print (up.shape)
# 图像会变大

在这里插入图片描述
拉普拉斯金字塔:
利用原始图像减去 (down后 再进行up的图像)

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:压缩水平的、垂直的和斜的部分,也就是,函数只保留他们的终点部分。

为了更高的准确率,使用二值图像。

img = cv2.imread('contours.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
cv_show(thresh,'thresh')
binary, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
# binary 二值图像
# counters 轮廓信息
# hierarchy 层级

#传入绘制图像,轮廓,轮廓索引,颜色模式,线条厚度
# 注意需要copy,要不原图会变。。。
draw_img = img.copy()
res = cv2.drawContours(draw_img, contours, -1, (0, 0, 255), 2)
# (0,0,255) 表示用红色来画出轮廓
cv_show(res,'res')

轮廓近似

原理简述 :
将弧线 ab 利用两条线段进行代替
若 距离d 小于阈值 则两条线段 ac和 cb为近似得到的轮廓
若 距离d 大于阈值 则重复上述步骤 找ac的近似轮廓

在这里插入图片描述

img = cv2.imread('contours2.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]

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

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')
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值