下图为代码实际运用效果:
环境:
- python 3.7
- opencv4.4.0
原理:
- 对图像二值化 这里我使用了提取blue通道用阈值判断的方法,比大律法效果好很多
- 计算图像中黑像素的中心点与设置的中心进行比较 通过微调使像素中心点一直处于中心位置
- 检测不到像素点了就往后退
- 速度一定要慢 一定要慢 一定要慢
- 具体看代码 我基本上都注释了
原代码
import time
import cv2
import numpy as np
import runcar as run
center = 160
a = 0
b = 0
cap = cv2.VideoCapture(0)
while (1):
ret, frame = cap.read()#frame size is 480x640
_, _, blue = cv2.split(frame)#提取blue通道
blur = cv2.GaussianBlur(blue,(5,5),0)#加高斯模糊
retval, dst = cv2.threshold(blur,20, 255, cv2.THRESH_BINARY)#图像二值化
dst = cv2.erode(dst, None, iterations=2)#腐蚀
dst = cv2.dilate(dst, None, iterations=2)#膨胀
time.sleep(0.1)
color = dst[400]#提取400行像素值
color1 = dst[10]
color2 = dst[470]
color = color[159:479]#只看中间的160~480个像素值
color1 = color1[159:479]
color2 = color2[159:479]
black_count = np.sum(color == 0)#统计黑像素的个数
black_count1 = np.sum(color1 == 0)
black_count2 = np.sum(color2 == 0)
#print(black_count)
black_index = np.where(color == 0)#找到黑像素索引
black = list(black_index[0])#tuple转化为list
if black_count == 0:
black = [1,1]
black_count = 1
center = (black[black_count - 1] + black[0]) / 2#求中心点
direction = center - 160#计算偏移量
print('d =',direction)
#画线
ptStart = (320, 0)
ptEnd = (320, 480)
p_color = [0,0,255]
cv2.line(dst, ptStart, ptEnd,p_color,1)
ptStart = (0, 400)
ptEnd = (640, 400)
p_color = [0,0,255]
cv2.line(dst, ptStart, ptEnd,p_color,1)
cv2.imshow('dst',dst[0:480,159:479])
cv2.imshow('video',frame[0:480,159:479])
#前进
if black_count >=80 and black_count <=95:
run.forword()
run.stop()
#左转
if black_count >=10 and direction <= 0:
run.stop()
run.turnLeft()
run.stop()
#右转
if black_count >=10 and direction >= 0:
run.stop()
run.turnRight()
run.stop()
#后退
if abs(direction) >= 155:
run.back()
run.stop()
#拐锐角弯 如果你不需要没有可以删掉
if (black_count >=20 and black_count <= 40 and abs(direction) <= 15):
if a == 0:
run.back()
time.sleep(0.2)
run.stop()
run.turnLeft()
time.sleep(1.2)
run.stop()
a = a+1
#print(black_count,direction)
#break
#判断黑线是否走完
if b>= 750 and a == 1 and black_count2 >= 80 and black_count2 <= 100 and black_count1 == 0 and abs(direction) == 159:
run.forword()
time.sleep(2)
run.stop()
break
b = b+1
if cv2.waitKey(1) & 0xFF == ord('q'):
break
print('b is ',b)
cap.release()
cv2.destroyAllWindows()
代码只供参考,图像处理和小车如何运动这些参数需要根据你的实际问题不断调试修改