OpenCV—颜色识别

一、前言

本内容为通过对opencv进行初步学习,结合python进行多种颜色的基本识别。

二、学习过程

1.颜色空间的转换

初学opencv,首先我对于图像进行了更深层的了解,对于灰度及彩色图像其内部的结构有了认识。之后便开始学习opencv的各种基本功能,如读取图像与视频,使用网络摄像头等等。

在初步了解掌握了opencv的基本函数后,对于颜色识别的学习开始于颜色空间的转换。

在日常生活中颜色空间大都是采用RGB的形式,RGB 适合于显示系统,却并不适合于图像处理,在opencv中采用BGR,HSV颜色空间,将RGB转化为HSV颜色空间则是我们进行颜色识别的基础。

HSV(Hue, Saturation, Value)是根据颜色的直观特性由A. R. Smith在1978年创建的一种颜色空间, 也称六角锥体模型(Hexcone Model)(参考百度)。在HSV模型中,颜色是由色相(Hue),饱和度(Saturation),明度(Value)共同组成。

1f35e8cb1f91476a84475675716fcaa5.jpg

进行不同颜色空间的转换,需要用到转换函数cv2.cvtColor(),如下图所示代码 

​
import cv2
cv2.namedWindow('window',cv2.WINDOW_NORMAL)
cv2.resizeWindow('window',820,520)
img = cv2.imread("D:/opencv/aaaaa.jpg")
img_1=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #转换为灰度图像
cv2.imshow('window',img_1)
cv2.waitKey(0)
cv2.destroyAllWindows()

​

 运行结果:

通过上述代码将彩色图像转换成了灰度图像

bcebb26cd9264f5cb6e77e9919a778f2.png2dfc0e5d3b24429cadd9903eca7ba0ea.png

 2.轨迹栏的使用

学习了颜色空间转换后,引入新的功能:轨迹栏的使用。主要两个函数:

cv2.createTrackbar(trackbarName, windowName, value, count, onChange)创建轨迹栏

主要参数:

trackbarName:轨迹栏名称
windowName:附加到的窗口名称
value:默认值
count:最大值
onChange:执行的回调函数每次跟踪栏值更改
cv2.getTrackbarPos(trackbarname, winname)获取轨迹栏的位置

trackbarname:轨迹栏名称
winname:附加到的窗口名称

代码展示:

import cv2
import numpy as np
cv2.namedWindow('window', cv2.WINDOW_NORMAL)
cv2.resizeWindow('window', 820, 520)
def void(value):
    print(value)
# 创建颜色变化的轨迹栏
cv2.createTrackbar('R','window',0,255,void)
cv2.createTrackbar('G','window',0,255,void)
cv2.createTrackbar('B','window',0,255,void)
img=np.zeros((520,820,3),np.uint8)# 创建一个黑色的图像,一个窗口
while True:
    # 得到四条轨迹的当前位置
    r=cv2.getTrackbarPos('R','window')
    g=cv2.getTrackbarPos('G','window')
    b=cv2.getTrackbarPos('B','window')
    img[:]=[b,g,r]
    cv2.imshow('window', img)
    key=cv2.waitKey(1)
    if key==ord('q'):
        break
cv2.destroyAllWindows()

运行结果:

3e6278f028d9441ab370a6b5df28297d.png2762c81db8914ad1a4fa9aa6242f648c.png

如上图通过轨迹栏改变了BGR三通道值来显示不同颜色

3.Opencv 绘制线段、矩形、圆形、多边形操作

OpenCV提供了许多用于绘制图形的方法,包括绘制线段的line()方法、绘制矩形的 rectangle()方法、绘制圆形的 circle()方法、绘制多边形的 polylines()方法和绘制文字的 putText()方法等等

通过学习绘制图形,使得我们可以在图片,视频的基础上添加我们想要的操作。

代码示例:

import cv2
import numpy as np
cv2.namedWindow('ww',cv2.WINDOW_NORMAL)
cv2.resizeWindow('ww',820,420)
img=cv2.imread("D:/opencv/sy.jpg")
width,height=640,480
cv2.line(img,[0,0],[1957,1227],[0,250,0],2)
cv2.rectangle(img,[0,0],[435,876],[250,0,0],2)
cv2.circle(img,[990,596],30,[255,255,0],3)
cv2.putText(img,"Shandong Agricultural University ",(655,236),cv2.FONT_HERSHEY_COMPLEX,2,[54,66,0],2)
p1=np.float32([[849,120],[1132,110],[849,592],[1132,592]])
p2=np.float32([[0,0],[width,0],[0,height],[width,height]])
m=cv2.getPerspectiveTransform(p1,p2)
img_1=cv2.warpPerspective(img,m,(width,height))
cv2.imshow('ww',img)
cv2.imshow('wqw',img_1)
cv2.waitKey(0)
cv2.destroyAllWindows()
​

​

运行结果:36e5903932c04c92b541daff0266ade0.png 

4.色彩空间转换,利用inrange函数过滤视频中的颜色,实现跟踪某一颜色

要想进行颜色识别,对于特定颜色进行分辨,需要了解各种颜色的对应范围

cv2.inRange()函数的作用是:可以提取你想要的颜色,并把该颜色的区域设置为白色,其余的设置为黑色。
其实原理是这样的:在RGB三通道图像中,该函数会让你输入一个低值数组和高值数组,然后这个函数会扫描图片的每个像素,每个像素的值,即这个数组的每个值,如果相对应的,都在两个你输入的数组的,相对应的位置的数值内,那么这个数值会被设置为白色。否则只要有一个不在这个范围内,那么就会设置为黑色。

可以通过下表对应颜色的数值过滤其他颜色
HSV颜色对应RGB的分量范围:

35d925b0a1384941bc05f5b8080b3924.png
代码如下:


import cv2
import numpy as np
def back(value):
    pass
cv2.namedWindow('ww',cv2.WINDOW_NORMAL)
cv2.resizeWindow('ww',820,420)
cv2.namedWindow('waw',cv2.WINDOW_NORMAL)
cv2.resizeWindow('waw',820,420)
cv2.namedWindow('wzw',cv2.WINDOW_NORMAL)
cv2.resizeWindow('wzw',820,420)
cv2.namedWindow('mask',cv2.WINDOW_NORMAL)
cv2.resizeWindow('mask',820,420)
img=cv2.imread("D:/opencv/aaaaa.jpg")
imghsv=cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
cv2.createTrackbar('a','ww',42,179,back)
cv2.createTrackbar('b','ww',179,179,back)
cv2.createTrackbar('c','ww',49,255,back)
cv2.createTrackbar('d','ww',255,255,back)
cv2.createTrackbar('e','ww',112,255,back)
cv2.createTrackbar('f','ww',255,255,back)
while True:
    a=cv2.getTrackbarPos('a','ww')
    b=cv2.getTrackbarPos('b','ww')
    c=cv2.getTrackbarPos('c','ww')
    d=cv2.getTrackbarPos('d','ww')
    e=cv2.getTrackbarPos('e','ww')
    f=cv2.getTrackbarPos('f','ww')
    lower=np.array([a,c,e])
    upper=np.array([b,d,f])
    mask=cv2.inRange(imghsv,lower,upper)
    imgmask=cv2.bitwise_and(img,img,mask=mask)
    cv2.imshow('waw',img)
    cv2.imshow('wzw',imghsv)
    cv2.imshow('mask',imgmask)
    k= cv2.waitKey(1)
    if k==ord('q'):
        break
cv2.destroyAllWindows()

​

运行结果:

3335c5a6640d4e699c0bde6443da827a.png

三、问题与解决方法

在刚开始着手颜色识别时,通过这几天的学习,我原计划通过inrange函数将颜色分隔,对于特定颜色进行识别,起初进展顺利,对于单一颜色识别成功但若实现画面内多种颜色识别,我考虑使用for 循环遍历颜色列表,但运行发现中心远点的颜色始终为单一颜色,后来添加count使其自加解决问题,后来运行发现在画面中出现多个颜色但太过杂乱,我便想改变方法,通过中心点对于物体颜色进行识别并通过puttext将物体颜色展示。

四、代码展示

import cv2
import numpy as np
height=640
width=480
vc=cv2.VideoCapture(0)#打开摄像头
vc.set(3,height)
vc.set(4,width)
while vc.isOpened():
    ret,img=vc.read()
    imghsv=cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
    x=int(height/2)
    y=int(width/2)
    center=imghsv[x,y]
    hue=center[0]
    color ='wu'
    if hue<20:
        color="red"
    if 30<=hue < 45:
        color = "yellow"
    if 45<=hue < 90:
        color = "green"
    if 90<=hue < 150:
        color = 'blue'
    if 150<=hue < 175:
        color = 'purple'
    if 175<=hue < 200:
        color = 'pink'
    centerbgr=img[x,y]
    b,g,r=int(centerbgr[0]),int(centerbgr[1]),int(centerbgr[2])
    cv2.circle(img,(x,y),5,(b,g,r),cv2.FILLED)
    cv2.putText(img,str(color),(10,70),cv2.FONT_HERSHEY_COMPLEX,3,(b,g,r),2)
    if not ret:
        break
    cv2.imshow('window',img)
    k=cv2.waitKey(100)
    if k==ord('q'):
        break
vc.release()
cv2.destroyAllWindows()

五、识别结果

e779e3612e304a7e8875d0d5c45b3631.pngcb23e073f5cd4eb5be472628ff980c65.png451c1c2ff8514f3288a9b1154e98bea7.pngc469e715b86146d094417b2d2369fd34.png 

 六、心得体会

在我近期学习了OpenCV,特别是在颜色识别的应用上。这段经历不仅让我对图像处理有了更深刻的理解,也让我体会到了编程与实际应用相结合的乐趣。编程与现实生活中身边事物的结合更加激发了我对于相关知识对于编程的热爱。

在更加深入地使用OpenCV实现颜色识别。如车牌,人脸识别时,在这个过程中,我遇到了许多挑战,比如如何准确地提取出区域、如何在不同光照条件下保持识别的稳定性等。通过不断地调试和优化代码,我逐渐掌握了利用阈值分割、形态学操作等方法来改进颜色识别的技巧。最终,当我的程序能够准确地识别颜色时,那种成就感无以言表。

通过此次初步的学习我对于opencv有了初步认识与浓厚兴趣,对于图像识别的车牌检测,人脸识别进行了进一步学习并掌握。此后,我会更加深入学习,不断提高自己,完善自身。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值