canny边缘检测算法 opencv_opencv学习手记(三)--模糊滤波与边缘检测

1.三种色彩空间

  • 灰度色彩空间
  • BGR,即蓝-绿-红色彩空间
  • HSV,H(Hue)是色调,S(Saturation)是饱和度,V(Value)表示黑暗的程度

2.傅里叶变换

  • 通过傅里叶变换来介绍图像的幅度谱(magnitude specturm),图像的幅度谱是另一种图像,幅度谱图像呈现了原始图像在变化方面的一种表示
  • 傅里叶变换的概念是许多常见的图像处理操作的基础,比如边缘检测或线段和形状检测。
  1. 高通滤波器
  • 高通滤波器(HPF)是检测图像的某个区域,然后根据像素与周围像素的亮度差值来提升该像素的亮度的滤波器。

以如下的核(kernel),即滤波器矩阵为例:

c6ae6e7d8e95d268e1fadaf2c9410523.png

注:核是指一组权重的集合,它会应用在源图像的一个区域,并由此生成目标图像的一个像素。比如,大小为7的核意味着每49(7x7)个源图像的像素会产生目标图像的一个像素。

  • 可把核看做一块覆盖在源图像上可移动的毛玻璃片,玻璃片覆盖区域的光线会按某种方式进行扩散混合后透过去。
  • 计算完中央像素与周围邻近像素的亮度差值之和以后,如果亮度变化很大,中央像素的亮度会增加,反之则不会。换句话说,如果一个像素比它周围的像素更突出,就会提升它的亮度。
  • 这在边缘检测上尤为有效,它采用一种称为高频提升滤波器(high boost filter)的高通滤波器。
  • 高通和低通滤波器都有一个半径(radius)的属性,它决定了多大面积的临近像素参与滤波运算。
import cv2
import numpy as np
from scipy import ndimage

'''
1.傅里叶变换
'''

'''
(1)高通滤波器
'''
kernel_3x3 = np.array([[-1,-1,-1],[-1,8,-1],[-1,-1,-1]]) 

kernel_5x5 = np.array([[-1,-1,-1,-1,-1],
                       [-1,-1, 2, 1,-1],
                       [-1, 2, 4, 2,-2],
                       [-1, 1, 2, 2,-1],
                       [-1,-1,-1,-1,-1]])


#读取图像,指定格式为灰度图像 
img = cv2.imread('./image/img6.jpg',cv2.IMREAD_GRAYSCALE)

#进行卷积运算
k3 = ndimage.convolve(img,kernel_3x3)
k5 = ndimage.convolve(img,kernel_5x5)
#模糊滤波
blurred = cv2.GaussianBlur(img,(11,11),0)
#作差
g_hpf = img - blurred


#显示图像
cv2.imshow('original',img)
cv2.imshow('3x3',k3)
cv2.imshow('5x5',k5)
cv2.imshow('g_hpf',g_hpf)
cv2.waitKey()
cv2.destroyAllWindows()

最后又用一种不同的方法来实现高通滤波器:通过对图像应用低通滤波器之后,与原始图像计算差值。这样得到的效果会更好。

2 低通滤波器

  • 高通滤波器是根据像素与邻近像素的亮度差值来提升该像素的亮度。低通滤波器(LPF)则是在像素与周围像素的亮度差值小于一定特征值,平滑该像素的亮度。它主要用于去噪和模糊化,比如说,高斯模糊是最常用的模糊滤波器(平滑滤波器)之一,它是削弱高频信号强度的低通滤波器。

3.边缘检测

def  strokeEdges(src,blurKsize=7,edgeKsize=5):
    '''
    该函数实现性能更好的边缘检测
    
    这里使用medianBlur()作为模糊函数,使用Laplacian()作为边缘检测函数。在使用medianBlur()之后,
    需要将图像从BGR色彩空间转换为灰度色彩空间。在得到Laplacian()函数结果之后,需要将图像转换为
    黑色边缘和白色背景(之前是白色边缘黑色背景)。然后将其归一化,并乘以源图像以便能将边缘变黑。
    
    args:
        src:源图像数据 BGR色彩空间       
        blurKsize:模糊滤波卷积核的宽和高  小于3,不进行模糊处理
        edgeKsize:边缘检测卷积核的宽和高  return:     dst:目标图像数据 灰度色彩空间
    '''
    if blurKsize >= 3:
        #先模糊处理
        blurredSrc = cv2.medianBlur(src,blurKsize)
        cv2.imshow('blurredSrc',blurredSrc)
        #BGR格式转化为灰度格式
        graySrc = cv2.cvtColor(blurredSrc,cv2.COLOR_BGR2GRAY)
    else:
        graySrc = cv2.cvtColor(src,cv2.COLOR_BGR2GRAY)
        
    cv2.imshow('graySrc',graySrc)
    #边缘检测 对灰度图像检测效果更好
    cv2.Laplacian(graySrc,cv2.CV_8U,graySrc,ksize = edgeKsize)
    cv2.imshow('laplacian',graySrc)
    
    #颜色反向处理 并归一化
    normalizedInverseAlpha = (1.0/255)*(255 - graySrc)
    cv2.imshow('normalizedInverseAlpha',normalizedInverseAlpha)
    
    #通道分离 B,G,R 单通道图像
    channels = cv2.split(src)
    cv2.imshow('B',channels[0])
    
    #计算后的结果分别与每个通道相乘
    for channel in channels:
        #这里是点乘,即对应元素相乘
        channel[:] = channel * normalizedInverseAlpha
            
    cv2.imshow('B1',channels[0])
    
    #通道合并(只能合并多个单通道成为多通道)
    return  cv2.merge(channels)
    
img = cv2.imread('./image/img6.jpg',cv2.IMREAD_COLOR)
dst = strokeEdges(img)
cv2.imshow('dst',dst)
cv2.waitKey()
cv2.destroyAllWindows()

  • Open CV提供了许多边缘检测滤波函数,包括以下:
  • Laplacian() #作为边缘检测函数,他会产生明显的边缘线条,灰度图像更是如此。 Sobel()
  • Scharr()
  • 这些滤波函数都会将非边缘区域转换为黑色,边缘区域转换成白色或其他饱和的颜色。但是这些函数都容易将噪声错误的识别为边缘。缓解这个问题的方法就是在找到边缘之前对图像进行模糊处理,去除噪声。
  • Open CV也提供了需要模糊滤波函数,包括以下:
  • blur()
  • medianBlur() #它对去除数字化的视频噪声特别有效,特别是去除彩色图像的噪声
  • GaussianBlur()
  • 边缘检测和模糊滤波的函数的参数有很多,但总会有一个ksize参数,它是一个奇数,表示滤波核的宽和高(以像素为单位)。

4.Canny边缘检测

Open CV还提供了一个非常方便的Canny()函数,该算法非常流行,不仅是因为它的效果,还因为在Open CV程序中实现时非常简单:

'''
Canny边缘检测
'''
can = cv2.Canny(img,200,300)
cv2.imshow('canny',can)


cv2.waitKey()
cv2.destroyAllWindows()
  • Canny边缘检测算法算法非常复杂,它有5个步骤,即使用高斯滤波器对图像进行去噪,计算梯度,在边缘上使用非最大抑制,在检测到的边缘上使用阈值去除假阳性,最后还会分析所有的边缘及其之间的连接,以保留真正的边缘并消除不明显的边缘。

cv2.Canny函数部分参数如下:

  • 第一个参数是需要处理的原图像,该图像必须是单通道的灰度图;
  • 第二个参数是阈值1。
  • 第三个参数是阈值2.

其中较大的阈值2用于检测图像中明显的边缘,但是一般情况下检测的效果不会那么完美,边缘检测出来是断断续续的。所以这时候较小的第一个阈值用于将这些断续的边缘连接起来。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值