上一节我们说到要加强目标识别方法,怎么做到这点呢,我翻了翻OpenCV的官方文档,发现除了模板匹配之外,颜色匹配是它的另一个目标识别方法,一般的思路是这样的:
首先使用OpenCV截取图像,然后将图像内RGB转换为HSV色彩空间进行判断,统计判断HSV和RGB的范围对应关系,最后输出RGB值
然后将目标图片进行处理,将RGB颜色转为HSV;使用cv2中inRange()函数过滤背景颜色;将过滤后的颜色进行二值化处理,得到双色彩图片(其中有一种是我们目标的颜色);再使用dilate()函数对双色彩图片进行形态学腐蚀膨胀;最后统计白色区域面积。
这里为什么要将RGB转换成HSV色彩空间呢?
主要是因为HSV色彩空间可以提高识别的准确率,较RGB而言更适合于目标识别这一领域,当前很多出色的颜色识别项目,都是在这个空间下进行的识别。这里我想到了一个增加精度的方法,在测试前对目标图片做一次高斯模糊的效果会更好一些,实验也证明确实是这样。下面就具体举一个例子,来看看颜色识别的效果吧,一言不合就上代码:
#coding:utf-8
import cv2 as cv
import numpy as np
import collections
import math
import ctypes,sys
def get_color(frame):
print('go in get_color')
hsv = cv.cvtColor(frame,cv.COLOR_BGR2HSV_FULL)
maxsum = -120
color = None
color_dict = getColorList()
for d in color_dict:
mask = cv.inRange(hsv,color_dict[d][0],color_dict[d][1])
#cv.imwrite(d+'.jpg',mask)
binary = cv.threshold(mask, 90, 255, cv.THRESH_BINARY)[1]
binary = cv.dilate(binary,None,iterations=2)
img, cnts, hiera = cv.findContours(binary.copy(),cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)
sum = 0
for c in cnts:
sum+=cv.contourArea(c)
if sum > maxsum :
maxsum = sum
color = d
return color
def separate_color(frame,color):
hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV) #色彩空间转换为hsv,便于分离
cv.imshow("f",hsv)
lower_hsv = np.array(color[0]) #提取颜色的低值
high_hsv = np.array(color[1]) #提取颜色的高值
mask = cv.inRange(hsv, lowerb = lower_hsv, upperb = high_hsv) #下面详细介绍
cv.namedWindow("ColorFilter", cv.WINDOW_NORMAL)
cv.imshow("ColorFilter", mask)
if __name__ == '__main__':
###高斯模糊
filename='D://PythonPicTemplate/colorCutting/tankTemplate1.jpg'
targetname = "D://PythonPicTemplate/colorCutting/tanks1.jpg"
kernel_size = (15, 15)
sigma = 1.5
imgC = cv.imread(filename)
imgColor = cv.GaussianBlur(imgC, kernel_size, sigma)
#提取模板颜色
imghsv = cv.cvtColor(imgColor, cv.COLOR_BGR2HSV) #色彩空间转换为hsv,便于分离
cv.imshow("f0",imghsv)
content = "正在提取模板颜色HAV矩阵向量......"
printGreen(content.decode("utf-8").encode("gbk"))
color_dict = getColorList()
print(get_color(imgColor))
tplColor = color_dict[get_color(imghsv)]
#目标颜色追踪
target = cv.imread(targetname)
HSV = cv.cvtColor(target, cv.COLOR_BGR2HSV)
#H, S, V = cv.split(HSV)
LowerBlue = np.array(tplColor[0])
UpperBlue = np.array(tplColor[1])
content0 = "正在对目标进行颜色分割处理......"
printGreen(content0.decode("utf-8").encode("gbk"))
mask = cv.inRange(HSV, LowerBlue, UpperBlue)
targetCutting0 = cv.bitwise_and(target, target, mask=mask)
cv.imwrite('targetCutting.jpg',targetCutting0)
cv.namedWindow('targetCutting0', cv.WINDOW_NORMAL)
cv.imshow('targetCutting0',targetCutting0)
cv.waitKey(0)
cv.destroyAllWindows()
###初始化处理过的目标
filename2='D://PythonPicTemplate/colorCutting/tankTemplate2.jpg'
targetname2 = "D://PythonPicTemplate/colorCutting/targetCutting.jpg"
imgC = cv.imread(filename2)
targetCutting0 = cv.imread(targetname2)
imgC = cv.GaussianBlur(imgC, kernel_size, sigma)
HSV2 = cv.cvtColor(imgC, cv.COLOR_BGR2HSV)
LowerBlue = np.array(tplColor[0])
UpperBlue = np.array(tplColor[1])
mask2 = cv.inRange(HSV2, LowerBlue, UpperBlue)
imgC= cv.bitwise_and(imgC, imgC, mask=mask2)
注:代码中对颜色范围是从网上找的,这里没有具体写出,文章最后会给出完整代码地址,自己只实验了下灰白和紫色。
测试结果如下:
初始目标场景 颜色分割 颜色分割后的模板匹配从结果中我们大概就可以看出,颜色识别这一方法优点是在目标坦克颜色与地貌、环境不符时,可以排除其他颜色下的干扰因素,然后便可进行模板匹配,增加识别的精度。缺点仍然有很多,例如:
1.该方法十分依赖RGB空间范围和HSV空间的对应关系,但网上没有试验将两者的对应关系很好的展现出来,在一些论文研究的时候也是作者自己测试了部分他所需要的数据而已,而网上的数据集十分不精确。
2.颜色匹配要求目标坦克的颜色要在图片中区别于其他障碍物,但实际中坦克外面是已经做过伪装措施的,而且针对不同地域进行了不同的伪装,其中就包括颜色的改变,所以这对本来数据集就少的颜色层次区分有了进一步的要求。
这里大家可能会问为什么一开始不直接使用机器学习的方法训练数据集来达到目标识别的目的,其实这个在后面的文章中会讲,主要原因一个是机器学习进行训练的时候,训练图片内容越复杂,训练起来越费时费力,我试过了好几种目标检测方法,效果都不如各种方法展示的那么好。而且我用的是笔记本,实在带不动太多的图片数据。
代码已上传至GitHub及Gitee,欢迎star,欢迎讨论:
GitHub:https://github.com/wangwei39120157028/Machine_Learning_research_on_simple_target_recognition_and_intention_analysis
Gitee:https://gitee.com/wwy2018/Machine_Learning_research_on_simple_target_recognition_and_intention_analysis/settings
网友评论