颜色识别轮廓识别-树莓派 Opencv-基于Python学习记录DAY-4

Posted 凉山有客不自赏

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了颜色识别轮廓识别-树莓派 Opencv-基于Python学习记录DAY-4相关的知识,希望对你有一定的参考价值。

学习颜色识别之前先介绍一下新认识的图像格式HSV:

色调H

用角度度量,取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°。它们的补色是:黄色为60°,青色为180°,紫色为300°;

 

饱和度S

饱和度S表示颜色接近光谱色的程度。一种颜色,可以看成是某种光谱色与白色混合的结果。其中光谱色所占的比例愈大,颜色接近光谱色的程度就愈高,颜色的饱和度也就愈高。饱和度高,颜色则深而艳。光谱色的白光成分为0,饱和度达到最高。通常取值范围为0%~100%,值越大,颜色越饱和。

 

明度V

明度表示颜色明亮的程度,对于光源色,明度值与发光体的光亮度有关;对于物体色,此值和物体的透射比或反射比有关。通常取值范围为0%(黑)到100%(白)。

注意:H:  0 — 180;S:  0 — 255;V:  0 — 255。

那么为什么不直接用RGB格式呢?

由于数字图像中物体颜色的R、G和B分量都与照射到物体上的光量相关,因此相互关联,因此根据这些分量的图像描述使得物体识别困难。色调/明度/色度或色调/明度/饱和度方面的描述通常更相关。

预处理

在识别前要对图像做一系列预处理:

1.高斯模糊

将原图像进行模糊处理,方便颜色的提取

img1 = cv2.GaussianBlur(src,ksize,sigmaX,sigmay,borderType)
#src: 输入图像
#ksize:高斯卷积核的大小,注意 : 卷积核的宽度和高度都应为奇数,且可以不同
#sigmaX: 水平方向的标准差
#sigmaY: 垂直方向的标准差,默认值为0,表示与sigmaX相同
#borderType:填充边界类型

2.BGR转化为HSV

 cv2.cvtColor(图像对象, cv2.COLOR_之前图像格式2要转换成的图像格式)
#第二个参数的意思就是在被转换格式和预转换格式之间加一个‘2’
#比方RGB转HSV === cv2.COLOR_RGB2HSV
#这里列举一下基本的图片格式
#BGR
#RGB
#GRAY
#HSV
#YCRCb
#HLS
#XYZ
#LAB
#YUV

3.去噪

基本上是腐蚀、膨胀、开闭运算的运用,具体要看环境情况,可以参考Day3博客里介绍的各种方法的优缺点来抉择用上门处理方法

树莓派 Opencv-基于Python学习记录DAY-3 形态学处理-腐蚀、膨胀、开闭运算_凉山有客不自赏的博客-CSDN博客

颜色识别

cv2.inRange(hsv, lower_, upper_)#处理对象,阈值上限,阈值下限

这一步就是对单一颜色的识别,将目标颜色的颜色转换为白色,其他背景转换为黑色

获取阈值

关于颜色阈值的获取可以使用以下代码,通过导入图片,拖动滑块获取阈值

import cv2
import numpy as np


def nothing(x):
    pass
    

cv2.namedWindow("Tracking")

cv2.createTrackbar("LH","Tracking",35,255,nothing)
cv2.createTrackbar("LS","Tracking",43,255,nothing)
cv2.createTrackbar("LV","Tracking",46,255,nothing)
cv2.createTrackbar("UH","Tracking",77,255,nothing)
cv2.createTrackbar("US","Tracking",255,255,nothing)
cv2.createTrackbar("UV","Tracking",255,255,nothing)

#cv2.createTrackbar:绑定滑动条和窗口,定义滚动条的数值
#参数
#第一个参数时滑动条的名字,
#第二个参数是滑动条被放置的窗口的名字,
#第三个参数是滑动条默认值,
#第四个参数时滑动条的最大值,
#第五个参数时回调函数,每次滑动都会调用回调函数。


while True:
    frame = cv2.imread('1.jpeg')
    hsv = cv2.cvtColor(frame,cv2.COLOR_BGR2HSV)
    #转换图像格式
    
    l_h = cv2.getTrackbarPos("LH","Tracking")
    l_s = cv2.getTrackbarPos("LS","Tracking")
    l_v = cv2.getTrackbarPos("LV","Tracking")
    
    u_h = cv2.getTrackbarPos("UH","Tracking")
    u_s = cv2.getTrackbarPos("US","Tracking")
    u_v = cv2.getTrackbarPos("UV","Tracking")
    #cv2.getTrackbarPos:得到滑动条的数值
    #参数
    #第一个参数是滑动条名字,
    #第二个时所在窗口,
    #返回值是滑动条的数值。
    
    l_g = np.array([l_h, l_s, l_v]) # 阈值下限
    u_g = np.array([u_h,u_s,u_v])   # 阈值上限

    mask = cv2.inRange(hsv,l_g,u_g) # 二值化
    
    res=cv2.bitwise_and(frame,frame,mask=mask) 

    #cv2.bitwise_and是对二进制数据进行“与”操作,即对图像(灰度图像或彩色图像均可)每个像素值进行二进制“与”操作,将原图与二值化图像与运算,将阈值内的颜色以原本颜色显示
     
    cv2.imshow("frame", frame)
    cv2.imshow("mask", mask)
    cv2.imshow("res", res)
    #显示窗口
    key = cv2.waitKey(1) 
    if key == 27: 
        break        
cv2.destroyAllWindows()
#延时,当按下ESC时关闭窗口,如果用户没有按下键,则继续等待下一个delay时间(循环),直到用户按键触发

  效果展示:

 摄像头实时颜色识别

import cv2
import numpy as np

ball_color = 'green'

color_dist = {'red': {'Lower': np.array([0, 60, 60]), 'Upper': np.array([6, 255, 255])},
              'blue': {'Lower': np.array([100, 80, 46]), 'Upper': np.array([124, 255, 255])},
              'green': {'Lower': np.array([35, 43, 35]), 'Upper': np.array([90, 255, 255])},
              }

cap = cv2.VideoCapture(0)
cv2.namedWindow('camera', cv2.WINDOW_AUTOSIZE)

while cap.isOpened():
    ret, frame = cap.read()
    if ret:
        if frame is not None:
            gs_frame = cv2.GaussianBlur(frame, (5, 5), 0)                     # 高斯模糊
            hsv = cv2.cvtColor(gs_frame, cv2.COLOR_BGR2HSV)                 # 转化成HSV图像
            erode_hsv = cv2.erode(hsv, None, iterations=2)                   # 腐蚀 粗的变细
            inRange_hsv = cv2.inRange(erode_hsv, color_dist[ball_color]['Lower'], color_dist[ball_color]['Upper'])
            

            cv2.imshow('camera', inRange_hsv)
            cv2.waitKey(1)
        else:
            print("无画面")
    else:
        print("无法读取摄像头!")

cap.release()
cv2.waitKey(0)
cv2.destroyAllWindows()

轮廓识别

主要使用cv2.findContours()函数来查找检测物体的轮廓。前提是对二值化的图片检测。


contours, hierarchy=cv2.findContours(image, mode, method[, contours[, hierarchy[, offset ]]])  

#第一个参数是寻找轮廓的图像;

#第二个参数表示轮廓的检索模式,有四种(本文介绍的都是新的cv2接口):
#    cv2.RETR_EXTERNAL     表示只检测外轮廓
#    cv2.RETR_LIST                检测的轮廓不建立等级关系
#    cv2.RETR_CCOMP          建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息.
#如果内孔内还有一个连通物体,这个物体的边界也在顶层。
#    cv2.RETR_TREE            建立一个等级树结构的轮廓。

#第三个参数method为轮廓的近似办法
#    cv2.CHAIN_APPROX_NONE 存储所有的轮廓点,相邻的两个点的像素位置差不超过1,即max(abs(x1-#x2),abs(y2-y1))==1
#    cv2.CHAIN_APPROX_SIMPLE 压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例#如一个矩形轮廓只需4个点来保存轮廓信息
#    cv2.CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS 使用teh-Chinl chain 近似算法

#返回值
#cv2.findContours()函数返回两个值,一个是轮廓本身contour,还有一个是每条轮廓对应的属性hierarchy。
#contour返回一个list,list中每个元素都是图像中的一个轮廓,用numpy中的ndarray表示。
#hierarchy返回一个可选的hiararchy结果,这是一个ndarray,其中的元素个数和轮廓个数相同,每个轮廓#contours[i]对应4个hierarchy元素hierarchy[i][0] ~hierarchy[i][3],分别表示后一个轮廓、前一个轮
#廓、父轮廓、内嵌轮廓的索引编号,如果没有对应项,则该值为负数

轮廓绘制

cv2.drawContours(image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset ]]]]]) 

#第一个参数是指明在哪幅图像上绘制轮廓;
#第二个参数是轮廓本身,在Python中是一个list。
#第三个参数指定绘制轮廓list中的哪条轮廓,如果是-1,则绘制其中的所有轮廓。
#后面的参数很简单。其中thickness表明轮廓线的宽度,如果是-1(cv2.FILLED),则为填充模式。绘制参数将在以后独立详细介绍。

示例代码

import cv2  
 
img = cv2.imread("./example.png")  
 
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)  
ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)  
 
contours, hierarchy = cv2.findContours(binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

cv2.drawContours(img,contours,-1,(0,0,255),3)  
 
cv2.imshow("img", img)  
cv2.waitKey(0)  

以上是关于颜色识别轮廓识别-树莓派 Opencv-基于Python学习记录DAY-4的主要内容,如果未能解决你的问题,请参考以下文章

树莓派 --- 基于OpenCV实现人脸识别

基于树莓派的人脸识别门禁系统

树莓派视觉小车 -- 物体跟踪(OpenCV)

树莓派安装openCV做图像识别

(附代码)树莓派利用OpenCV的图像跟踪人脸识别等

从3D打印到python编程 从opencv到人脸识别 从win10到树莓派ubuntu (全教程附代码)