您好,登錄后才能下訂單哦!
這篇文章主要講解了“怎么實(shí)現(xiàn)OpenCV物體跟蹤樹莓派視覺小車效果”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“怎么實(shí)現(xiàn)OpenCV物體跟蹤樹莓派視覺小車效果”吧!
一、初始化
二、運(yùn)動(dòng)控制函數(shù)
三、舵機(jī)角度控制
四、攝像頭&&圖像處理
1、打開攝像頭
2、把圖像轉(zhuǎn)換為灰度圖
3、 高斯濾波(去噪)
4、亮度增強(qiáng)
5、轉(zhuǎn)換為二進(jìn)制
6、閉運(yùn)算處理
7、獲取輪廓
代碼
五、獲取最大輪廓坐標(biāo)
六、運(yùn)動(dòng)
1、沒有識別到輪廓(靜止)
2、向前走
3、向左轉(zhuǎn)
4、向右轉(zhuǎn)
代碼
總代碼
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):是頂部的舵機(jī)(攝像頭上下擺動(dòng)的那個(gè)舵機(jī))
下面的(5):是底部的舵機(jī)(攝像頭左右擺動(dòng)的那個(gè)舵機(jī))
# 1 Image Process img, contours = Image_Processing()
width, height = 160, 120 camera = cv2.VideoCapture(0) camera.set(3,width) camera.set(4,height)
打開攝像頭,并設(shè)置窗口大小。
設(shè)置小窗口的原因: 小窗口實(shí)時(shí)性比較好。
# Capture the frames ret, frame = camera.read()
# 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)
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
由于有可能出現(xiàn)多個(gè)物體,我們這里只識別最大的物體(深度學(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):
根據(jù)反饋回來的坐標(biāo),判斷它的位置,進(jìn)行運(yùn)動(dòng)。
# 3 Move Move(x,y)
if x==0 and y==0: Stop()
識別到物體,且在正中央(中間1/2區(qū)域),讓物體向前走。
#go ahead elif width/4 <x and x<(width-width/4): Front(70)
物體在左邊1/4區(qū)域。
#left elif x < width/4: Left(50)
物體在右邊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í)會(huì)繼續(xù)優(yōu)化。有意見或者想法的朋友歡迎交流。
感謝各位的閱讀,以上就是“怎么實(shí)現(xiàn)OpenCV物體跟蹤樹莓派視覺小車效果”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對怎么實(shí)現(xiàn)OpenCV物體跟蹤樹莓派視覺小車效果這一問題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識點(diǎn)的文章,歡迎關(guān)注!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。