@[TOC]
改变颜色空间
1. 转换颜色空间 cv2.cvtColor()
OpenCV中提供了100多种颜色空间,其实我们常用的也就那么三个,RGB、HSV、灰度图,HSV其实是一个用来描述颜色的很好的颜色空间,具体的原理请百度,转换颜色空间的方法就是cv2.cvtColor()
,代码如下:
1 | # 所有的颜色空间 |
2. 物体跟踪 cv2.inRange()
OpenCV官方教程中提供了以下的例子,用来在视频中实时地追踪指定颜色的物体(代码里是蓝色),方法就是上面讲到的HSV颜色空间,首先你需要找到你要追踪的颜色的下界和上界,然后利用cv2.inRange()
方法得到一张mask图片,再用mask和每一帧进行按位与操作即可,代码如下:
1 | def object_tracking(): |
效果如下:
当然,你也可以换一个颜色,==需要注意的是,OpenCV中HSV空间三个量依次对应的范围是0-179,0-255,0-255,如果用其他工具转换时需要变换到该范围下对应的值==,也可以通过下列的示例代码进行转换:
1 | green = np.uint8([[[0,255,0 ]]]) |
图像的阈值处理
1. 简单阈值处理 cv2.threshold()
所谓阈值处理,就是给定一个阈值,当像素值比指定阈值大或小时做相关的操作。==这个字念yu,不是fa==,方法签名为:cv2.threshold(src,thresh,maxval,type,dst=None)
,需要将的是OpenCV中提供的几种type:
- cv2.THRESH_BINARY:若像素值大于阈值,则置为maxval;否则置0
- cv2.THRESH_BINARY_INV:THRESH_BINARY的反转
- cv2.THRESH_TRUNC:若像素值大于阈值,则置为阈值;否则不变
- cv2.THRESH_TOZERO:小于阈值的部分置为0;其他不变
- cv2.THRESH_TOZERO_INV:THRESH_TOZERO的反转
示例代码如下:
1 | def thresh_ops(): |
效果如下:
遇到的问题
- mat is not a numerical tuple
出现这个问题的原因是 cv2.threshold()返回2个参数,我开始想当然的认为只返回一个,于是最开始直接用cv2.imshow(“winName”,thresh1)的时候就报错了。添加一个占位返回参数即可。
2. 自适应阈值处理 cv2.adaptiveThreshold()
自适应阈值处理和简单处理略有不同,该方法会在一定的区域内(比如5*5)进行一次阈值计算,计算的方法可以是直接求均值、weighted mean,然后再根据该阈值在指定的区域内进行简答阈值化操作。方法签名为:cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C, dst=None)
。
- Adaptive Method :处理方法
- cv2.ADAPTIVE_THRESH_MEAN_C : 阈值为邻域内像素的均值
- cv2.ADAPTIVE_THRESH_GAUSSIAN_C : 阈值为邻域内像素的权重均值,权重是一个高斯窗口
- Block Size :邻域大小
- C - 计算阈值后固定减去的值
代码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17def adaptive_thresh_ops():
img = cv2.cvtColor(cv2.imread("bear.jpg"), cv2.COLOR_BGR2GRAY)
ret, th1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
th2 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, \
cv2.THRESH_BINARY, 11, 2)
th3 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, \
cv2.THRESH_BINARY, 11, 2)
titles = ['Original Image', 'Global Thresholding (v = 127)',
'Adaptive Mean Thresholding', 'Adaptive Gaussian Thresholding']
images = [img, th1, th2, th3]
for i in range(4):
plt.subplot(2, 2, i + 1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]), plt.yticks([])
plt.show()
效果如下:
平滑处理
1. 添加椒盐噪音
椒盐噪声也称为脉冲噪声,是图像中经常见到的一种噪声,它是一种随机出现的白点或者黑点,可能是亮的区域有黑色像素或是在暗的区域有白色像素。椒盐噪声的成因可能是影像讯号受到突如其来的强烈干扰而产生、模数转换器或位元传输错误等。例如失效的感应器导致像素值为最小值,饱和的感应器导致像素值为最大值。
说直白一点,就是会出现一些随机的黑白点,即所谓的salt&pepper noise。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33def add_salt_and_pepper_nosie(image, num):
"""
给图片添加椒盐噪音,num是噪声点的个数
:param image:
:param num:
:return:
"""
img = copy.deepcopy(image)
if len(img.shape) == 3:
rows, cols = img.shape[:2]
else:
rows, cols = img.shape
# add pepper noise
for n in range(num):
i = random.randint(0, rows - 1)
j = random.randint(0, cols - 1)
if len(img.shape) == 3:
img[i, j, :] = [255, 255, 255]
else:
img[i, j] = 255
# add salt noise
for n in range(num):
i = random.randint(0, rows - 1)
j = random.randint(0, cols - 1)
if len(img.shape) == 3:
img[i, j, :] = [0, 0, 0]
else:
img[i, j] = 0
return img
效果:
2. 去噪
主要是用OpenCV提供的各种滤波器在图像上进行卷积运算,以下分别是一些常用滤波器对椒盐噪音图像滤波的效果:
代码:
1 | def smoothing_ops(img): |
形态转变
形态转变一般用在二值图上,需要两个输入,①待处理的图像 ②处理图片的kernel (在OpenCV中被称为 structuring element )
1. 腐蚀操作
腐蚀操作的原理如下:
有一个slide window(类似卷积核的概念)在原图像上进行滑动,如果该滑动窗口中所有的像素值都为1,则生成的图像在此处的像素点为1;否则为0。更清楚的英文解释如下:
The kernel slides through the image (as in 2D convolution). A pixel in the original image (either 1 or 0) will be considered 1 only if all the pixels under the kernel is 1, otherwise it is eroded (made to zero).
2.扩张操作
扩张操作则和腐蚀操作相反,在腐蚀中,必须所有在滑动窗口在像素全为1才为1,而在扩张中,则是至少有一个像素在滑动窗口中是1.
It is just opposite of erosion. Here, a pixel element is ‘1’ if atleast one pixel under the kernel is ‘1’. So it increases the white region in the image or size of foreground object increases.
在二值图中,我们假定前景全为白色(取值为1),一种直观的理解是,腐蚀操作相当于把白色的像素减少了,一定程度上达到了去噪的效果;扩张操作则是增加了白色的像素,相当于恢复了边缘像素的信息。
试想,如果在图片的某些区域内有一些白色的噪点,通过腐蚀操作就可以消除他们,可腐蚀操作又可能把边缘的一些白色像素抹去,请看下面这张图,像这些边界上的白色像素就会被腐蚀掉。
于是,我们先腐蚀,再扩张,一定程度上也可以达到去噪的效果。这也就是所谓的==Opening操作==
代码如下:
1 | def morphological_ops(): |
3. 腐蚀+扩张(opening操作)
直接用下面这行代码,效果和先腐蚀,再膨胀一样。1
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
4. 扩张+腐蚀(closing操作)
opening的逆操作,可以用来消除图像中的一些黑点噪声。
1 | closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel) |
5. 梯度运算
1 | gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel) |
6. OpenCV内置函数生成structuring element
上述都是我们手动用numpy生成了一个5*5的kernel,有时候我们可能需要多种类型的kernel,也可以用内置函数cv2.getStructuringElement().
来生成kernel,OpenCV中的术语为structuring element 。
1 | # Rectangular Kernel |