OpenCV物體跟蹤樹莓派視覺小車實(shí)現(xiàn)過程學(xué)習(xí)
物體跟蹤效果展示




過程:
一、初始化
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()
二、運(yùn)動控制函數(shù)
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
三、舵機(jī)角度控制
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):是頂部的舵機(jī)(攝像頭上下擺動的那個舵機(jī))
下面的(5):是底部的舵機(jī)(攝像頭左右擺動的那個舵機(jī))
四、攝像頭&&圖像處理
# 1 Image Process
img, contours = Image_Processing()
width, height = 160, 120
camera = cv2.VideoCapture(0)
camera.set(3,width)
camera.set(4,height)
1、打開攝像頭
打開攝像頭,并設(shè)置窗口大小。
設(shè)置小窗口的原因: 小窗口實(shí)時性比較好。
# Capture the frames
ret, frame = camera.read()

2、把圖像轉(zhuǎn)換為灰度圖
# to gray
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cv2.imshow('gray',gray)

3、 高斯濾波(去噪)
# Gausi blur
blur = cv2.GaussianBlur(gray,(5,5),0)
4、亮度增強(qiáng)
#brighten
blur = cv2.convertScaleAbs(blur, None, 1.5, 30)
5、轉(zhuǎn)換為二進(jìn)制
#to binary
ret,binary = cv2.threshold(blur,150,255,cv2.THRESH_BINARY_INV)
cv2.imshow('binary',binary)

6、閉運(yùn)算處理
#Close
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (17,17))
close = cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel)
cv2.imshow('close',close)

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)

代碼
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
五、獲取最大輪廓坐標(biāo)
由于有可能出現(xiàn)多個物體,我們這里只識別最大的物體(深度學(xué)習(xí)可以搞分類,還沒學(xué)到這,學(xué)到了再做),得到它的坐標(biāo)。
# 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
返回最大輪廓的坐標(biāo):

六、運(yùn)動
根據(jù)反饋回來的坐標(biāo),判斷它的位置,進(jìn)行運(yùn)動。
# 3 Move
Move(x,y)
1、沒有識別到輪廓(靜止)
if x==0 and y==0:
Stop()
2、向前走
識別到物體,且在正中央(中間1/2區(qū)域),讓物體向前走。
#go ahead
elif width/4 <x and x<(width-width/4):
Front(70)
3、向左轉(zhuǎn)
物體在左邊1/4區(qū)域。
#left
elif x < width/4:
Left(50)
4、向右轉(zhuǎn)
物體在右邊1/4區(qū)域。
#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()
檢測原理是基于最大輪廓的檢測,沒有用深度學(xué)習(xí)的分類,所以容易受到干擾,后期學(xué)完深度學(xué)習(xí)會繼續(xù)優(yōu)化。有意見或者想法的朋友歡迎交流。
以上就是OpenCV物體跟蹤樹莓派視覺小車實(shí)現(xiàn)過程學(xué)習(xí)的詳細(xì)內(nèi)容,更多關(guān)于OpenCV物體跟蹤樹莓派視覺小車的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
pytorch獲取模型某一層參數(shù)名及參數(shù)值方式
今天小編就為大家分享一篇pytorch獲取模型某一層參數(shù)名及參數(shù)值方式,具有很好的價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-12-12
Python 中pandas.read_excel詳細(xì)介紹
這篇文章主要介紹了Python 中pandas.read_excel詳細(xì)介紹的相關(guān)資料,需要的朋友可以參考下2017-06-06
Python的網(wǎng)絡(luò)編程庫Gevent的安裝及使用技巧
Gevent庫的奧義在于并發(fā)式的高性能網(wǎng)絡(luò)程序設(shè)計支持,這里我們將來講解Python的網(wǎng)絡(luò)編程庫Gevent的安裝及使用技巧,來看一下Gevent支持的多進(jìn)程程序編寫:2016-06-06
Python3.10.4激活venv環(huán)境失敗解決方法
這篇文章主要介紹了Python3.10.4激活venv環(huán)境失敗解決方法的相關(guān)資料,需要的朋友可以參考下2023-01-01

