欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

基于yanshee的颜色识别任务中,注意:使用opencv3会返回三个值,即img、countours和hierarchy。

最编程 2024-01-13 13:28:12
...

cv2.findContours()函数首先返回一个list列表

list中每个元素都是图像中的一个轮廓

参数介绍:

Image:寻找轮廓的图像

Mode:表示轮廓的检索模式

Method:轮廓的近似办法

作用:寻找轮廓。

 

Bb:通过轮廓的面积筛选轮廓并将轮廓画出:

 for cnt in contours:

# 计算轮廓的面积
        area = cv2.contourArea(cnt)
        if area > 50:
            #             print("面积:{}".format(area))

# 筛选完后将筛选过后的轮廓draw画出来。
            cv2.drawContours(frame_copy, cnt, -1, (0, 0, 255), 3)
            # 计算轮廓周长

    peri = cv2.arcLength(cnt, True)
            #             print("周长:{}".format(peri))

# 画出的轮廓可能不够规整,比如圆形不像圆形,多边形不像多边形,因此对其进行一个多边形拟合操作approxPolyDP。达到一种轮廓近似的效果。
            approx = cv2.approxPolyDP(cnt, 0.02 * peri, True)

cv2.drawContoursimg,contours,contourIndex,color,crudeness

参数介绍:

Img:指明在哪幅图像上绘制轮廓(ima为三通道才能显示轮廓)

Contours:轮廓本身,是一个list;

contourIndex:指定绘制轮廓list中的哪条轮廓,如果是-1,则绘制其中的所有轮廓。

Color:指明颜色(需为三通道,eg:(255,0,0),否则不会显色)

crudeness:线条粗细

作用:画出轮廓。  ps:(在本代码中,此行代码只用于测试,没有也不影响)

cv2.aprroxPolyDP(cnt, epsilon, True)

参数介绍:

Cnt:为输入的轮廓值

Epsilon:为阈值T,通常使用轮廓的周长作为阈值

True:表示的是轮廓是闭合的

作用:画出的轮廓可能不够规整,比如圆形不像圆形,多边形不像多边形,因此对其进行一个多边形拟合操作approxPolyDP。达到一种轮廓近似的效果。

(小说明:进行完上述的操作之后,我们基本已经精准地找到了我们目标(小球)的位置,接下来的任务就是通过找出的轮廓,然后用圆圈圈出它。)

1)根据轮廓的位置,对其进行一个跟踪,即用圆圈把它的位置圈出,进行一个标记。

(主要思路:我们可以根据我们所找出的轮廓,求它的最小整矩形,然后借这个最小正矩形的返回值(返回值会返回它左上角的焦点的x点和y点以及它的宽和高)来得到圆圈的圆心还有半径。)

具体步骤:

  1. 用上述我们已经找出的轮廓,求它的最小正矩形,并返回四个返回值。

# 进行轮廓近似后的图形,用boundingRect函数得到它的最小正矩形

# 矩形的边界与图像边界平行

x,y最小正矩形左上角的点,w为宽,h为高。
            x, y, w, h = cv2.boundingRect(approx)

cv2.boundingRect(cnt)

参数介绍:

Cnt:轮廓近似后的图形

作用:得到图形的最小正矩形,得出四个返回值。

 

  1. 用得出的四个返回值,来作为cv.circle的参数。

cv2.circle(frame, ((x + w / 2), (y + h / 2)), w / 2, (0, 255, 0), 2)

cv2.Cricle(img, center, radius, (0, 255, 0), 2) 

参数介绍:

Img:表示需要画的图片

Center:表示圆的中心点

Radius:表示圆的半径,(0, 255, 0)表示颜色

 2:表示线条的粗细

作用: 根据坐标在图上画出圆

具体代码:

  1 #!/usr/bin/env python
  2 # coding: utf-8
  3 
  4 # In[ ]:
  5 
  6 
  7 # python2 所需 ↓
  8 
  9 
 10 # 导入需要用到的包
 11 import time
 12 from picamera.array import PiRGBArray
 13 from picamera import PiCamera
 14 import numpy as np
 15 import cv2
 16 import math
 17 import requests
 18 import json
 19 
 20 # 分辨小球颜色需要用到的HSV值。
 21 # 样题只要红色
 22 # # 红色:
 23 # red_min = np.array([0, 128, 46])
 24 # red_max = np.array([5, 255, 255])
 25 # red2_min = np.array([156, 128, 46])
 26 # red2_max = np.array([180, 255, 255])
 27 
 28 # # 绿色:
 29 # green_min = np.array([35, 128, 46])
 30 # green_max = np.array([77, 255, 255])
 31 
 32 # # 蓝色:
 33 # blue_min = np.array([100, 128, 46])
 34 # blue_max = np.array([124, 255, 255])
 35 
 36 # # 黄色:
 37 # yellow_min = np.array([15, 128, 46])
 38 # yellow_max = np.array([34, 255, 255])
 39 
 40 # 橙色:
 41 orange_min = np.array([0, 49, 117])
 42 orange_max = np.array([40, 255, 255])
 43 # # ...等等颜色
 44 
 45 # # 把颜色都汇总到一个数组中,顺带给各自定义一个颜色名。
 46 # COLOR_ARRAY = [[red_min, red_max, 'red'], [red2_min, red2_max, 'red'], [green_min, green_max, 'green'],
 47 #                [blue_min, blue_max, 'blue'], [yellow_min, yellow_max, 'yellow'], [orange_min, orange_max, 'orange']]
 48 
 49 
 50 //建立与机器人的连接。
 51 root_url = "http://127.0.0.1:9090/v1"
 52 motions_url = root_url + "/motions"
 53 led_url = root_url + "/devices/led"
 54 headers = {'Content-Type': 'application/json'}
 55 
 56 
 57 # 定义一个停止运动的函数。
 58 def stopmotion():
 59     motion = {"operation": "stop", "motion": {"name": ""}}
 60     json_data = json.dumps(motion)
 61     response = requests.put(url=motions_url, data=json_data, headers=headers)
 62 
 63 
 64 # 定义一个带有颜色参数的函数。
 65 # 作用在于传对应参数颜色给机器人,机器人就闪什么颜色。
 66 def putled(color):
 67     led = {"type": "button", "color": color, "mode": "on"}
 68     json_data = json.dumps(led)
 69     response = requests.put(url=led_url, data=json_data, headers=headers)
 70 
 71 # 定义一个带有参数的函数。
 72 # 作用在于传对应参数方向(左右手)给机器人,机器人就举起哪只手。
 73 def putmotion(direction):
 74     motion = {"operation": "start", "motion": {"name": "raise","direction": direction}}
 75     json_data = json.dumps(motion)
 76     response = requests.put(url=motions_url, data=json_data, headers=headers)
 77 
 78 
 79 
 80 # 先初始化摄像头:
 81 camera = PiCamera()
 82 camera.resolution = (320, 240)
 83 camera.framerate = 40
 84 rawCapture = PiRGBArray(camera, size=(320, 240))
 85 time.sleep(2)
 86 # 在初始化摄像头后定义一个全局变量(global ) change,好让机器人在检测到小球的位置后 所执行的次数仅为1,不会死循环执行。
 87 change = 0
 88 
 89 
 90 # 查找颜色小球并圆圈圈出:
 91 def find_color(img):
 92     global change
 93     cv2.imwrite('frame.jpg', img)
 94     hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
 95     cv2.imwrite('hsv.jpg', hsv)
 96 
 97     #     for (color_min, color_max, name) in COLOR_ARRAY:
 98 
 99     # 创建一个蒙版,在阈值范围内的像素点全变为255 白色,之外的全都变成0 黑色。
100     #     mask = cv2.inRange(hsv, color_min, color_max)
101 #  创建一个蒙版,在阈值范围内的像素点全变为255 白色,之外的全都变成0 黑色。
102     mask = cv2.inRange(hsv, orange_min, orange_max)
103     cv2.imwrite('mask.jpg', mask)
104     # '与'操作,有蒙版参数在内的话,则仅上色蒙版中255的部分。
105     resultImg = cv2.bitwise_and(img, img, mask=mask)
106     cv2.imwrite('res.jpg', resultImg)
107     x, y, w, h = getContours(mask)
108     if x != 0 and y != 0 and w != 0 and h != 0:
109         cv2.circle(frame, ((x + w / 2), (y + h / 2)), w / 2, (0, 255, 0), 2)
110         cv2.putText(frame, 'orange', (x + w / 2, y + h + 10), cv2.FONT_HERSHEY_COMPLEX, 0.4, (0, 0, 255), 1)
111         #         print(x + w / 2)
112         if change == 0:
113             change = 1 if (x + w // 2) < 160 else 2
114             print 'change001 = %d' % change
115         if ((x + w // 2) < 160) and (change == 1):
116             print("左手一个慢动作")
117             change = 2
118             putmotion("left")
119             putled("yellow")
120         elif ((x + w // 2) > 160) and (change == 2):
121             print("右手一个慢动作")
122             change = 1
123             putmotion("right")
124             putled("green")
125 
126 
127 # 找出轮廓:
128 def getContours(img):
129     x, y, w, h = 0, 0, 0, 0
130 # 进行一个均值滤波操作,去除一些不必要的噪点,消除一些影响因素。
131     blured = cv2.blur(img, (5, 5))
132     # kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3))
133 # 对进行过滤后的图片进行一个开操作 (先腐蚀再膨胀)
134 # 作用:
135 去除噪声,消除小物体
136 在纤细点处分离物体
137 平滑较大物体的边界的同时并不明显改变其面积
138 
139 opened = cv2.morphologyEx(blured, cv2.MORPH_OPEN, (3, 3))
140     cv2.imwrite('opened.jpg', opened)
141 
142 
143 
144 
145 
146 
147 # 对进行过滤后的图片进行一个闭操作 (先膨胀再腐蚀)
148 # 作用:
149 排除小型空洞(指黑色区域)
150 平滑物体轮廓
151 弥合(连接)窄的间断点,沟壑
152 填补轮廓线断裂
153 
154     closed = cv2.morphologyEx(opened, cv2.MORPH_CLOSE, (3, 3))
155     cv2.imwrite('closed.jpg', closed)
156 # 对图像进行边缘检测。
157     imgCanny = cv2.Canny(closed, 50, 100)
158     cv2.imwrite('imgCanny.jpg', imgCanny)
159 # 将边缘检测的图像找出来。(其中可能会检测到多个轮廓,因此要对轮廓进行一个筛选。)
160     contours, hierachy = cv2.findContours(imgCanny, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
161     for cnt in contours:
162         area = cv2.contourArea(cnt)
163         if area > 50:
164             #             print("面积:{}".format(area))
165 # 筛选完后将筛选过后的轮廓draw画出来。
166             cv2.drawContours(frame_copy, cnt, -1, (0, 0, 255), 3)
167             peri = cv2.arcLength(cnt, True)
168             #             print("周长:{}".format(peri))
169 # 画出的轮廓可能不够规整,比如圆形不像圆形,多边形不像多边形,因此对其进行一个多边形拟合操作approxPolyDP。达到一种轮廓近似的效果。
170             approx = cv2.approxPolyDP(cnt, 0.02 * peri, True)
171 # 进行轮廓近似后的图形,用boundingRect函数得到它的最小正矩形。
172 # 矩形的边界与图像边界平行
173 # (x,y)为最小正矩形左上角的点,w为宽,h为高。
174             x, y, w, h = cv2.boundingRect(approx)
175     return x, y, w, h
176 
177 
178 # 关闭摄像头与窗口:
179 def close_it():
180     camera.close()
181     cv2.destroyAllWindows()
182     stopmotion()
183 
184 
185 for frame in camera.capture_continuous(rawCapture, format='bgr', use_video_port=True):
186     # 当前帧
187     frame = frame.array
188     frame_copy = frame.copy()
189     find_color(frame)
190     cv2.imshow("Result", frame)
191     rawCapture.truncate(0)
192     if cv2.waitKey(1) & 0xFF == ord('q'):
193         close_it()
194         break

原文地址:https://www.cnblogs.com/simmons99/p/14023716.html