综合实验二 利用智能小车探测环境
一、实验简介
在病毒环境、生化环境、爆炸环境、火灾环境等特殊环境下,人不能直接进入探测,考虑借助于智能设备完成探测环境、搜救、搬运等任务,考虑采用带摄像头的智能小车实现具体探测功能。
二、实验目的
通过本实验能够综合利用智能小车行走、避障、照相、识别图片色彩和语音播报的功能。
三、实验步骤与结果
1、实验实现功能说明
本实验通过二维码识别“start”开始运行,语音播报系统,颜色识别算法,小车控制指令,实现了小车识别到包含start信息的二维码时,小车起步,之后边走边识别颜色,并且记录,最后识别到包含stop信息的二维码时,小车停止并返回初始位置,最终播报识别到的颜色。
2、实验整体设计思路
本实验的要求:小车边走路边识别颜色,并且将识别的颜色记录下来,故传统的单线程无法满足需求,所以要引入多线程,我们引入一条线程thread1,令它执行颜色识别和二维码识别的功能,主线程控制小车的运动。
设置开始标志stopFlag为0,在thread1线程中不断捕获摄像头的图像,扫描到start信号后,置开始标志stopFlag为1,跳出死循环,直行-左转,之后设置停止标志stopFlag为0,让小车一直向前走,在thread1中继续不断捕获摄像头,扫描到stop信号后,置停止标志stopFlag为1,跳出直行循环,之后设置程序让小车返回原处。
颜色识别,由于小车一秒捕获的图像较多,颜色识别到像素块颜色过多,会有重复,因此我们书写了比较算法,利用数组统计每种颜色像素块的数量,比较颜色块数量,令数组数值-即数量最多的为识别到的颜色。
3、实验程序
#bgr8转jpeg格式
import enum
import cv2
import time
import numpy as np
import traitlets
import threading
import inspect
import ctypes
#语音播报# 下面的key要换成自己的
import pygame from aip
import AipSpeech
""" 语音技术 APPID AK SK """
SpeechAPP_ID = '17852430'
SpeechAPI_KEY ='eGeO4iQGAjHCrzBTYd1uvTtf'
SpeechSECRET_KEY = 'Cn1EVsUngZDbRLv4OxAFrDHSo8PsvFVP'
#连接客户端
Speechclient = AipSpeech(SpeechAPP_ID, SpeechAPI_KEY, SpeechSECRET_KEY)
#语音播报初始化
pygame.mixer.init()
def voice_play(text, name,sped=2):
rst = Speechclient.synthesis(text, 'zh', 1, {'spd': sped, 'vol': 10, 'per': 3})#语音文字text
with open(f'./{name}.mp3', 'wb') as f:
f.write(rst)#播报text
pygame.mixer.init()
pygame.mixer.music.load(f'./{name}.mp3')
pygame.mixer.music.play()
time.sleep(0.1)
#二维码识别。标志位转换函数
stopFlag = 0def detect_control(info):
global stopFlag
if stopFlag == 0:
if info == "stop":
robot.Speed_axis_Yawhold_control(0, 0) #停车
stopFlag = 1
voice_play("停止","stop")
# 代表往回走
else:
pass
def bgr8_to_jpeg(value, quality=75):
return bytes(cv2.imencode('.jpg', value)[1])
#导入库并显示摄像头显示组件
# import the necessary packages
#import simple_barcode_detection
import cv2
import pyzbar.pyzbar as pyzbar
from PIL import Image
import ipywidgets.widgets as widgets
#底层驱动方法
from Raspblock import Raspblockrobot = Raspblock()
origin_widget=widgets.Image(format='jpeg',width=280, height=160)
mask_widget = widgets.Image(format='jpeg',width=280,height=160)
result_widget=widgets.Image(format='jpeg',width=280,height=160)
image_container=widgets.HBox([origin_widget,mask_widget,result_widget])
display(image_container)# 二维码
def decodeDisplay(image):
urls = []
barcodes = pyzbar.decode(image)
for barcode in barcodes:
# 提取二维码的边界框的位置
# 画出图像中条形码的边界框
(x, y, w, h) = barcode.rect
# 提取二维码数据为字节对象,所以如果想在输出图像上
# 画出来,就需要先将它转换成字符串
barcodeData = barcode.data.decode("utf-8")
barcodeType = barcode.type
# 向终端打印条形码数据和条形码类型
print("[INFO] Found {} barcode: {}".format(barcodeType, barcodeData))
urls.append(barcodeData)
if len(urls) > 0:
return urls[0]
#线程def _async_raise(tid, exctype):
tid = ctypes.c_long(tid)
if not inspect.isclass(exctype):
exctype = type(exctype)
res=ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))
if res == 0:
raise ValueError("invalid thread id")
elif res != 1:
ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)
def stop_thread(thread):
_async_raise(thread.ident, SystemExit)
# 摄像头参数
cap = cv2.VideoCapture(0)
cap.set(3, 560)
cap.set(4, 420)
cap.set(5, 10)
cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter.fourcc('M', 'J', 'P', 'G'))
width =280
height =160
color = [0,0,0,0,0,0,0,0,0]
#color数组初始化
# #红色区间
red_color_lower = np.array([0, 43, 46])red_color_upper = np.array([10, 255, 255])
# #绿色区间
green_color_lower = np.array([35, 43, 46])green_color_upper = np.array([77, 255, 255])
# #蓝色区间
blue_color_lower=np.array([100, 43, 46])blue_color_upper = np.array([124, 255, 255])
# #黄色区间
yellow_color_lower = np.array([26, 43, 46])yellow_color_upper = np.array([34, 255, 255])
# #橙色区间
orange_color_lower = np.array([11, 43, 46])orange_color_upper = np.array([25, 255, 255])
color_results = []gray = Nonedef Color_Recongnize():
global gray
while(1):
ret, frame = cap.read()
#cv2.imshow('Capture', frame)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
im = decodeDisplay(gray)
if im:
detect_control(im)
print(im)
origin_widget.value = bgr8_to_jpeg(frame)
# change to hsv model
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
red_mask = cv2.inRange(hsv, red_color_lower, red_color_upper)
orange_mask = cv2.inRange(hsv, orange_color_lower, orange_color_upper)
yellow_mask = cv2.inRange(hsv, yellow_color_lower, yellow_color_upper)
green_mask = cv2.inRange(hsv, green_color_lower, green_color_upper)
blue_mask = cv2.inRange(hsv,blue_color_lower, blue_color_upper)
# 247需要
for i in range(height-10,height+10):
for j in range(width-10,width+10):
if red_mask[i,j] == 255:
color[1] +=1
if orange_mask[i,j] == 255:
color[2] +=1
if yellow_mask[i,j] == 255:
color[3] +=1
if green_mask[i,j] == 255:
color[4] +=1
if blue_mask[i,j] == 255:
color[5] +=1
max = 0
for i in range(8):
if color[i]>color[max]:
max = i
result = [""]
if max ==1:
result = ("红色", 'zh', 1, {'spd': 2, 'vol': 15, 'per': 1})
## if max ==2:
#result = ("橙色", 'zh', 1, {'spd': 2, 'vol': 15, 'per': 1})
if max ==3:
result = ("黄色", 'zh', 1, {'spd': 2, 'vol': 15, 'per': 1})
if max ==4:
result = ("绿色", 'zh', 1, {'spd': 2, 'vol': 15, 'per': 1})
#if max ==5:
#result = ("蓝色", 'zh', 1, {'spd': 2, 'vol': 15, 'per': 1})
colRst = result[0]
if colRst not in color_results:
color_results.append(colRst)
print(colRst,end=" ")
for i in range(len(color)):
color[i] = 0
#启动进程
thread1=threading.Thread(target=Color_Recongnize)
thread1.setDaemon(True)thread1.start()robot = Raspblock()
# 开始标志startFlag = 0
while startFlag == 0:
if type(gray) != type(None):
ifo = decodeDisplay(gray)
if ifo == "start":
# 检测到开始信号,退出循环
startFlag = 1
break#初始检测到start信号后退
voice_play("down","down")for i in range(28):
robot.Speed_axis_Yawhold_control(0, -5)#后退
time.sleep(0.1)
for i in range(24):
robot.Speed_Wheel_control(-2, -2, -6, -6)#右后转
time.sleep(0.1)
# 让小车不停的倒退,直到检测到stop信号
voice_play("down","down")while stopFlag == 0:
robot.Speed_axis_Yawhold_control(0, -5)#后退
time.sleep(0.1)
voice_play("forward","forward")for i in range(135): #待调
robot.Speed_axis_Yawhold_control(0, 5)
time.sleep(0.1)
voice_play("right","come back")for i in range(24):
robot.Speed_Wheel_control(2, 2, 6, 6)#右转
time.sleep(0.1)
voice_play("forward","forward")for i in range(15): #待调
robot.Speed_axis_Yawhold_control(0, 5)
time.sleep(0.1)
# 语音播报识别到的颜色t
ext = "识别颜色为" +",".join(color_results)voice_play(text,"rscolor")
# 语音播报识别到的颜色#结束进程,只有在结束时才需要执行此段代码
stop_thread(thread1)
4.实验结果
见文件夹中,以视频形式提交。
四、实验分析
1、实验总结与收获
实验通过程序设计达到预期。通过视觉识别、语音合成、图像处理、小车控制等完成实验目标。但是,识别效果达不到理想,主要原因是所用的算法无法高效规避误差。
2、实验收获
(1)实验中使用了多线程来实现同时进行图像处理和小车控制的功能。这有助于更好地理解了多线程编程的原理和应用。
(2)实验中,需要不断调试小车运动代码,以适应地形,需要非常多的耐心。
(3)颜色识别过程中,需精准的描述各颜色值区间,避免误判,并且,在不同光线环境条件下需不断调试颜色数值区间,来准确判断识别颜色。
(4)此外,释放线程、增加break、字符串与指令相互转换等操作,在后续的程序设计中都可以运用借鉴。
3、其他(实验建议或意见)
关于多线程,函数定义和opencv精准识别颜色方法的介绍,摄像头的使用注意事项提醒。