OpenCV基于颜色的目标识别(入门简单摄像头版)

接上篇OpenCV基于颜色识别目标(入门简单图片版)

这次加入了摄像头
实现思路:视频其实就是每一张图片的叠加,只要对视频中的每一帧读入并作处理,就能实现对视频流中目标的识别。所以这里我们只要将读入图像和处理图像的操作放入while循环中就能实现实时的识别目标了。

具体代码实现

import cv2
import numpy as np
import os
os.environ['KMP_DUPLICATE_LIB_OK'] = 'True'

#定义一个形态学处理的函数
def good_thresh_img(img):
    gs_frame = cv2.GaussianBlur(img, (5, 5), 0)                     #高斯滤波
    hsv = cv2.cvtColor(gs_frame, cv2.COLOR_BGR2HSV)                 # 转化成HSV图像
    erode_hsv = cv2.erode(hsv, None, iterations=2)
    return erode_hsv

#定义一个识别目标颜色并处理的函数
def select_color_img(target_color,img):
        for i in target_color:
            mask=cv2.inRange(erode_hsv,color_dist[i]['Lower'],color_dist[i]['Upper'])
            if(i==target_color[0]):
                inRange_hsv=cv2.bitwise_and(erode_hsv,erode_hsv,mask = mask)
            else:
                inRange_hsv1=cv2.bitwise_and(erode_hsv,erode_hsv,mask = mask)
                inRange_hsv=cv2.add(inRange_hsv,inRange_hsv1)
        return  inRange_hsv

#定义一个提取轮廓的函数
def extract_contour(img):
    inRange_gray = cv2.cvtColor(final_inRange_hsv,cv2.COLOR_BGR2GRAY)
    contours,hierarchy = cv2.findContours(inRange_gray,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
    return contours
    
#定义一个寻找目标并绘制外接矩形的函数
def find_target(contours,draw_img):
    for c in contours:
        if cv2.contourArea(c) < 2000:             #过滤掉较面积小的物体
            continue
        else:
            target_list.append(c)               #将面积较大的物体视为目标并存入目标列表
    for i in target_list:                       #绘制目标外接矩形
        rect = cv2.minAreaRect(i)
        box = cv2.boxPoints(rect)
        cv2.drawContours(draw_img, [np.int0(box)], -1, (0, 255, 255), 2)
    return draw_img

#定义一个绘制中心点坐标的函数
def draw_center(target_list,draw_img):
    for  c in target_list:
        M = cv2.moments(c)                   #计算中心点的x、y坐标
        center_x = int(M['m10']/M['m00'])
        center_y = int(M['m01']/M['m00'])
        print('center_x:',center_x)
        print('center_y:',center_y)
    
        cv2.circle(draw_img,(center_x,center_y),7,128,-1)#绘制中心点
        str1 = '(' + str(center_x)+ ',' +str(center_y) +')' #把坐标转化为字符串
        cv2.putText(draw_img,str1,(center_x-50,center_y+40),cv2.FONT_HERSHEY_SIMPLEX,1,(255,255,0),2,cv2.LINE_AA)#绘制坐标点位
    
    return draw_img
###主函数部分
#创建颜色字典
color_dist = {'red': {'Lower': np.array([0, 60, 60]), 'Upper': np.array([6, 255, 255])},
              'yellow': {'Lower': np.array([15, 160, 50]), 'Upper': np.array([35, 255, 255])},
              'green': {'Lower': np.array([50, 50, 50]), 'Upper': np.array([130, 255, 255])},
              }
#目标颜色
target_color = ['green','yellow']

#创建摄像头
capture = cv2.VideoCapture(0)
#初始化保存图片的编号
count=0
#target_list=[]
while True:
    #创建目标列表。注意一定要将其放入循环中,可以尝试一下将这一行注释掉,把目标列表建在外面,看看区别
    target_list=[]
    
    ret, img = capture.read()
    draw_img = img
    erode_hsv = good_thresh_img(img)
    final_inRange_hsv = select_color_img(target_color,erode_hsv)
    contours = extract_contour(final_inRange_hsv)
    draw_img = find_target(contours,draw_img)
    final_img = draw_center(target_list,draw_img)
    cv2.imshow('final_img',final_img)
    key = cv2.waitKey(1)
	#保存截图或退出
    if key == ord('s'):              #按's'键保存截图
        cv2.imwrite(r"D:lesson/"+str(count)+".jpg",final_img)    #路径名+保存的图片以编号命名+要保存的图片
        count+=1       #编号加一,实现连续截图
    if key==27:       #按Esc键退出
        break
cv2.destroyAllWindows()      #关闭展示窗口
capture.release()            #释放摄像头,若不释放,程序结束后摄像头一直处于开启状态

问题总结:了解了视频的原理后,以为只要把每一帧处理好然后放入循环里就ok了,没想到实际操作起来还是会遇到问题。着重记一笔:上面创建的target_list一定要放在循环里,不然每一帧获取到的目标物体会累加在里面,最后展现的图像和返回的坐标会像重影一般给框出很多目标。而放入while循环里之后,每次循环都会重建一个target_list就相当于之前的给清零了。

回顾总结:到这里这个项目算是完成了,虽说是完成了,但是不够完善,也不够完美。主要的问题有:
1、只能识别单一背景下的目标气球,如果是拿到室外等背景比较复杂的多物体环境中就难以准确识别。
2、识别精确度低,因为采取颜色识别的方案,所以只要在颜色字典设置的阈值之内都会被认作是目标。

但是想要实现的基本功能都实现了,所以说还算凑合吧~
效果展示:

继续努力,继续加油!

你可能感兴趣的:(opencv,计算机视觉,人工智能)