1 不同色彩空间的转换
opencv 中有数百种关于不同色彩空间的转换方法,但常用的有三种色彩空间:灰度、BRG、HSV(Hue-Saturation-Value)
- 灰度 - 灰度色彩空间是通过去除彩色信息来将其转换成灰阶,灰度色彩空间对中间处理特别有效,比如人脸检测
- BGR - 蓝-绿-红 彩色空间,每个像素点都由一个三元数组来表示,分别代表蓝-绿-红三种颜色。
- HSV,Hue 表示色调,Saturation 表示饱和度,Value 表示黑暗的程度。
2 傅里叶变换
傅里叶变换的概念是许多常见的图像处理操作的基础,比如边缘检测或线段和形状检测。
2.1 高通滤波器
高通滤波器(HPF)是检测图像的某个区域,然后根据像素与周围像素的亮度差值来提升(boost)该像素的亮度的滤波器。
高通滤波器在边缘检测非常有效,它会采用一种称为高频提升滤波器(high boost filter)的高通滤波器。
首先给出一个例子
import cv2 import numpy as np from scipy import ndimage kernel_3 = np.array([ [-1, -1, -1], [-1, 8, -1], [-1, -1, -1] ]) kernel_5 = 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('small.jpg', 0) print(help(cv2.imread)) k3 = ndimage.convolve(img, kernel_3) k5 = ndimage.convolve(img, kernel_5) blurred = cv2.GaussianBlur(img, (11, 11), 0) g_hpf = img - blurred cv2.imshow('3*3', k3) cv2.imshow('5*5', k5) cv2.imshow('g_hpf', g_hpf) cv2.waitKey() cv2.destroyAllWindows()
运行可以得到如下图:
代码分析:
1)导入模块后,定义了核。
核,是指一组权重的积核,将它应用在源图像的一个区域,并由此生成目标图像。详见4 用定制内核做卷积
2)在cv2.imread()中的参数 0 。主要是将其转换为单通道灰度图像。详见 OpenCV 学习笔记 02 处理文件、摄像头和图形用户界面
cv2.IMREAD_GRAYSCALE = 0 如果设置,则始终将图像转换为单通道灰度图像。
3)对于给定核与图像的“ 卷积 convole ” 而言,numpy 在多维数组卷积运算时较为复杂(一维数组完成可以胜任),scipy 的 convolve() 函数可解决完美地解决该问题。
4)最后一种高通滤波器的实现方法有两步;第一步对图像应用低通滤波器,第二步再对与原始图像计算差值。
5)不难发现,第三种效果最好。
2.2 低通滤波器
高通滤波器是根据像素与临近像素的亮度差值来提升该像素的亮度;
低通滤波器(Low Pass Filter, LPF)的实现原理是在像素与周围像素的亮度差值小于一个特定值时,平滑该像素的亮度。该法主要应用于去噪和模糊化;其中,高斯模糊是最常用的模糊滤波器(平滑滤波器)之一,它是一个削弱高频信号强度的低通滤波器。
3 边缘检测
opencv 提供了许多边缘检测滤波函数,包括有Laplacian()、Sobel()、Scharr()等,这些滤函数都会将非边缘区域转为黑色,将边缘区域转为白色或其他饱和的颜色,不过这些函数很容易将噪声错误地识别为边缘,缓解该问题的方法就是找到边缘之前对图像进行模糊处理。
- Laplacian() - 它会产生明显的边缘线条,灰度图更是如此
opencv 提供了许多模糊滤波函数,包括有blur()(简单的算术平均)、medianBlur()、GaussianBlur()等。
- medianBlur() - 对去除数字化的视频噪声非常有效,特别是去除彩色图像的噪声
边缘检测滤波函数和模糊滤波函数有必有一个参数 Ksize ,它是一个奇数,表示滤波核的宽和高(以像素为单位)。
注意:函数的使用顺序,模糊函数medianBlur() ---> 将图像从 BGR 色彩空间转为灰度色彩空间 ---> 边缘检测函数Laplacian() ---> 将图像转换成黑色边缘和白色背景的图像 ---> 将图像归一化处理(使它的像素值在0~1之间),并乘以源图像以便能将边缘变黑。
4 用定制内核做卷积
核也称为卷积矩阵,是一组权重,它作用于源图像的一个区域,并由此生成目标图像。
卷积矩阵的特点:
- 是一个二维数组
- 有奇数行、奇数列
- 元素值是整数或浮点数。
- 中心的元素对应于感兴趣的像素,其他元素对应于这个像素周围的临近像素
示例
kernel = numpy.array([ [-1, -1, -1], [-1, 9, -1], [-1, -1, -1]])
示例中感兴趣的像素权重为 9 ,其临近像素权重为 -1,当进行卷积计算时,对感兴趣的像素来说,新像素值是用当前像素值乘以9,然后减去8个临近像素值;以拉大该点像素值与临近像素值之间的差距,让图像更锐化。
opencv 提供了一个非常通用的 filter2D() 函数,它运用由用户指定的任意核或卷积矩阵。
filter2D(src, ddepth, kernel[, dst[, anchor[, delta[, borderType]]]]) -> dst
参数:
- src - 输入图像
- ddepth - 目标图像每个通道的位深度,若为负值,则表示目标图像与源图像由同样的位深度。位深度 cv2.CV_8U 表示每个通道为 8 位。
- kernel - 卷积核,单通道浮点矩阵,若要应用于不同的通道,需使用拆分将图像拆分为单独的颜色平面,然后单独处理它们。
- dst - 输出与 src 相同大小核相同通道的图像
- anchor - 内核的锚点,指示内核中过滤点的相对位置,锚应位于内核中,默认值(-1, -1),表示锚位于内核中心。
- delta - 在将它们存储在dst中之前,将可选值添加到已过滤的像素中。
- borderType - 像素外推法
对于多通道彩色图像来说,filter2D 会对每个通道都用同样的核,若每个通道都使用不同的核,则需用 split() 函数和 merge() 函数。
备注:
卷积核权重加起来为 1 ,则不会改变图像的亮度。可以达到模糊效果,
卷积核权重加起来为 0,则会使图像更加锐化。也可称之为边缘检测核,边缘转为白色,非边缘区域转为黑色。
5 Canny 边缘检测
opencv 提供了一个非常方便的 Canny 函数。
Canny 边缘检测算法非常复杂,共计有 5 个步骤。
使用高斯滤波器对图像进行去噪、计算梯度、在边缘上使用非最大抑制(NMS)、在检测到的边缘上使用双阈值去假阳性(false positive),最后还会分析所有的边缘及其之间的连接,以保证真正的边缘并消除不明显的边缘。
import cv2 img = cv2.imread('small.jpg', 0) cv2.imwrite('canny.jpg', cv2.Canny(img, 200, 300)) cv2.imshow('canny', cv2.imread('canny.jpg')) cv2.waitKey() cv2.destroyAllWindows()
运行
6 轮廓检测
轮廓检测不单是用来检测图像或者视频帧中物体的轮廓,而且还有计算多边形边界、形状逼近和计算感兴趣区域等与轮廓检测有关的操作。