当前位置: 首页 > article >正文

小车AI视觉交互--2.颜色跟随

一、实验目标

        前面利用了颜色对象在摄像头画面的x,y不同位置通过云台进行跟踪,接下来我们可以在这个基础上修改下,x方向改为车身左右运动进行跟随,然后根据识别的图像外切圆大小进行前进的控制,通过二者叠加来整体控制小车电机运动。

二、实验源码

import sys
sys.path.append('/home/pi/project_demo/lib')
#导入麦克纳姆小车驱动库 Import Mecanum Car Driver Library
from McLumk_Wheel_Sports import *
sys.path.append('/home/pi/software/oled_yahboom/')
from yahboom_oled import *
# 创建oled对象 Create an oled object
oled = Yahboom_OLED(debug=False)
#bgr8转jpeg格式 bgr8 to jpeg format
import enum
import cv2
​
def bgr8_to_jpeg(value, quality=75):
    return bytes(cv2.imencode('.jpg', value)[1])
#显示摄像头组件 Display camera components
import traitlets
import ipywidgets.widgets as widgets
from IPython.display import display
import time
# 线程功能操作库 Thread function operation library
import threading
import inspect
import ctypes
import numpy as np
​
image_widget = widgets.Image(format='jpeg', width=640, height=480)
image = cv2.VideoCapture(0)
​
image.set(3, 320)
image.set(4, 240)
image.set(5, 30)  #设置帧率 Setting the frame rate
# image.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter.fourcc('M', 'J', 'P', 'G'))
# image.set(cv2.CAP_PROP_BRIGHTNESS, 62) #设置亮度 -64 - 64  0.0 Set Brightness -64 - 64 0.0
# image.set(cv2.CAP_PROP_CONTRAST, 63) #设置对比度 -64 - 64  2.0 Set Contrast -64 - 64 2.0
# image.set(cv2.CAP_PROP_EXPOSURE, 4800) #设置曝光值 1.0 - 5000  156.0  Set the exposure value 1.0 - 5000 156.0
ret, frame = image.read()
​
# from picamera2 import Picamera2, Preview
# import libcamera
# picam2 = Picamera2()  
# camera_config = picam2.create_preview_configuration(main={"format":'RGB888',"size":(320,240)})
# camera_config["transform"] = libcamera.Transform(hflip=1, vflip=1)
# picam2.configure(camera_config) 
# # picam2.stop_preview() #停止相机预览,防止占用资源,从而开启相机失败 Stop camera preview to prevent resources from being occupied, which may cause camera startup failure
# # picam2.start_preview(True) #开启相机预览  Open camera preview
# picam2.start() 
# frame = picam2.capture_array()
​
image_widget.value = bgr8_to_jpeg(frame)
global g_mode
g_mode = 0
global color_x, color_y, color_radius
color_x = color_y = color_radius = 0
global color_lower
#color_lower = np.array([0, 43, 46])
global color_upper
#color_upper = np.array([10, 255, 255])
color_lower = np.array([0,70,72])
color_upper = np.array([7, 255, 255])
Redbutton = widgets.Button(     
    value=False,     
    description='red',     
    disabled=False,     
    button_style='', # 'success', 'info', 'warning', 'danger' or ''     
    tooltip='Description',     
    icon='uncheck' )
Greenbutton = widgets.Button(     
    value=False,     
    description='green',     
    disabled=False,     
    button_style='', # 'success', 'info', 'warning', 'danger' or ''     
    tooltip='Description',     
    icon='uncheck' )
Bluebutton = widgets.Button(     
    value=False,     
    description='blue',     
    disabled=False,     
    button_style='', # 'success', 'info', 'warning', 'danger' or ''     
    tooltip='Description',     
    icon='uncheck' )
Yellowbutton = widgets.Button(     
    value=False,     
    description='yellow',     
    disabled=False,     
    button_style='', # 'success', 'info', 'warning', 'danger' or ''     
    tooltip='Description',     
    icon='uncheck' )
Orangebutton = widgets.Button(     
    value=False,     
    description='orange',     
    disabled=False,     
    button_style='', # 'success', 'info', 'warning', 'danger' or ''     
    tooltip='Description',     
    icon='uncheck' )
Closebutton = widgets.Button(     
    value=False,     
    description='close',     
    disabled=False,     
    button_style='', # 'success', 'info', 'warning', 'danger' or ''     
    tooltip='Description',     
    icon='uncheck' )
output = widgets.Output()
​
def ALL_Uncheck():
    Redbutton.icon = 'uncheck'
    Greenbutton.icon = 'uncheck'
    Bluebutton.icon = 'uncheck'
    Yellowbutton.icon = 'uncheck'
    Orangebutton.icon = 'uncheck'
    
def on_Redbutton_clicked(b):
    global color_lower, color_upper, g_mode 
    global target_valuex, target_valuey
    ALL_Uncheck()
    b.icon = 'check'
    #color_lower = np.array([0, 43, 46])
    #color_upper = np.array([10, 255, 255])
    color_lower = np.array([0,43,89])
    color_upper = np.array([7, 255, 255])
    g_mode = 1
    with output:
        bot.Ctrl_WQ2812_ALL(1,0)#红色 red
        oled.clear()
        oled.add_line("Color_Follow", 1)
        oled.add_line("color: red", 3)
        oled.refresh()
        bot.Ctrl_Servo(1,90)
        bot.Ctrl_Servo(2,10)
        print("RedButton clicked.")
​
def on_Greenbutton_clicked(b):
    global color_lower, color_upper, g_mode 
    global target_valuex, target_valuey
    ALL_Uncheck()
    b.icon = 'check'
    #color_lower = np.array([35, 43, 46])
    #color_upper = np.array([77, 255, 255])
    color_lower = np.array([54,104,64])
    color_upper = np.array([78, 255, 255])
    g_mode = 1
    with output:
        bot.Ctrl_WQ2812_ALL(1,1)#绿色 green
        oled.clear()
        oled.add_line("Color_Follow", 1)
        oled.add_line("color: green", 3)
        oled.refresh()
        bot.Ctrl_Servo(1,90)
        bot.Ctrl_Servo(2,10)
        print("GreenButton clicked.")
        
def on_Bluebutton_clicked(b):
    global color_lower, color_upper, g_mode 
    global target_valuex, target_valuey
    ALL_Uncheck()
    b.icon = 'check'
    #color_lower=np.array([100, 43, 46])
    #color_upper = np.array([124, 255, 255])
    color_lower = np.array([92,100,62])
    color_upper = np.array([121, 255, 255])
    g_mode = 1
    with output:
        bot.Ctrl_WQ2812_ALL(1,2)#蓝色
        oled.clear()
        oled.add_line("Color_Follow", 1)
        oled.add_line("color: blue", 3)
        oled.refresh()
        bot.Ctrl_Servo(1,90)
        bot.Ctrl_Servo(2,10)
        print("Bluebutton clicked.")   
​
def on_Yellowbutton_clicked(b):
    global color_lower, color_upper, g_mode 
    global target_valuex, target_valuey
    ALL_Uncheck()
    b.icon = 'check'
    #color_lower = np.array([26, 43, 46])
    #color_upper = np.array([34, 255, 255])
    color_lower = np.array([26,100,91])
    color_upper = np.array([32, 255, 255])
    g_mode = 1
    with output:
        bot.Ctrl_WQ2812_ALL(1,3)#黄色 yellow
        oled.clear()
        oled.add_line("Color_Follow", 1)
        oled.add_line("color: yellow", 3)
        oled.refresh()
        bot.Ctrl_Servo(1,90)
        bot.Ctrl_Servo(2,10)
        print("Yellowbutton clicked.")
        
def on_Orangebutton_clicked(b):
    global color_lower, color_upper, g_mode 
    global target_valuex, target_valuey
    ALL_Uncheck()
    b.icon = 'check'
    color_lower = np.array([11, 43, 46])
    color_upper = np.array([25, 255, 255])
    g_mode = 1
    with output:
        bot.Ctrl_WQ2812_brightness_ALL(255, 48, 0)
        oled.clear()
        oled.add_line("Color_Follow", 1)
        oled.add_line("color: orange", 3)
        oled.refresh()
        bot.Ctrl_Servo(1,90)
        bot.Ctrl_Servo(2,10)
        print("Orangebutton clicked.")
        
def on_Closebutton_clicked(b):  
    global g_mode 
    ALL_Uncheck()
    g_mode = 0
    with output:
        bot.Ctrl_WQ2812_ALL(0,0)
        oled.clear()
        oled.add_line("Color_Follow", 1)
        oled.add_line("color: none", 3)
        oled.refresh()
        bot.Ctrl_Servo(1,90)
        bot.Ctrl_Servo(2,10)
        print("CloseButton clicked.")
Redbutton.on_click(on_Redbutton_clicked)
Greenbutton.on_click(on_Greenbutton_clicked)
Bluebutton.on_click(on_Bluebutton_clicked)
Yellowbutton.on_click(on_Yellowbutton_clicked)
Orangebutton.on_click(on_Orangebutton_clicked)
Closebutton.on_click(on_Closebutton_clicked)
import PID
​
direction_pid = PID.PositionalPID(0.8, 0, 0.2)
​
yservo_pid = PID.PositionalPID(0.8, 0.4, 0.01)
​
speed_pid = PID.PositionalPID(1.1, 0, 0.2)
# 定义 target_servox 和 target_servoy 在外部 Define target_servox and target_servoy externally
target_servox = 90
target_servoy = 25
def servo_reset():
    bot.Ctrl_Servo(1,90)
    bot.Ctrl_Servo(2,25)
servo_reset()
def Color_Recongnize():
    oled.init_oled_process() #初始化oled进程 Initialize oled process
    global color_lower, color_upper, g_mode, first_read, while_cnt
    global color_x, target_servox,target_servoy,picture,speed_value
    t_start = time.time()
    fps = 0
    ret, frame = image.read()
    #frame = picam2.capture_array()
    #frame = cv2.resize(frame, (300, 300))
    frame = cv2.GaussianBlur(frame,(5,5),0) 
    first_read = 1
    while_cnt = 0
    speed=30
    time.sleep(1)
    while True:
        ret, frame = image.read()  
        #frame = picam2.capture_array()
        #frame = cv2.resize(frame, (300, 300))
        #frame = cv2.GaussianBlur(frame,(3,3),0)  
        hsv = cv2.cvtColor(frame,cv2.COLOR_BGR2HSV)
        mask = cv2.inRange(hsv,color_lower,color_upper)   
        mask = cv2.erode(mask,None,iterations=2)
        mask = cv2.dilate(mask,None,iterations=2)
        mask = cv2.GaussianBlur(mask,(5,5),0)
        cnts = cv2.findContours(mask.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)[-2]
        if g_mode == 1: # 按钮切换开关 Push button switch
            if len(cnts) > 0:
                cnt = max (cnts, key = cv2.contourArea)
                (color_x,color_y),color_radius = cv2.minEnclosingCircle(cnt)
​
                if color_radius > 10:
                    # 将检测到的颜色用原形线圈标记出来 Mark the detected color with a prototype circle
                    cv2.circle(frame,(int(color_x),int(color_y)),int(color_radius),(255,0,255),2)  
                    direction_pid.SystemOutput = color_x
                    direction_pid.SetStepSignal(250)
                    direction_pid.SetInertiaTime(0.01, 0.05)
                    target_valuex = int(direction_pid.SystemOutput+65)
                    #print("color_x %f", color_x)                         
                    #print("target_valuex %d", target_valuex)   
                    # 将云台转动至PID调校位置 Turn the gimbal to the PID adjustment position
​
                    if math.fabs(180 - color_y) > 75:
                        # 输入Y轴方向参数PID控制输入 Input Y-axis direction parameter PID control input
                        yservo_pid.SystemOutput = color_y
                        yservo_pid.SetStepSignal(250)
                        yservo_pid.SetInertiaTime(0.01, 0.1)
                        target_valuey = int(1150+yservo_pid.SystemOutput)
                        target_servoy = int((target_valuey-500)/10)                         
                        #print("target_servoy %d", target_servoy)  
                        if target_servoy > 110:
                            target_servoy = 110
                        if target_servoy < 0:
                            target_servoy = 0
                        #print(target_servoy)
​
​
                    speed_pid.SystemOutput = int(color_radius)
                    speed_pid.SetStepSignal(80)
                    speed_pid.SetInertiaTime(0.01, 0.1)               
                    speed_value = int(speed_pid.SystemOutput)
                    #print("color_radius %d", color_radius)
​
                    if speed_value > 255:
                        speed_value = 255
                    if speed_value < 0:
                        speed_value = 0
                        
                    if(target_valuex>70):
                        rotate_left(int(speed/6))# speed
                    elif(target_valuex<-70):
                        rotate_right(int(speed/6))
                    elif(65<color_radius<90):#调试目标半径70~90 Debug target radius 70~90
                        stop_robot()
                    elif(color_radius>90):#调试目标半径90 Debug target radius 90
                        if(abs(target_valuex)<30):
                            move_backward(speed)
                    elif(20<color_radius<75):
                        if(abs(target_valuex)<30):
                            move_forward(speed_value)
                    else:stop_robot()
​
                    bot.Ctrl_Servo(2,target_servoy)
                
                else:
                    stop_robot()
                    
            else:
                stop_robot()
        else:
            stop_robot()
​
        fps = fps + 1
        mfps = fps / (time.time() - t_start)
        cv2.putText(frame, "FPS " + str(int(mfps)), (40,40), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0,255,255), 3)
        #cv2.putText(frame, "1" , (160,120), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0,255,255), 3)
​
        image_widget.value = bgr8_to_jpeg(frame)
​
​

1. 无死区控制,实时性高,舵机会一直工作,抖动频繁;

display(image_widget)
display(Redbutton, Greenbutton, Bluebutton, Yellowbutton, Orangebutton, Closebutton, output)
thread1 = threading.Thread(target=Color_Recongnize)
thread1.setdaemon=True
thread1.start()

2. 带死区控制,跟随实时性差一些,舵机在死区范围内不运动,抖动较稳定;

stop_thread(thread1)
servo_reset()
#使用完成对象记住释放掉对象,不然下一个程序使用这个对象模块会被占用,导致无法使用# Release resources
​
# picam2.stop()
# picam2.close()
image.release()
stop_robot()    

        跟随是依据识别颜色在图像中呈现的大小进行接近的,也就是物体越小需要靠得越近才会停止接近,物体越大可能离得很远就不接近。

三、实验现象

        代码块运行后,我们可以通过按钮控制小车的跟随不同的颜色,选择后,小车会随着带颜色的物体前后左右运动。同时RGB灯条也会亮起识别的颜色,oled显示识别的颜色因摄像头受光线影响较大。若效果不好时,需要调节代码里识别的颜色的hsv值。

 


http://www.kler.cn/a/419343.html

相关文章:

  • 《如何使用Unity的Avatar人偶以及启动重定向-实现2个或多个人物模型使用同一个动画片段》
  • Kali Linux系统一键汉化中文版及基础使用详细教程
  • 32 从前序与中序遍历序列构造二叉树
  • Docker for Everyone Plus——No Enough Privilege
  • CENet及多模态情感计算实战
  • JVM 性能调优 -- JVM常用调优工具【jps、jstack、jmap、jstats 命令】
  • 每日速记10道java面试题06
  • 七、Python —— 元组、集合和字典
  • windows部署PaddleSpeech详细教程
  • 解决Ubuntu下无法远程登录
  • Qt中QGraphics绘图类相关解释
  • Python PDF转JPG图片小工具
  • 深度学习-48-AI应用实战之基于face_recognition的人脸识别
  • 【AI日记】24.12.01 kaggle 比赛 Titanic-4
  • gitee:删除仓库
  • 【大模型】深度解析 NLP 模型5大评估指标及 应用案例:从 BLEU、ROUGE、PPL 到METEOR、BERTScore
  • Doris 2.1.7镜像制作
  • 【Figma】中文版安装
  • 【智能流体力学】RAG大模型方法:解决固体力学和流体动力学问题
  • 【优选算法篇】滑动窗口的艺术:如何动态调整子区间解决复杂问题(中篇)
  • 高德应用OceanBase云数据库的升级选型与迁移干货
  • MATLAB中exportgraphics函数用法
  • 【数据库设计】如何根据UI界面设计数据库结构
  • 马铃薯病害识别(VGG-16复现)
  • 【openssl】相关指令
  • day01(Linux底层)基础知识