【OpenCV_python】噪点消除(滤波) 边缘检测Canny算法 轮廓绘制

图片降噪

  1. 均值滤波blur
    中心点的像素值等于核值区域的平均值

import cv2
img_gs = cv2.imread('./media/lvbo2.png') # 高斯噪声
img_jy = cv2.imread('./media/lvbo3.png') # 椒盐噪声

def buler():
	img_jz1= cv2.blur(img_gs,(3,3))
    img_jz2= cv2.blur(img_jy,(3,3))
    cv2.imshow('img_jz1',img_jz1)
    cv2.imshow('img_jz2',img_jz2)

buler()

cv2.imshow('img_gs',img_gs)
cv2.imshow('img_jy',img_jy)

cv2.waitKey(0)

高斯噪声,比较均匀的噪点
椒盐噪声
在这里插入图片描述

在这里插入图片描述

  1. 方框滤波boxFilter
  • normalize=False 中心点的像素值等于核区域像素的总和
  • normalize=True 默认为True 就是均值滤波
    img_jz1 = cv2.boxFilter(img_gs,-1,(3,3),normalize=False )  # [图像]  [输出图像的深度,-1是原图像的深度]  [核的大小]
    img_jz2 = cv2.boxFilter(img_jy,-1,(3,3))
    cv2.imshow('img_jz1',img_jz1)
    cv2.imshow('img_jz2',img_jz2)

在这里插入图片描述
在这里插入图片描述

  1. 高斯滤波GaussianBlur
    核的权重取决于高斯函数并取近似值,对应的像素乘以权重相加得到中心点的像素值
    sigma的值 模糊效果越明显 (中心点的权重变小)
    g ( x , y ) = 1 2 π σ 2 e − ( x 2 + y 2 ) 2 σ 2 g(x,y)=\frac{1}{2\pi\sigma^{2}}e^{-\frac{(x^{2}+y^{2})}{2\sigma^{2}}} g(x,y)=2πσ21e2σ2(x2+y2)
    如3*3的核权重矩阵是[[1/16,1/8,1/16],[1/8,1/4,1/8],[1/16,1/8,1/16]]
    img_jz1 = cv2.GaussianBlur(img_jy,(3,3),10) # 图像 核大小   sigma的值  值越大 模糊效果越明显 
    img_jz2 = cv2.GaussianBlur(img_gs,(3,3),10)

在这里插入图片描述
在这里插入图片描述

  1. 中值滤波
    对核值大小范围内像素值排序,取中位数,对椒盐噪声和斑点效果较好,效率较低
    img_jz1 = cv2.medianBlur(img_gs,3)    # 图像 核大小
    img_jz2 = cv2.medianBlur(img_jy,3)  # 均值滤波

在这里插入图片描述
在这里插入图片描述

  1. 双边滤波

同时考虑像素点周围的点和像素值的大小

核值范围内每个像素点的权重值由位置的权重和像素值的权重相乘得到

ω ( i , j , k , l ) = w s ∗ w r \omega(i,j,k,l)=w_{s}*w_{r} ω(i,j,k,l)=wswr
空间位置的权重值
ω s = e − ( i − k ) 2 + ( j − l ) 2 2 σ s 2 \omega_{s}=e^{-{\frac{(i-k)^{2}+(j-l)^{2}}{2\sigma_{s}{}^{2}}}} ωs=e2σs2(ik)2+(jl)2
像素值大小得到的权重
ω r = e − ∥ f ( i , j ) − f ( k , l ) ∥ 2 2 σ r 2 \omega_{r}=e^{-{\frac{\|f(i,j)-f(k,l)\|^{2}}{2\sigma_{r}{}^{2}}}} ωr=e2σr2f(i,j)f(k,l)2

    img_jz1 = cv2.bilateralFilter(img_gs,9,70,70)
    img_jz2 = cv2.bilateralFilter(img_jy,9,70,70)

在这里插入图片描述
在这里插入图片描述

边缘检测

  1. Sobel 算子
    k = [ − 1 0 1 − 1 0 1 − 1 0 1 ] k=\left[{\begin{array}{r r r}{-1}&{0}&{1}\\ {-1}&{0}&{1}\\ {-1}&{0}&{1}\end{array}}\right] k= 111000111
    boder_x = cv2.Sobel(img_nut,-1,1,0)  # x方向的梯度,就是y方向的边缘
    boder_y = cv2.Sobel(img_nut,-1,0,1)  # y方向的梯度
    
    cv2.imshow('boder_x',boder_x)
    cv2.imshow('boder+y',boder_y)

在这里插入图片描述

  1. Scharr算子
    k = [ − 3 0 3 − 10 0 10 − 3 0 3 ] k=\left[{\begin{array}{r r r}{-3}&{0}&{3}\\ {-10}&{0}&{10}\\ {-3}&{0}&{3}\end{array}}\right] k= 31030003103
    boder_x = cv2.Scharr(img_nut,-1,1,0)
    boder_y = cv2.Scharr(img_nut,-1,0,1)

在这里插入图片描述

  1. Laplacian算子
    k = [ 1 1 1 1 − 8 1 1 1 1 ] k=\left[\begin{array}{c c c}{1}&{1}&{1}\\ {1}&{-8}&{1}\\ {1}&{1}&{1}\end{array}\right] k= 111181111
boder = cv2.Laplacian(img_nut,-1)

在这里插入图片描述

  1. Canny边缘检测
    边缘的像素值和周围的像素值有着其差异,表现为较大的像素差值,通过这个特点找到图像的边缘
    Canny边缘检测步骤
    4.1 读取图像
    4.2 二值化图像
    4.3 高斯滤波
    4.4 计算图像的梯度和方向

    • 图像梯度
      • 通过算子也就是特定的核(矩阵)对图像进行运算,从而得到图像像素值的变化值。也就是对图像做差分,得到图像的梯度。梯度的大小,描述了图像像素值的变化程度
    • Canny中使用Subol算子对x反向和y方向进行求梯度
      • 两个方向的梯度相加取绝对值得到像素点的梯度
    • 通过反正弦函数求出梯度的方向
      • θ = arctan ⁡   ( G y G x ) \theta=\arctan\,({\frac{G_{\mathrm{y}}}{G_{x}}}) θ=arctan(GxGy)
      • 为了简化计算统一角度值,对角度进行插值,指定范围的角度统一到同一个角度
        在这里插入图片描述

    4.5 非极大值抑制

    • 得到图像每个像素点的梯度值和方向,通过在比较同方向的相邻像素点的梯度值,(梯度方向和边缘的方向垂直)保留最大的像素值,不是最大的就舍去,可以去掉一些不是边缘的像素点
      • 比较的像素点是梯度方向指向的领域内的像素点,确保得到的是局部最大值

    4.6 双阈值筛选

    • 通过指定两个阈值,去掉一些弱边缘
    • 大于高阈值,就是强边缘点
    • 小于低阈值就不是边缘点
    • 介于两者之间,弱边缘点
    • 根据连通性判断 是否保留,如果弱边缘点和强边缘有连通性,就保留弱边缘
    boder = cv2.Canny(img_nut,60,120) # 图像 低阈值  高阈值

在这里插入图片描述

绘制图像轮廓

  1. 寻找图像轮廓
    contours,hierarchy = cv2.findContours(image,mode,method)

contours 返回轮廓点的列表,子列表的格式就是轮廓的个数
hierarchy 轮廓的关系
mode:轮廓的搜索模式

  • RETR_LIST所有轮廓
  • RETE_EXTERNAL最外层轮廓
  • RETE_-CCOMP列出所有轮廓
  • RETR_TREE所有轮廓

method:对轮廓点的存储方式

  • CHAIN_APPROX_NONE表示将所有的轮廓点都进行存储;

  • CHAIN_APPROX_SIMPLE只存储有用的点 默认使用这个方法;

  • CHAIN_APPROX_TC89_L1减少轮廓中的冗余点,更加准确地表示轮廓的形状。

  • CHAIN_APPROX_TC89_L1是一种较为精确的轮廓逼近方法,适用于需要较高精度的轮廓表示的情况。

  1. 绘制轮廓
    cv2.drawContours(image, contours, contourIdx, color, thickness)
    图片,轮廓点,要绘制哪些轮廓,颜色,线条粗细
def contours():

    img_nut = cv2.imread('./media/nut.png')
    img_nut_gray = cv2.cvtColor(img_nut,cv2.COLOR_BGR2GRAY)
    nut_erzhi = cv2.adaptiveThreshold(img_nut_gray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY_INV,25,10)
    
    cv2.imshow('nut_erzhi',nut_erzhi)
     
    contours,h = cv2.findContours(nut_erzhi,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
    cv2.drawContours(img_nut,contours,-1,(255,0,0))
    cv2.imshow('nut',img_nut)
    
contours()
cv2.waitKey(0)

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值