OpenCV 学习笔记 02 使用opencv处理图像

时间:2024-01-01 15:47:09

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()

运行可以得到如下图:

OpenCV 学习笔记 02 使用opencv处理图像

代码分析:

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()

运行

OpenCV 学习笔记 02 使用opencv处理图像

6 轮廓检测

轮廓检测不单是用来检测图像或者视频帧中物体的轮廓,而且还有计算多边形边界、形状逼近和计算感兴趣区域等与轮廓检测有关的操作。