2. 使用OpenCV3处理图像
2.1 不同色彩空间的转换
OpenCV中有数百种关于在不同色彩空间之间转换的方法。
三种常用色彩空间:灰度、BGR、HSV(Hue色调,Saturation饱和度,Value亮度)
注:计算机遵从加色模型,而绘画遵从减色模型。
2.2 傅里叶变换
傅里叶变换作用:可以用来区分图像里哪些区域的信号变化特别强,哪些不那么强,
从而可以任意标记噪声区域、感兴趣区域、前景和背景。
幅度谱(magnitude spectrum):图像的幅度谱是另一种图像,幅度谱图像呈现了
原始图像在变化方面的一种表示:把一幅图像中最亮的像素放中间,然后逐渐变暗,
在边缘上的像素最暗。这样可以发现图像中有多少亮的像素和暗的像素,以及他们
分布的百分比。
2.2.1 高通滤波器(HPF)
知识准备:核是指一组权重的组合,它会应用的在源图像的一个区域,并由此产生目标图像的一个像素。
比如:大小为7的核意味着每49(7*7)个源图像的像素会产生目标图像的一个像素。
import cv2 import numpy as np from scipy import ndimage
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, -1], [-1, 1, 2, 1, -1], [-1, -1, -1, -1, -1]]) img = cv2.imread("../images/statue_small.jpg", 0) # 卷积运算 k3 = ndimage.convolve(img, kernel_3x3) k5 = ndimage.convolve(img, kernel_5x5) # 高斯模糊(一种低通滤波器) blurred = cv2.GaussianBlur(img, (17,17), 0) g_hpf = img - blurred cv2.imshow("3x3", k3) cv2.imshow("5x5", k5) cv2.imshow("g_hpf", g_hpf) cv2.waitKey() cv2.destroyAllWindows()
2.2.2 低通滤波器
高通滤波器是根据像素与邻近像素的亮度差值来提升该像素的亮度。
低通滤波器则是在像素与周围像素的亮度差值小于一个特定值时,平均该亮度的像素。
它主要用于去噪和模糊化,比如说,高斯模糊是最常用的模糊滤波器(平滑滤波器)之一,
它是一个削弱高频信号强度的低通滤波器。
2.3 创建模块
2.4 边缘检测
OpenCV提供了许多边缘检测滤波函数,包括Laplacian()、Sobel()以及Scharr()。这些
滤波函数都会将非边缘区域转换成黑色,将边缘区域转换成白色或者其它饱和的颜色。
但是,这些函数都很容易将噪声错误地识别为边缘。
缓解这个问题地办法是在找到边缘之前对图像进行模糊处理。
OpenCV提供了许多模糊滤波函数,包括blur()(简单地算术平均)、medianBlur()以及
GaussianBlur()。边缘检测滤波函数和模糊滤波函数的参数有很多,但总会有个ksize参数,
它是一个奇数,表示滤波核的宽和高(以像素为单位)。
这里使用medianBlur()作为模糊函数,它对去除数字化的视频噪声非常有效,特别是去除
彩色图像的噪声;使用Laplacian()作为边缘检测函数,它会产生明显的边缘线条,灰度图像
更是如此。在使用medianBlur()函数之后,将要使用Laplacian()函数之前,需要将图像从BGR
色彩空间转换为灰度色彩空间。
在得到Laplacian()函数的结果之后,需要将其转换成黑色边缘和背景的图像。然后将其
归一化(使它的像素值在0到1),并乘以源图像以便能使边缘变黑。
def strokeEdges(src, dst, 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) cv2.Laplacian(graySrc, cv2.CV_8U, graySrc, ksize = edgeKsize) normalizedInverseAlpha = (1.0/255)*(255-graySrc) channels = cv2.split(src) for channel in channels: channel[:] = channel*normalizedInverseAlpha cv2.merge(channels, dst)
注:对于较大的ksize(包括7),使用medianBlur()的代价很高。