文章目录
QQ:3020889729 小蔡
opencv色域转换
将会使用cv.cvtColor()函数实现图像色域的转换,它的参数如下
- 第一个参数为输入图像
- 第二个参数为转换色域的选择——一般在色域追踪中,可能将opencv默认的BGR转换位HSV会查找更简单一些。(虽然opencv默认色域是RGB;但是,实质上它是采用的BGR存储的,所以我们在处理数据时,按照BGR来处理就好)
- 第三个参数为色域通道数设置——默认为0,意味着原图形默认的通道数
至于输出图像,采用返回值的方式来实现就好。
img = cv.imread('1.png', 1)
hsv = cv.cvtColor(img , cv.COLOR_BGR2HSV) # COLOR_BGR2HSV是指将图像色域转换为HSV
色域转换的本质
其本质我认为主要是对数据的等权重数据转换吧——就比如,我们常常举例说明一样,都是为了问题的简便。
捕获指定区域(采用获取指定范围的掩码实现捕获)
cv.inRange()函数获取指定数据的范围——也就是掩饰掉我们需要的数据之外的数据
主要参数:
- 第一个参数:输入数组(需要提取指定范围的图像数组)
- 第二个参数:查找满足条件的下限值
- 第三个参数:查找满足条件的上限值——由二、三参数可以得到我们搜索的数据范围
至于输出掩码——我们采用就收返回值的方式获取。
对于色域判断,我们通常是把某个色域的上下限取出来,然后放入inRange中作为判断条件。然后得到的掩码——就是只包含这个区域的图像信息的数组。
lower_blue = np.array([110, 50, 50])
upper_blue = np.array([130, 255, 255]) # 设置色域范围
mask = cv.inRange(hsv, lower_blue, upper_blue) # 返回一个满足指定色域外的其它区域值置0的掩码(图像)
官方函数功能的说明:(我就不多说了,就提两句)
该函数在一维时,就直接将在lowerb和upperb的数据保留,其它舍去——置零
——可类推多维度,见下面文档
补充: 如果是图像色域范围的筛选,那么满足为就为阈值(全1位),否则就为0
The function checks the range as follows:
For every element of a single-channel input array: % 0 表示下标,对应维度
dst(I) = lowerb(I)0≤src(I)0≤upperb(I)0
For two-channel arrays:
dst(I) = lowerb(I)0≤src(I)0≤upperb(I)0∧lowerb(I)1≤src(I)1≤upperb(I)1
and so forth.
That is, dst (I) is set to 255 (all 1 -bits) if src (I) is within the specified 1D, 2D, 3D, ... box and 0 otherwise.
通过以上步骤,已经可以操作色域的转换,实现问题的一些简化,又可以通过,对满足指定色域的图像范围的读取/获取。那么接着我们就应该让满足条件的图像区域呈现我们实际的图像了——这里就要用到图像的与,实现图像的混合了。
图像与cv.bitwise_and(),实现掩码与原图像融合
主要参数:
- 第一参数:输入图像1(输入数组1/标量)
- 第二参数:输入图像2(另一个数组/标量)
- 第三参数:输出数组——通常按返回值获取输出数组
- 第四参数:与操作的掩码输入——8位单通道数组,用于指定要更改的输出数组的元素[对应维度]。
实例:(简单理解可以是:输入图像1与输入图像2的按位与,而当mask不等于0时,就是将mask添加到图像混合中,作为与的元素)
res = cv.bitwise_and(frame, frame, mask=mask) # 用图像与操作,实现掩码原图像混合
上面采用原图混合(本来是无任何变化的),由于掺入mask实现了指定位置/范围的与/即图像修改。
【除掩码外的另外两个传入参数是必须要有的,如果只是对掩码处理,不妨就传入一个相同的图像~】
通过色域选定实现对象追踪
实现思路
- 进行色域转换——直接处理BGR与处理HSV,我们选择后者——因为后者更容易表现颜色,换句话说更好被处理。
- 获取指定色域的范围——list类型——用numpy创建数组
- 使用inRange获取指定区域的掩码
- 把掩码掺入到实际的图像中——这里采用图像混合中常用的bitwise_and
代码实例(实现蓝色追踪)
import cv2 as cv
import numpy as np
if __name__ == "__main__":
cap = cv.VideoCapture(0) # 默认摄像设备
while True:
_, frame = cap.read() # 读取设备帧图像——frame为图像
hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV) # 转换色域——因为HSV更容易在图像中查找色彩区域
# 也可通过cvtColor获取不同色域下的颜色值——比如,传入一个BGR(对应cv.COLOR_BGR2HSV)的色值,然后得到HSV下的该色色值
lower_blue = np.array([110, 50, 50])
upper_blue = np.array([130, 255, 255]) # 设置需要的色域范围
mask = cv.inRange(hsv, lower_blue, upper_blue) # 返回一个满足指定色域外的其它区域值置0的掩码
res = cv.bitwise_and(frame, frame, mask=mask) # 用图像与操作,实现掩码与原图像的混合
cv.imshow('imag', frame) # 显示原图像
cv.imshow('mask', mask) # 显示掩码图像
cv.imshow('res', res) # 显示混合图像——也就是追踪图像
if cv.waitKey(5) & 0xFF == 27:
break
cv.destroyAllWindows()
效果
说明:图中噪点写成噪声了,很抱歉,请谅解。
至于如何除噪声,我会在后边单独整理后发出,但是可以有很多滤波方式来消噪——消除噪点。