网络编程
位置:首页>> 网络编程>> Python编程>> OpenCV物体跟踪树莓派视觉小车实现过程学习

OpenCV物体跟踪树莓派视觉小车实现过程学习

作者:_睿智_  发布时间:2021-09-15 21:55:48 

标签:OpenCV,树莓派视觉,物体跟踪

物体跟踪效果展示

OpenCV物体跟踪树莓派视觉小车实现过程学习 

OpenCV物体跟踪树莓派视觉小车实现过程学习

OpenCV物体跟踪树莓派视觉小车实现过程学习

OpenCV物体跟踪树莓派视觉小车实现过程学习

OpenCV物体跟踪树莓派视觉小车实现过程学习

过程:

一、初始化


def Motor_Init():
   global L_Motor, R_Motor
   L_Motor= GPIO.PWM(l_motor,100)
   R_Motor = GPIO.PWM(r_motor,100)
   L_Motor.start(0)
   R_Motor.start(0)
def Direction_Init():
   GPIO.setup(left_back,GPIO.OUT)
   GPIO.setup(left_front,GPIO.OUT)
   GPIO.setup(l_motor,GPIO.OUT)

GPIO.setup(right_front,GPIO.OUT)
   GPIO.setup(right_back,GPIO.OUT)
   GPIO.setup(r_motor,GPIO.OUT)  
def Servo_Init():
   global pwm_servo
   pwm_servo=Adafruit_PCA9685.PCA9685()
def Init():
   GPIO.setwarnings(False)
   GPIO.setmode(GPIO.BCM)
   Direction_Init()
   Servo_Init()
   Motor_Init()

二、运动控制函数


def Front(speed):
   L_Motor.ChangeDutyCycle(speed)
   GPIO.output(left_front,1)   #left_front
   GPIO.output(left_back,0)    #left_back
   R_Motor.ChangeDutyCycle(speed)
   GPIO.output(right_front,1)  #right_front
   GPIO.output(right_back,0)   #right_back      
def Back(speed):
   L_Motor.ChangeDutyCycle(speed)
   GPIO.output(left_front,0)   #left_front
   GPIO.output(left_back,1)    #left_back
   R_Motor.ChangeDutyCycle(speed)
   GPIO.output(right_front,0)  #right_front
   GPIO.output(right_back,1)   #right_back
def Left(speed):
   L_Motor.ChangeDutyCycle(speed)
   GPIO.output(left_front,0)   #left_front
   GPIO.output(left_back,1)    #left_back
   R_Motor.ChangeDutyCycle(speed)
   GPIO.output(right_front,1)  #right_front
   GPIO.output(right_back,0)   #right_back
def Right(speed):
   L_Motor.ChangeDutyCycle(speed)
   GPIO.output(left_front,1)   #left_front
   GPIO.output(left_back,0)    #left_back
   R_Motor.ChangeDutyCycle(speed)
   GPIO.output(right_front,0)  #right_front
   GPIO.output(right_back,1)   #right_back
def Stop():
   L_Motor.ChangeDutyCycle(0)
   GPIO.output(left_front,0)   #left_front
   GPIO.output(left_back,0)    #left_back
   R_Motor.ChangeDutyCycle(0)
   GPIO.output(right_front,0)  #right_front
   GPIO.output(right_back,0)   #right_back

三、舵机角度控制


def set_servo_angle(channel,angle):
   angle=4096*((angle*11)+500)/20000
   pwm_servo.set_pwm_freq(50)                #frequency==50Hz (servo)
   pwm_servo.set_pwm(channel,0,int(angle))

set_servo_angle(4, 110)     #top servo     lengthwise
   #0:back    180:front    
   set_servo_angle(5, 90)     #bottom servo  crosswise
   #0:left    180:right

上面的(4):是顶部的舵机(摄像头上下摆动的那个舵机)

下面的(5):是底部的舵机(摄像头左右摆动的那个舵机)

四、摄像头&&图像处理


# 1 Image Process
       img, contours = Image_Processing()

width, height = 160, 120
   camera = cv2.VideoCapture(0)
   camera.set(3,width)
   camera.set(4,height)

1、打开摄像头

打开摄像头,并设置窗口大小。

设置小窗口的原因: 小窗口实时性比较好。


# Capture the frames
   ret, frame = camera.read()

OpenCV物体跟踪树莓派视觉小车实现过程学习

2、把图像转换为灰度图


# to gray
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cv2.imshow('gray',gray)

OpenCV物体跟踪树莓派视觉小车实现过程学习

3、 高斯滤波(去噪)


# Gausi blur
   blur = cv2.GaussianBlur(gray,(5,5),0)

4、亮度增强


#brighten
   blur = cv2.convertScaleAbs(blur, None, 1.5, 30)

5、转换为二进制


#to binary
   ret,binary = cv2.threshold(blur,150,255,cv2.THRESH_BINARY_INV)
   cv2.imshow('binary',binary)

OpenCV物体跟踪树莓派视觉小车实现过程学习

6、闭运算处理


#Close
   kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (17,17))
   close = cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel)
   cv2.imshow('close',close)

OpenCV物体跟踪树莓派视觉小车实现过程学习

7、获取轮廓


#get contours
   binary_c,contours,hierarchy = cv2.findContours(close, 1, cv2.CHAIN_APPROX_NONE)
   cv2.drawContours(image, contours, -1, (255,0,255), 2)
   cv2.imshow('image', image)

OpenCV物体跟踪树莓派视觉小车实现过程学习

代码


def Image_Processing():
   # Capture the frames
   ret, frame = camera.read()
   # Crop the image
   image = frame
   cv2.imshow('frame',frame)
   # to gray
   gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
   cv2.imshow('gray',gray)
   # Gausi blur
   blur = cv2.GaussianBlur(gray,(5,5),0)
   #brighten
   blur = cv2.convertScaleAbs(blur, None, 1.5, 30)
   #to binary
   ret,binary = cv2.threshold(blur,150,255,cv2.THRESH_BINARY_INV)
   cv2.imshow('binary',binary)
   #Close
   kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (17,17))
   close = cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel)
   cv2.imshow('close',close)
   #get contours
   binary_c,contours,hierarchy = cv2.findContours(close, 1, cv2.CHAIN_APPROX_NONE)
   cv2.drawContours(image, contours, -1, (255,0,255), 2)
   cv2.imshow('image', image)
   return frame, contours

五、获取最大轮廓坐标

由于有可能出现多个物体,我们这里只识别最大的物体(深度学习可以搞分类,还没学到这,学到了再做),得到它的坐标。


# 2 get coordinates
       x, y = Get_Coord(img, contours)

def Get_Coord(img, contours):
   image = img.copy()
   try:
       contour = max(contours, key=cv2.contourArea)
       cv2.drawContours(image, contour, -1, (255,0,255), 2)
       cv2.imshow('new_frame', image)
       # get coord
       M = cv2.moments(contour)
       x = int(M['m10']/M['m00'])
       y = int(M['m01']/M['m00'])
       print(x, y)
       return x,y

except:
       print 'no objects'
       return 0,0

返回最大轮廓的坐标:

OpenCV物体跟踪树莓派视觉小车实现过程学习

六、运动

根据反馈回来的坐标,判断它的位置,进行运动。


# 3 Move
       Move(x,y)

1、没有识别到轮廓(静止)


   if x==0 and y==0:
       Stop()

2、向前走

识别到物体,且在正中央(中间1/2区域),让物体向前走。


#go ahead
   elif width/4 <x and x<(width-width/4):
       Front(70)

3、向左转

物体在左边1/4区域。


#left
   elif x < width/4:
       Left(50)

4、向右转

物体在右边1/4区域。


#Right
   elif x > (width-width/4):
       Right(50)

代码


def Move(x,y):
   global second
   #stop
   if x==0 and y==0:
       Stop()
   #go ahead
   elif width/4 <x and x<(width-width/4):
       Front(70)
   #left
   elif x < width/4:
       Left(50)
   #Right
   elif x > (width-width/4):
       Right(50)

总代码


#Object Tracking
import  RPi.GPIO as GPIO
import time
import Adafruit_PCA9685
import numpy as np
import cv2
second = 0
width, height = 160, 120
camera = cv2.VideoCapture(0)
camera.set(3,width)
camera.set(4,height)
l_motor = 18
left_front   =  22
left_back   =  27
r_motor = 23
right_front   = 25
right_back  =  24
def Motor_Init():
   global L_Motor, R_Motor
   L_Motor= GPIO.PWM(l_motor,100)
   R_Motor = GPIO.PWM(r_motor,100)
   L_Motor.start(0)
   R_Motor.start(0)
def Direction_Init():
   GPIO.setup(left_back,GPIO.OUT)
   GPIO.setup(left_front,GPIO.OUT)
   GPIO.setup(l_motor,GPIO.OUT)    
   GPIO.setup(right_front,GPIO.OUT)
   GPIO.setup(right_back,GPIO.OUT)
   GPIO.setup(r_motor,GPIO.OUT)
def Servo_Init():
   global pwm_servo
   pwm_servo=Adafruit_PCA9685.PCA9685()
def Init():
   GPIO.setwarnings(False)
   GPIO.setmode(GPIO.BCM)
   Direction_Init()
   Servo_Init()
   Motor_Init()
def Front(speed):
   L_Motor.ChangeDutyCycle(speed)
   GPIO.output(left_front,1)   #left_front
   GPIO.output(left_back,0)    #left_back
   R_Motor.ChangeDutyCycle(speed)
   GPIO.output(right_front,1)  #right_front
   GPIO.output(right_back,0)   #right_back  
def Back(speed):
   L_Motor.ChangeDutyCycle(speed)
   GPIO.output(left_front,0)   #left_front
   GPIO.output(left_back,1)    #left_back
   R_Motor.ChangeDutyCycle(speed)
   GPIO.output(right_front,0)  #right_front
   GPIO.output(right_back,1)   #right_back
def Left(speed):
   L_Motor.ChangeDutyCycle(speed)
   GPIO.output(left_front,0)   #left_front
   GPIO.output(left_back,1)    #left_back
   R_Motor.ChangeDutyCycle(speed)
   GPIO.output(right_front,1)  #right_front
   GPIO.output(right_back,0)   #right_back  
def Right(speed):
   L_Motor.ChangeDutyCycle(speed)
   GPIO.output(left_front,1)   #left_front
   GPIO.output(left_back,0)    #left_back
   R_Motor.ChangeDutyCycle(speed)
   GPIO.output(right_front,0)  #right_front
   GPIO.output(right_back,1)   #right_back
def Stop():
   L_Motor.ChangeDutyCycle(0)
   GPIO.output(left_front,0)   #left_front
   GPIO.output(left_back,0)    #left_back
   R_Motor.ChangeDutyCycle(0)
   GPIO.output(right_front,0)  #right_front
   GPIO.output(right_back,0)   #right_back
def set_servo_angle(channel,angle):
   angle=4096*((angle*11)+500)/20000
   pwm_servo.set_pwm_freq(50)                #frequency==50Hz (servo)
   pwm_servo.set_pwm(channel,0,int(angle))
def Image_Processing():
   # Capture the frames
   ret, frame = camera.read()
   # Crop the image
   image = frame
   cv2.imshow('frame',frame)
   # to gray
   gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
   cv2.imshow('gray',gray)
   # Gausi blur
   blur = cv2.GaussianBlur(gray,(5,5),0)
   #brighten
   blur = cv2.convertScaleAbs(blur, None, 1.5, 30)
   #to binary
   ret,binary = cv2.threshold(blur,150,255,cv2.THRESH_BINARY_INV)
   cv2.imshow('binary',binary)
   #Close
   kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (17,17))
   close = cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel)
   cv2.imshow('close',close)
   #get contours
   binary_c,contours,hierarchy = cv2.findContours(close, 1, cv2.CHAIN_APPROX_NONE)
   cv2.drawContours(image, contours, -1, (255,0,255), 2)
   cv2.imshow('image', image)
   return frame, contours
def Get_Coord(img, contours):
   image = img.copy()
   try:
       contour = max(contours, key=cv2.contourArea)
       cv2.drawContours(image, contour, -1, (255,0,255), 2)
       cv2.imshow('new_frame', image)
       # get coord
       M = cv2.moments(contour)
       x = int(M['m10']/M['m00'])
       y = int(M['m01']/M['m00'])
       print(x, y)
       return x,y        
   except:
       print 'no objects'
       return 0,0    
def Move(x,y):
   global second
   #stop
   if x==0 and y==0:
       Stop()
   #go ahead
   elif width/4 <x and x<(width-width/4):
       Front(70)
   #left
   elif x < width/4:
       Left(50)
   #Right
   elif x > (width-width/4):
       Right(50)  
if __name__ == '__main__':
   Init()    
   set_servo_angle(4, 110)     #top servo     lengthwise
   #0:back    180:front    
   set_servo_angle(5, 90)     #bottom servo  crosswise
   #0:left    180:right      
   while 1:
       # 1 Image Process
       img, contours = Image_Processing()
       # 2 get coordinates
       x, y = Get_Coord(img, contours)
       # 3 Move
       Move(x,y)      
       # must include this codes(otherwise you can't open camera successfully)
       if cv2.waitKey(1) & 0xFF == ord('q'):
           Stop()
           GPIO.cleanup()    
           break    
   #Front(50)
   #Back(50)
   #$Left(50)
   #Right(50)
   #time.sleep(1)
   #Stop()

检测原理是基于最大轮廓的检测,没有用深度学习的分类,所以容易受到干扰,后期学完深度学习会继续优化。有意见或者想法的朋友欢迎交流。

来源:https://blog.csdn.net/great_yzl/article/details/120338859

0
投稿

猜你喜欢

手机版 网络编程 asp之家 www.aspxhome.com