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

要完成功能:

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部分

你可能感兴趣的:(之前文章,python,计算机视觉,opencv)