OpenCV提供许多边缘检测滤波函数,包括Laplacian()、Sobel()以及Scharr(),这些滤波函数都会将非边缘区域转为黑色,将边缘区域转为白色或其它饱和颜色,但是这些函数很容易将噪声识别为边缘。缓解这个问题的方法就是边缘检测之前,对图像进行模糊处理。
OpenCV提供了很多模糊滤波函数,包括blur()(简单算术平均)、medianBlur()(中值滤波)以及GaussianBlur()(高斯滤波)等。尽管边缘检测滤波函数和模糊滤波函数的参数由很多,但总会有一个ksize参数,它是一个奇数,表示滤波核的宽和高(以像素为单位)。
(1) 中值滤波器:
中值滤波对消除椒盐噪声非常有效,能够克服线性滤波器带来的图像细节模糊等弊端,能够有效保护图像边缘信息,是非常经典的平滑噪声处理方法。在光学测量条纹图像的香味分析处理方法中有特殊作用,但在条纹中心分析方法中作用不大。
(2) Laplacian边缘检测函数
dst = cv2.Laplacian(src, ddepth[, dst[, ksize[, scale[, delta[, borderType]]]]])
前两个是必须的参数:
第一个参数是需要处理的图像;
第二个参数是图像的深度,-1表示采用的是与原图像相同的深度。目标图像的深度必须大于等于原图像的深度;
其后是可选的参数:
dst不用解释了;
ksize是算子的大小,必须为1、3、5、7。默认为1。
scale是缩放导数的比例常数,默认情况下没有伸缩系数;
delta是一个可选的增量,将会加到最终的dst中,同样,默认情况下没有额外的值加到dst中;
borderType是判断图像边界的模式。这个参数默认值为cv2.BORDER_DEFAULT。
应用举例:
main.py 内容:def strokeEdges(src,blurKsize=7, edgeKsize=5):
if blurKsize >= 3:
#中值滤波
blurredSrc = cv2.medianBlur(src, blurKsize)
#转换为彩色图像转换为灰度图像
graySrc = cv2.cvtColor(blurredSrc, cv2.COLOR_BGR2GRAY)
else:
graySrc = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
#Laplacian边缘检测函数
cv2.Laplacian(graySrc, cv2.CV_8U, graySrc, ksize = edgeKsize)
#在得到Laplacian()函数的结果后,需要将其转换成黑色边缘和白色背景的图像。然后
#将其归一化(使像素值在0-1之间),并乘以源图像以便将边缘变黑。
normalizedInverseAlpha = (1.0/255)*(255-graySrc)
#拆分通道为单通道,获取各个通道的灰度值
channels = cv2.split(src)
for channel in channels:
channel[:] = channel * normalizedInverseAlpha
#合并单通道为多通道
dst = cv2.merge(channels)
return graySrc,dst
img = cv2.imread("./00.png")
lapsrc,result = strokeEdges(img)
cv2.imshow("img",img)
cv2.imshow("lapsrc",lapsrc)
cv2.imshow("result",result)
cv2.waitKey()
cv2.destroyAllWindows()
运行结果:
(3) 定制内核做卷积
OpenCV预定义的许多滤波器(滤波函数)都会使用核。核即是一组权重,它决定如何通过邻近像素点来计算新的像素点。核也称为卷积矩阵,它对一个区域的像素做调和(mix up)或卷积运算。
通常基于核的滤波器(滤波函数)被称为卷积滤波器(滤波函数),卷积矩阵是一个二维数组,有奇数行、奇数列,中心元素对应于感兴趣的像素。
如:kernel = numpy.array([[-1, -1, -1],
[-1, 9, -1],
[-1, -1, -1]])
感兴趣的像素权重为9,其邻近像素权重为-1。对于感兴趣的像素来说,新像素值是用当前像素值乘以9.然后减去8个邻近像素值。
应用举例:
filters.py 内容:#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sat Apr 7 22:58:11 2018
@author: lu
"""
import cv2
import numpy
#一般的卷积滤波器
class VConvolutionFilter(object):
def __init__(self, kernel):
self._kernel = kernel
def apply(self, src):
dst = cv2.filter2D(src, -1, self._kernel)
return dst
#特定锐化滤波器,权重和为1
class SharpenFilter(VConvolutionFilter):
def __init__(self):
kernel = numpy.array([[-1, -1, -1],
[-1, 9, -1],
[-1, -1, -1]])
VConvolutionFilter.__init__(self, kernel)
#边缘检测核,把边缘转化为白色,非边缘转为黑色,权重和为0
class FindEdgesFilter(VConvolutionFilter):
def __init__(self):
kernel = numpy.array([[-1, -1, -1],
[-1, 8, -1],
[-1, -1, -1]])
VConvolutionFilter.__init__(self, kernel)
#模拟滤波器,通常权重应该为1,而且邻近像素权重为正
class BlurFilter(VConvolutionFilter):
def __init__(self):
kernel = numpy.array([[0.04, 0.04, 0.04, 0.04, 0.04],
[0.04, 0.04, 0.04, 0.04, 0.04],
[0.04, 0.04, 0.04, 0.04, 0.04],
[0.04, 0.04, 0.04, 0.04, 0.04],
[0.04, 0.04, 0.04, 0.04, 0.04]])
VConvolutionFilter.__init__(self, kernel)
#同时具有模糊(正的权重)和锐化(负的权重),产生一种脊状或浮雕的效果
class EmbossFilter(VConvolutionFilter):
def __init__(self):
kernel = numpy.array([[-2, -1, 0],
[-1, 1, 1],
[ 0, 1, 2]])
VConvolutionFilter.__init__(self, kernel)
main.py 内容:import matplotlib.pyplot as plt
import cv2
import filters
#读取图像
img = cv2.imread("./00.png")
#特定锐化滤波器
filt = filters.SharpenFilter()
result1 = filt.apply(img)
#边缘检测滤波器
filt = filters.FindEdgesFilter()
result2 = filt.apply(img)
#模拟滤波器
filt = filters.BlurFilter()
result3 = filt.apply(img)
#模糊+锐化滤波器
filt = filters.EmbossFilter()
result4 = filt.apply(img)
plt.figure(figsize=(10,10)) #参数figsize设置画布大小
plt.subplot(221)
plt.title('SharpenFilter')
plt.imshow(result1)
plt.subplot(222)
plt.title('FindEdgesFilter')
plt.imshow(result2)
plt.subplot(223)
plt.title('BlurFilter')
plt.imshow(result3)
plt.subplot(224)
plt.title('EmbossFilter')
plt.imshow(result4)
plt.show()
运行结果:
(4) Canny边缘检测
OpenCV中提供了非常方便的边缘检测函数Canny,直接调用即可,近一步详细介绍访问这里。
cv2.Canny(image, threshold1, threshold2[, edges[, apertureSize[, L2gradient ]]])
必要参数:
第一个参数是需要处理的原图像,该图像必须为单通道的灰度图;
第三个参数是阈值2,一般用来检测图像中明显的边缘,但一般会出现断断续续的状况,需要结合调整第二个参数阈值1来将一些间断的边缘连接起来。
应用举例:
main.py 内容:img = cv2.imread("./00.png",0)
result = cv2.Canny(img, 200, 300)
cv2.imshow("Original",img)
cv2.imshow("Canny",result)
cv2.waitKey()
cv2.destroyAllWindows()
运行结果:
参考:
注意:本站所有文章除特别说明外,均为原创,转载请务必以超链接方式并注明作者出处。