-
Notifications
You must be signed in to change notification settings - Fork 11
Yanshee人工智能5 能分辨颜色的机器人视觉
通过本课程,首先我们会学到一些诸如:颜色、色彩空间等物理概念知识,然后我们会学习摄像头识别颜色的基本原理、使用方法和应用场景以及在机器人领域的其它颜色传感器是如何被使用的。最后,我们要通过一个Yanshee过红绿灯的实验课来提高大家对摄像头视觉识别颜色的概念的实际应用能力。
生活是五彩斑斓的,我们的生活在一个多彩的世界里,但是是什么让我们能分辨颜色的呢?原来我们的眼睛里视网膜上有一种叫做视锥细胞的东西,视锥细胞除感强光外,还有色觉及形觉的功能。根据三原色学说,正常色觉者,视锥细胞外节含有三种不同感光色素(红、绿、蓝),各吸收一定的波长光线而产生色觉。对其它波长光线也可重叠吸收,故可产生各种色觉。所以人的眼睛就能辨出各种不同的色彩。然而我们想让机器人产生颜色的概念于是就有了机器人的眼睛——摄像头分辨颜色功能的诞生。有了能知色彩的摄像头,机器人就可以很轻松的识别出一盆绿色的花或者一片蓝色的天空。
颜色是通过眼、脑和我们的生活经验所产生的对光的视觉感受,我们肉眼所见到的光线,是由波长范围很窄的电磁波产生的,不同波长的电磁波表现为不同的颜色,对色彩的辨认是肉眼受到电磁波辐射能刺激后所引起的视觉神经感觉。 RGB色彩空间: RGB颜色空间以R(Red红)、G(Green绿)、B(Blue蓝)三种基本色为基础,进行不同程度的叠加,产生丰富而广泛的颜色,所以俗称三基色模式。在大自然中有无穷多种不同的颜色,而人眼只能分辨有限种不同的颜色,RGB模式可表示一千六百多万种不同的颜色,在人眼看来它非常接近大自然的颜色,故又称为自然色彩模式。红绿蓝代表可见光谱中的三种基本颜色或称为三原色,每一种颜色按其亮度的不同分为256个等级。
HSV (色相hue,饱和度saturation, 明度value), 也称HSB (B指brightness) 是艺术家们常用的,因为与加法减法混色的术语相比,使用色相,饱和度等概念描述色彩更自然直观。HSV 是RGB色彩空间的一种变形,它的内容与色彩尺度与其出处——RGB色彩空间有密切联系。 可以通过下面这幅图来理解HSV色彩空间颜色值分布情况:
HSV颜色空间的模型对应于圆柱坐标系中的一个圆锥形子集,圆锥的顶面对应于V=1. 它包含RGB模型中的R=1,G=1,B=1 三个面,所代表的颜色较亮。色彩H由绕V轴的旋转角给定。红色对应于角度0° ,绿色对应于角度120°,蓝色对应于角度240°。在HSV颜色模型中,每一种颜色和它的补色相差180° 。 饱和度S取值从0到1,所以圆锥顶面的半径为1。
一种通过光电转换的颜色识别电子元器件。利用色敏元器件将光信号转换为电流转换,再进行微小电流信号预处理,再进行A/D转换,最后将数字信号交予单片机或微机处理,最后输出特定的RGB值,通过比色卡对比,输出颜色值。
目前多数人接受的是托马斯-杨等提出的视觉的三原色学说。在视网膜中存在分别对红,绿,蓝光线特别敏感的三种视锥细胞或相应的三种感光色素,当光谱上波长介于这三者之间的光线作用于视网膜时,这些光线可以对敏感波长与之相近的两种视锥细胞或感光色素起不同程度的刺激作用,在中枢神经系统引起介于这两种原色之间的其他颜色感觉。 我们看东西其实就是用眼睛接收可见光。可见光是电磁波的一个频段。我们把感受到的不同频率的电磁波映射成不同的颜色。遇到过高或过低频率的电磁波(红外线等等)眼睛处理不了,所以就看不见。所以,颜色只是人的主观感受,不是物体的客观属性。物体只是在发射或反射电磁波。
Yanshee机器人一台、颜色测试面板一张
树莓派Rasbian系统、python环境
树莓派直连摄像头: 硬件连接图:(树莓派原装CSI接口摄像头)
摄像头识别颜色原理: 通过将摄像头成像的RGB图片转换成HSV色彩空间里的值,经过图像二值化,判断对应的区域是否属于某种颜色的HSV值范围,最终确定被识别颜色是哪种颜色,并输出识别结果。
我们通过Yanshee 树莓派摄像头进行python代码编程,实现机器人识别红、蓝、黄、绿等颜色的功能,然后执行相关代码:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import sys
import time
from picamera.array import PiRGBArray
from picamera import PiCamera
import numpy as np
import cv2
# define HSV color value
red_min = np.array([0, 128, 46])
red_max = np.array([5, 255, 255])
red2_min = np.array([156, 128, 46])
red2_max = np.array([180, 255, 255])
green_min = np.array([35, 128, 46])
green_max = np.array([77, 255, 255])
blue_min = np.array([100, 128, 46])
blue_max = np.array([124, 255, 255])
yellow_min = np.array([15, 128, 46])
yellow_max = np.array([34, 255, 255])
black_min = np.array([0, 0, 0])
black_max = np.array([180, 255, 10])
white_min = np.array([0, 0, 70])
white_max = np.array([180, 30, 255])
COLOR_ARRAY = [ [ red_min, red_max, 'red'], [ red2_min, red2_max, 'red'], [ green_min, green_max, 'green'], [ blue_min, blue_max, 'blue'],[yellow_min, yellow_max, 'yellow'] ]
#take photo use piCamera
camera = PiCamera()
camera.resolution = (640, 480)
camera.framerate = 25
rawCapture = PiRGBArray(camera, size=(640, 480))
time.sleep(0.1)
#read rgb_jpg file for test
for frame in camera.capture_continuous(rawCapture, format="bgr", use_video_port=True):
frame = frame.array
cv2.imwrite("frame.jpg", frame)
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
cv2.imwrite("hsv.jpg", hsv)
for (color_min, color_max, name) in COLOR_ARRAY:
mask=cv2.inRange(hsv, color_min, color_max)
res=cv2.bitwise_and(frame, frame, mask=mask)
#cv2.imshow("res",res)
cv2.imwrite("2.jpg", res)
img = cv2.imread("2.jpg")
h, w = img.shape[:2]
blured = cv2.blur(img,(5,5))
cv2.imwrite("blured.jpg", blured)
ret, bright = cv2.threshold(blured,10,255,cv2.THRESH_BINARY)
gray = cv2.cvtColor(bright,cv2.COLOR_BGR2GRAY)
cv2.imwrite("gray.jpg", gray)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (50, 50))
opened = cv2.morphologyEx(gray, cv2.MORPH_OPEN, kernel)
cv2.imwrite("opened.jpg", opened)
closed = cv2.morphologyEx(opened, cv2.MORPH_CLOSE, kernel)
#cv2.imshow("closed", closed)
cv2.imwrite("closed.jpg", closed)
contours, hierarchy = cv2.findContours(closed,cv2.RETR_LIST,cv2.CHAIN_APPROX_NONE)
cv2.drawContours(img,contours,-1,(0,0,255),3)
cv2.imwrite("result.jpg", img )
#output number and color we find in the photo
number = len(contours)
print('Total:', number)
if number >=1:
total = 0
for i in range(0, number):
total = total + len(contours[i])
print 'NO:',i,' size:', len(contours[i])
if total > 400:
print 'Currrent color is ', name
cv2.destroyAllWindows()
sys.exit()
rawCapture.truncate(0)
Yanshee机器人在模拟红绿灯环境下,先看到红灯后停止前进并蹲下休息,看到绿灯后起立并走过马路。语音播报:“主人,我已成功通过红绿灯”。
工业机器人,通过颜色来区分物件,完成生产作业。消费级领域机器人通过颜色来分辨小球进行分拣、示范教育、或各种竞技型比赛等等。总之,它的用途非常广泛。
这节课是我们学习机器人摄像头基础之后的第一个视觉应用——即用摄像头来识别颜色,有了这个功能之后我们就可以通过它获得机器人对颜色的感知来编写出各式各样有趣的场景了。比如:去跟踪红色的小球或者白色的足球等等有趣的应用。配合机器人的动作,让你的水平大大提高,它就像是机器人的眼睛触觉,让机器人变的更加聪明智慧。后续我们会继续深入研究机器人视觉的更多功能。