循迹识别小车:(三)树莓派部分

要完成功能:

1、目标识别:通过树莓派上的摄像头模块(Pi Cam)进行颜色识别,如果发现绿色的圆,即发现目标,则显示发现目标。
2、完成与STM32的串口通信。

准备工作:

本项目的树莓派图像识别我只是进行了简单的识别绿色圆,如果有需要请自行进行修改。

1、树莓派烧录系统:

在总项目文件中有介绍文档:总项目文件下载链接
也可参考本人文章:树莓派3b+系统(镜像)烧录

2、树莓派安装OpenCV环境:

图像识别方面我采用了OpenCV相关的库,所有需要在树莓派中先安装OpenCV环境,这也是我在做本项目最恶心的地方,在安装OpenCV环境时总是出一些奇奇怪怪的错误。下面是我安装成功的参考:
在总项目文件中有介绍文档:总项目文件下载链接
也可参考本人文章:树莓派3b+的OpenCV环境安装

3、串口通信:

在总项目文件中有介绍文档:总项目文件下载链接
也可参考本人文章:串口通信(树莓派3b+)

4、摄像头模块(Pi Cam)的安装使用

在总项目文件中有介绍文档:总项目文件下载链接
也可参考本人文章:树莓派摄像头模块(Pi Cam)的安装使用

目标识别

1、颜色识别:

# Function: Color recognition
# return: 1 red  2 blue  3 green

def color_demo(cl_img):
    
    # 常数设置和初始化
    area_red = 0  # 颜色框面积
    area_blue = 0
    area_green = 0
    len_const = 3000  # 限定颜色框面积大小的常数
    judge_const = 0  # 判断常数。0为没发现目标物,大于0为发现目标物
    frame3 = cl_img  # 传入照片(相当于函数参数)

    while True:
        hsv = cv.cvtColor(frame3, cv.COLOR_BGR2HSV)# 转换颜色空间 BGR 到 HSV
        # 定义HSV中蓝色的范围
        lower_red = np.array([0, 100, 80])  # 红色阈值下界
        higher_red = np.array([10, 255, 255])  # 红色阈值上界
        lower_blue = np.array([100, 43, 46])
        higher_blue = np.array([124, 255, 255])
        lower_green = np.array([35, 43, 46])
        higher_green = np.array([77, 255, 255])

        #mask = cv.inRange(hsv, lower_blue, upper_blue)# 设置HSV的阈值使得只取蓝色
        mask_red = cv2.inRange(hsv, lower_red, higher_red)  # 可以认为是过滤出红色部分,获得红色的掩膜
        mask_green = cv2.inRange(hsv, lower_green, higher_green)  # 获得绿色部分掩膜
        mask_blue = cv2.inRange(hsv, lower_blue, higher_blue)  # 获得蓝色部分掩膜
        mask_green = cv2.medianBlur(mask_green, 7)  # 中值滤波
        mask_red = cv2.medianBlur(mask_red, 7)  # 中值滤波
        mask_blue = cv2.medianBlur(mask_blue, 7)  # 中值滤波

        # 将掩膜和图像逐像素相加
        # res = cv.bitwise_and(frame, frame, mask=mask)
        # mask = cv2.bitwise_or(mask_green, mask_red, mask_blue)  # 三部分掩膜进行按位或运算
        
        # cnts3, hierarchy3 = cv2.findContours(mask_green, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) # 轮廓检测 #绿色 
        _,cnts1,hierarchy1 = cv2.findContours(mask_red, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) 
        _,cnts2,hierarchy2 = cv2.findContours(mask_blue, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)  
        _,cnts3,hierarchy3 = cv2.findContours(mask_green, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)  
 
       # while(cv2.waitKey(1) & 0xFF == ord('q')):
        for cnt in cnts1:
            (x, y, w, h) = cv2.boundingRect(cnt)  # 该函数返回矩阵四个点
            if (w * h) > len_const:
                cv2.rectangle(frame3, (x, y), (x + w, y + h), (0, 0, 255), 2)  # 将检测到的颜色框起来 
                cv2.putText(frame3, 'red', (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
                area_red = area_red + (w * h)
        for cnt in cnts2:
            (x, y, w, h) = cv2.boundingRect(cnt)
            if (w * h) > len_const:
                cv2.rectangle(frame3, (x, y), (x + w, y + h), (255, 0, 0), 2) 
                cv2.putText(frame3, 'blue', (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 0, 0), 2)
                area_blue = area_blue + (w * h)
        for cnt in cnts3:
            (x, y, w, h) = cv2.boundingRect(cnt)  
            if (w * h) > len_const:
                cv2.rectangle(frame3, (x, y), (x + w, y + h), (0, 255, 0), 2)  
                cv2.putText(frame3, 'green', (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
                area_green = area_green + (w * h)

        if area_red > area_blue:#1 red  2 blue  3 green
            if area_blue > area_green:
                judge_const = 1
                print("max:red-{}".format(area_red))
            elif area_blue < area_green:
                if area_red > area_green:
                    judge_const = 1
                    print("max:red-{}".format(area_red))
                elif area_red < area_green:
                    judge_const = 3
                    print("max:green-{}".format(area_green))
        elif area_red < area_blue:
            if area_red > area_green:
                judge_const = 2
                print("max:blue-{}".format(area_blue))
            elif area_red < area_green:
                if area_green > area_blue:
                    judge_const = 3
                    print("max:green-{}".format(area_green))
                elif area_green < area_blue:
                    judge_const = 2
                    print("max:blue-{}".format(area_blue))
        
        # 判断追踪到的目标颜色
        if judge_const == 1 and cv.waitKey(500) & 0xFF:
            print("target color:red")
            return 1
        elif judge_const == 2 and cv.waitKey(500) & 0xFF:
            print("target color:blue")
            return 2
        elif judge_const == 3 and cv.waitKey(500) & 0xFF:
            print("target color:green")
            return 3


        # areas = area_green + area_blue + area_red
        cv2.imshow('frame3', frame3)
        print("No target color")
        return 0

2、测试距离:

import cv2 
import time 
import numpy as np
 
#设定蓝色阈值,HSV空间 
blueLower = np.array([80, 100, 100]) 
blueUpper = np.array([100, 255, 255])
 
#打开摄像头 
camera = cv2.VideoCapture(0)
 
#创建一个xianshifangfa 
def ceju_xianshi(): 
    while True: 
        # 读取帧 
        (ret, frame) = camera.read()
         frame = cv2.flip(frame, 1, dst=None)  # 水平翻转镜像
 
        # 判断是否成功打开摄像头 
        if not ret: 
            print('No Camera') 
            break
 
        # 转到HSV空间 
        hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
 
        # 根据阈值构建掩膜 
        mask = cv2.inRange(hsv, blueLower, blueUpper)
 
        # 腐蚀操作 
        mask = cv2.erode(mask, None, iterations=2)
 
        # 膨胀操作,其实先腐蚀再膨胀的效果是开运算,去除噪点 
        mask = cv2.dilate(mask, None, iterations=2)
 
        # 轮廓检测 
        cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2]
 
        # 如果存在轮廓 
        if len(cnts) > 0: 
            # 找到面积最大的轮廓 
            c = max(cnts, key=cv2.contourArea)
 
            # 确定面积最大的轮廓的矩形 
            x, y, w, h = cv2.boundingRect(c)
 
            #计算目标距离 
            juli = (1029.006/w)*2.54
            juli1 = str(juli)            
 
            # 输出距离 
            print("juli",juli1)
            print("shijikuandu",w)
 
            # 显示矩形框 
            cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 0, 255), 2)
            cv2.putText(frame, juli1, (30, 300), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 3)#shipin_zhong,xinshi_juli
 
        cv2.imshow('Frame', frame)
        cv2.waitKey(1)
        # 摄像头释放
        
if __name__ == '__main__': 
    ceju_xianshi()

3、总程序:

import cv2
import math,serial,numpy,time
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt

# Function: Color recognition
# return: 1 red  2 blue  3 green
def color_demo(cl_img):
    
    area_red = 0   
    area_blue = 0
    area_green = 0
    len_const = 3000  
    judge_const = 0  
    frame3 = cl_img  

    while True:
       
        hsv = cv.cvtColor(frame3, cv.COLOR_BGR2HSV)
       
        lower_red = np.array([0, 100, 80]) 
        higher_red = np.array([10, 255, 255]) 
        lower_blue = np.array([100, 43, 46])
        higher_blue = np.array([124, 255, 255])
        lower_green = np.array([35, 43, 46])
        higher_green = np.array([77, 255, 255])

        # mask = cv.inRange(hsv, lower_blue, upper_blue)
        mask_red = cv2.inRange(hsv, lower_red, higher_red)  
        mask_green = cv2.inRange(hsv, lower_green, higher_green)  
        mask_blue = cv2.inRange(hsv, lower_blue, higher_blue) 
        mask_green = cv2.medianBlur(mask_green, 7) 
        mask_red = cv2.medianBlur(mask_red, 7) 
        mask_blue = cv2.medianBlur(mask_blue, 7) 

       
        # res = cv.bitwise_and(frame, frame, mask=mask)
        # mask = cv2.bitwise_or(mask_green, mask_red, mask_blue)  
        
        # cnts3, hierarchy3 = cv2.findContours(mask_green, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)  
        _,cnts1,hierarchy1 = cv2.findContours(mask_red, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) 
        _,cnts2,hierarchy2 = cv2.findContours(mask_blue, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)  
        _,cnts3,hierarchy3 = cv2.findContours(mask_green, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)  
 
       # while(cv2.waitKey(1) & 0xFF == ord('q')):
        for cnt in cnts1:
            (x, y, w, h) = cv2.boundingRect(cnt)  
            if (w * h) > len_const:
                cv2.rectangle(frame3, (x, y), (x + w, y + h), (0, 0, 255), 2)  
                cv2.putText(frame3, 'red', (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
                area_red = area_red + (w * h)
        for cnt in cnts2:
            (x, y, w, h) = cv2.boundingRect(cnt)
            if (w * h) > len_const:
                cv2.rectangle(frame3, (x, y), (x + w, y + h), (255, 0, 0), 2) 
                cv2.putText(frame3, 'blue', (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 0, 0), 2)
                area_blue = area_blue + (w * h)
        for cnt in cnts3:
            (x, y, w, h) = cv2.boundingRect(cnt)  
            if (w * h) > len_const:
                cv2.rectangle(frame3, (x, y), (x + w, y + h), (0, 255, 0), 2)  
                cv2.putText(frame3, 'green', (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
                area_green = area_green + (w * h)

        if area_red > area_blue:#1 red  2 blue  3 green
            if area_blue > area_green:
                judge_const = 1
                print("max:red-{}".format(area_red))
            elif area_blue < area_green:
                if area_red > area_green:
                    judge_const = 1
                    print("max:red-{}".format(area_red))
                elif area_red < area_green:
                    judge_const = 3
                    print("max:green-{}".format(area_green))
        elif area_red < area_blue:
            if area_red > area_green:
                judge_const = 2
                print("max:blue-{}".format(area_blue))
            elif area_red < area_green:
                if area_green > area_blue:
                    judge_const = 3
                    print("max:green-{}".format(area_green))
                elif area_green < area_blue:
                    judge_const = 2
                    print("max:blue-{}".format(area_blue))
        
        
        if judge_const == 1 and cv.waitKey(500) & 0xFF:
            print("target color:red")
            return 1
        elif judge_const == 2 and cv.waitKey(500) & 0xFF:
            print("target color:blue")
            return 2
        elif judge_const == 3 and cv.waitKey(500) & 0xFF:
            print("target color:green")
            return 3


        # areas = area_green + area_blue + area_red
        cv2.imshow('frame3', frame3)
        print("No target color")
        return 0

# Function: Test distance
#
def ceju_xianshi():
 
    while True:
        (ret, frame) = cap.read()
        frame = cv2.flip(frame, -1, dst=None) 
 
        hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
        mask = cv2.inRange(hsv, blueLower, blueUpper)
        mask = cv2.erode(mask, None, iterations=2)
        mask = cv2.dilate(mask, None, iterations=2)
        cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2] 
        
        if len(cnts) > 0:
            c = max(cnts, key=cv2.contourArea)
            x, y, w, h = cv2.boundingRect(c)
            
            juli = (1029.006/w)*2.54
            juli1 = str(juli)
 
            print("juli",juli1)
            print("shijikuandu",w)
 
            cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 0, 255), 2)
            cv2.putText(frame, juli1, (30, 300), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 3)#shipin_zhong,xinshi_juli
 
        cv2.imshow('Frame', frame)
        cv2.waitKey(1)
        break

if __name__ == '__main__':

    ser = serial.Serial('/dev/ttyAMA0', 9600)
    cap = cv.VideoCapture(0)  
    if not cap.isOpened():  
        print("NO PI")
        exit()
    
    try:
        while True:
            size = ser.inWaiting()              
            if size != 0:
                response = ser.read(size)        
                print(response) 
                while response==b'B': #begin pi work
                    print("flagPi = 1 ")
                    
                    rets, frame = cap.read()
                    color_img = cv.imread('/home/pi/Desktop/WindowsLogo.jpg')
            
                    k = color_demo(frame)  #1 red  2 blue  3 green
                    if k==3:
                      print("STM32_work")
                      ser.write(b'F\r\n')  #found target
                      ser.flushInput()                
                      response = b'E'  #end pi work
                      break                  
            
            cv2.destroyAllWindows()
                 
    except KeyboardInterrupt:
        ser.close()

资源链接:

总项目文件:下载链接

上一篇文章:循迹识别小车:(二)STM32部分

下一篇文章:循迹识别小车:(四)OpenMV4部分

  • 6
    点赞
  • 132
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
小车使用了红外对管循迹,超声波测距,颜色传感器,直流减速电机,180°舵机,步进电机。 该资源包含小车的所有完整程序,原理图,PCB图,题目要求。 把题目简单介绍下: 寻迹智能电动车(本科大大四题) 一、任务 设计并制作一个寻迹智能电动车,根据要求完成从出发区到终点区的任务: 二、要求 1、基本要求 (1)电动车从出发区出发(车体不得超出出发区),沿引导黑线向终点区行驶,电动车行驶过程中不可脱离黑色引导线行驶。 (2)电动车行驶过程中遇到十字路口时发出声光指示信息。 (3)电动车行驶过程中遇到障碍物。电动车必须避开障碍通过且不得与其接触。 (4)电动车到达终点后应立即停车,但全程行驶时间不能大于90秒,行驶时间达到90秒时必须立即自动停车。 2、发挥部分 (1)电动车行驶过程中遇到红色障碍物电动车必须选择向左转避开障碍物,遇到绿色障碍物电动车必须选择向右转避开障碍物。 (2)电动车避开障碍物通过不得与其接触且选择最短行驶距离到达终点区。 (3)电动车进入终点区域后,能进一步准确驶入终点区,要求电动车的车身完全进入终点区到达终点区中心。停车后,能准确显示电动车全程行驶时间和路程。 、评分标准 项 目 满分 基本要求 完成第(1)项 10 完成第(2)项 12 完成第(3)项 15 完成第(4)项 13 发挥部分 完成第(1)项 20 完成第(2)项 12 完成第(3)项 8 其它 10 四、说明 1、场地上面铺设白纸,可用一张A0或者两张A1纸制作。 2、场地的引导线宽度2cm,可以涂墨或粘黑色胶带。示意图中的和尺寸标注线不要绘制在白纸上,出发区和终点区的边框为25cm*25cm 用签字笔细线标注。 3、电动车出发方向由测评专家指定,可选择(如图)正X方向或正Y方向。 3、障碍物可由包有红、绿色纸的长方体制作,其长、宽、高约为62mm 62mm 87mm(可用几张扑克牌制作长方体),场地上可允许有最多两个障碍物(也可只有一个,也可以放置两个同色或者不同色的障碍物,由测评专家指定),放置位置可在任意十字路口中间位置(T字路口不放置,障碍物面向电动车放置)。 4、电动车允许用玩具车改装,但不能由人工遥控,其外围尺寸(含车体上附加装置)的限制为:长度≤30cm,宽度≤20cm。 5、要求在电动车顶部明显标出电动车的中心点位置,即横向与纵向两条中心线的交点。 6、以图的左下角为坐标原点。 由于该程序是我2个月的心血,所以10分,不要嫌分多,肯定物超所值。 文件列表: 循迹主系统修正版.ddb 智能循迹小车程序 智能循迹小车程序 颜色传感器 HC-SR04超声波测距模块.pdf 步进电机工作原理及使用说明.pdf 舵机舵机的工作原理.pdf 利用单片机PWM进行舵机控制.pdf 颜色传感器产品使用手册.doc 寻迹智能电动车(本科).doc

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值