OpenCV中给出了很多种提取对象特征的方法。 从简单的图像色块>图像阈值分割>轮廓查找>特征点检测>直方图检测等等有很多。这些简单的方法看似没有什么实际的场景可以直接拿来使用,但是就学习的时候拿来学习学习是非常恰当的。 下面就按照颜色阈值的方式来查找图像中的蓝色物体,提取出对象的掩膜并进行覆盖。
色域转换
通常情况下,摄像机直接采集到的图像是RGB色域的(在Opencv中三通道色彩默认是BGR排列)。对于人的肉眼来说RGB色域是更好的选择,三色差别显著,但是对于计算机来说并不是很明显。相当于人眼观察时要一个颜色特征明显的色域空间,对于计算机来说通常使用HSV色域空间。在Opencv中可以很简单的实现色域的转换。
hsv = cv.cvtColor(imagein, cv.COLOR_BGR2HSV)
这样我们就完成了色域的转换。
转换色域后我们可以看出图像的颜色差别更加直观了。
阈值提取
这是最简单的一种图像特征的提取方式,直接通过对图像中的特定颜色进行阈值调整,可以提取出固定的颜色。有一些树莓派的小球跟踪小车就是通过对图像的阈值直接处理后在加上轮廓特征提取出小球相对相机的坐标位置,然后控制小车向前向后或者左右转。 这里我们直接设置阈值
# 定义HSV中蓝色的范围
lower_blue = np.array([110,50,50])
upper_blue = np.array([130,255,255])
# 设置HSV的阈值使得只取蓝色
mask = cv.inRange(hsv, lower_blue, upper_blue)
blur = cv.GaussianBlur(mask,(5,5),0)
掩膜提取和原图覆盖
这里通过阈值处理之后我们就得到了一张只包含我们感兴趣颜色部分的图像,这张图像可以称之为掩膜。把掩膜图像和原始的图像进行相加处理就可以得到原始图像中只包含我们感兴趣区域的图像。 融合掩膜与原图像:
# 将掩膜和图像逐像素相加
res = cv.bitwise_and(frame,frame, mask= mask)
Mask是阈值处理之后的图像就是我们将要使用的掩膜,RES是将掩膜与原图像相加之后的结果。
最后直观的放两张图对比一下:
可以看到提取的效果还是挺好的。 这里决定掩膜质量的因素是阈值的数值和色域空间的选择
源代码
源码中使用了matplotlib画了图。阈值后的图像做了平滑处理。
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
cap = cv.VideoCapture(0)
while(1):
# 读取帧
_, frame = cap.read()
# 转换颜色空间 BGR 到 HSV
hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV)
# 定义HSV中蓝色的范围
lower_blue = np.array([110,50,50])
upper_blue = np.array([130,255,255])
# 设置HSV的阈值使得只取蓝色
mask = cv.inRange(hsv, lower_blue, upper_blue)
blur = cv.GaussianBlur(mask,(5,5),0)
# 将掩膜和图像逐像素相加
res = cv.bitwise_and(frame,frame, mask= mask)
cv.imshow('frame',frame)
cv.imshow('mask',mask)
cv.imshow('res',res)
plt.subplot(221), plt.imshow(frame), plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(222), plt.imshow(hsv), plt.title('HSV')
plt.xticks([]), plt.yticks([])
plt.subplot(223), plt.imshow(mask), plt.title('Mask')
plt.xticks([]), plt.yticks([])
plt.subplot(224), plt.imshow(res), plt.title('RES')
plt.xticks([]), plt.yticks([])
plt.show()
k = cv.waitKey(5) & 0xFF
if k == 27:
break
cv.destroyAllWindows()
|