千家信息网

怎么实现OpenCV物体跟踪树莓派视觉小车效果

发表于:2026-10-31 作者:千家信息网编辑
千家信息网最后更新 2026年10月31日,这篇文章主要讲解了"怎么实现OpenCV物体跟踪树莓派视觉小车效果",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"怎么实现OpenCV物体跟踪树莓派视觉
千家信息网最后更新 2026年10月31日怎么实现OpenCV物体跟踪树莓派视觉小车效果

这篇文章主要讲解了"怎么实现OpenCV物体跟踪树莓派视觉小车效果",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"怎么实现OpenCV物体跟踪树莓派视觉小车效果"吧!

目录
  • 一、初始化

  • 二、运动控制函数

  • 三、舵机角度控制

  • 四、摄像头&&图像处理

    • 1、打开摄像头

    • 2、把图像转换为灰度图

    • 3、 高斯滤波(去噪)

    • 4、亮度增强

    • 5、转换为二进制

    • 6、闭运算处理

    • 7、获取轮廓

    • 代码

  • 五、获取最大轮廓坐标

    • 六、运动

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

      • 2、向前走

      • 3、向左转

      • 4、向右转

      • 代码

    • 总代码

    一、初始化

    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_backdef 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()

    2、把图像转换为灰度图

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

    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)

    6、闭运算处理

    #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

    五、获取最大轮廓坐标

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

    # 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

    返回最大轮廓的坐标:

    六、运动

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

    # 3 Move        Move(x,y)

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

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

    2、向前走

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

    #go ahead    elif width/4 

    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  (width-width/4):        Right(50)

    总代码

    #Object Trackingimport  RPi.GPIO as GPIOimport timeimport Adafruit_PCA9685import numpy as npimport cv2second = 0 width, height = 160, 120camera = cv2.VideoCapture(0)camera.set(3,width) camera.set(4,height) l_motor = 18left_front   =  22left_back   =  27r_motor = 23right_front   = 25right_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_backdef 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_backdef 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, contoursdef 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  (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()

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

    感谢各位的阅读,以上就是"怎么实现OpenCV物体跟踪树莓派视觉小车效果"的内容了,经过本文的学习后,相信大家对怎么实现OpenCV物体跟踪树莓派视觉小车效果这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!

    0