当前位置:   article > 正文

【方法】树莓派小车自动循迹(摄像头)_树莓派循迹小车

树莓派循迹小车

Github上有更多代码,按需自取

文章目录


今天我们来介绍一下树莓派小车的循迹教程
首先看一个效果视频
在这里插入图片描述

说明

该小车的硬件是:树莓派+L298N,其实用Arduino也是一样的,下位机只提供一个车轮的控制,视觉识别都是通过树莓派完成的

视觉利用Opencv来实现,关于如何安装Opencv以及使用摄像头请参看我另一篇博客

算法逻辑:看到这样一个赛道,赛道是白色的,其余部分是我们都看成非白色,这样很自然而然地就想到了二值化,将赛道的白色单独显示出来,通过一个二值化就能够很好的区分开赛道与背景。(二值化参考博客
我们不需要分析整个摄像头范围,其实只需要选取图像中的一行像素,类似于一个线阵摄像头,中间部分是白色的,左右是黑色,所以只需要找到白色部分的中点,然后让小车一直朝着这个中点矫正就好了,如果偏左了,就让左轮加快速度,另一边同理。重点是过弯的时候,需要仔细调整这个速度,否则容易转不过去。

主要是GPIO口的一些操控,可以看我的另一篇博客

注意

尽量自己学会调试,查找问题,我的代码不是万能的,但你是万能的

一、腐蚀膨胀问题,原理我不在这里多解释了,自己选择是否腐蚀膨胀/先后顺序/迭代次数,会满足你不同的使用场景

二、转弯速度问题
30 + direction …
这些速度参数设置自己调节,甚至都可以采用缩放倍率

三、检查摄像头拍的图片
有发现拍出来的图最右边多了一列全白,解决办法有俩:1、先腐蚀,把白色去掉。2、别膨胀,把最后一列去掉,怎么去掉呢?white_index[0][white_count - 1] 把这个1改为2,相当于不去考虑最后一列

代码

# coding:utf-8

# 加入摄像头模块,让小车实现自动循迹行驶
# 思路为:摄像头读取图像,进行二值化,将白色的赛道凸显出来
# 选择下方的一行像素,黑色为0,白色为255
# 找到白色值的中点
# 目标中点与标准中点(320)进行比较得出偏移量
# 根据偏移量来控制小车左右轮的转速
# 考虑了偏移过多失控->停止;偏移量在一定范围内->高速直行(这样会速度不稳定,已删)

import RPi.GPIO as gpio
import time
import cv2
import numpy as np

# 定义引脚
pin1 = 12
pin2 = 16
pin3 = 18
pin4 = 22

# 设置GPIO口为BOARD编号规范
gpio.setmode(gpio.BOARD)

# 设置GPIO口为输出
gpio.setup(pin1, gpio.OUT)
gpio.setup(pin2, gpio.OUT)
gpio.setup(pin3, gpio.OUT)
gpio.setup(pin4, gpio.OUT)

# 设置PWM波,频率为500Hz
pwm1 = gpio.PWM(pin1, 500)
pwm2 = gpio.PWM(pin2, 500)
pwm3 = gpio.PWM(pin3, 500)
pwm4 = gpio.PWM(pin4, 500)

# pwm波控制初始化
pwm1.start(0)
pwm2.start(0)
pwm3.start(0)
pwm4.start(0)

# center定义
center = 320
# 打开摄像头,图像尺寸640*480(长*高),opencv存储值为480*640(行*列)
cap = cv2.VideoCapture(0)
while (1):
    ret, frame = cap.read()
    # 转化为灰度图
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    # 大津法二值化
    retval, dst = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU)
    # 膨胀,白区域变大
    dst = cv2.dilate(dst, None, iterations=2)
    # # 腐蚀,白区域变小
    # dst = cv2.erode(dst, None, iterations=6)

    # 单看第400行的像素值
    color = dst[400]
    # 找到白色的像素点个数
    white_count = np.sum(color == 255)
    # 找到白色的像素点索引
    white_index = np.where(color == 255)

    # 防止white_count=0的报错
    if white_count == 0:
        white_count = 1

    # 找到白色像素的中心点位置
    center = (white_index[0][white_count - 1] + white_index[0][0]) / 2

    # 计算出center与标准中心点的偏移量
    direction = center - 320

    print(direction)

    # 停止
    if abs(direction) > 250:
        pwm1.ChangeDutyCycle(0)
        pwm2.ChangeDutyCycle(0)
        pwm3.ChangeDutyCycle(0)
        pwm4.ChangeDutyCycle(0)

    # 右转
    elif direction >= 0:
        # 限制在70以内
        if direction > 70:
            direction = 70
        pwm1.ChangeDutyCycle(30 + direction)
        pwm2.ChangeDutyCycle(0)
        pwm3.ChangeDutyCycle(30)
        pwm4.ChangeDutyCycle(0)

    # 左转
    elif direction < 0:
        if direction < -70:
            direction = -70
        pwm1.ChangeDutyCycle(30)
        pwm2.ChangeDutyCycle(0)
        pwm3.ChangeDutyCycle(30 - direction)
        pwm4.ChangeDutyCycle(0)

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# 释放清理
cap.release()
cv2.destroyAllWindows()
pwm1.stop()
pwm2.stop()
pwm3.stop()
pwm4.stop()
gpio.cleanup()

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/390238
推荐阅读
相关标签
  

闽ICP备14008679号