单目测距在无人驾驶,路径规划中的地位越来越重要,比激光雷达和深度相机的成本更低,更适合于项目的开发。
单目测算距离的原理就是初中物理上学的小孔成像原理,但是由于我们不知道高度,所以会造成深度丢失。所以我们第一步就是测量我们要测量物体的真实宽度和镜头的焦距。
镜头测算焦距,我们需要对着标定板拍照,然后将拍好的照片导入到Matlab中,计算出焦距。大家在初中学过相距和焦距之间的关系,相距应该在一倍焦距以内,因为焦距比较小,所以我们就将相距等于一倍焦距,这样误差也会很小。
list(i.rect())
这个函数可以返回出所检测到目标画框出来的x,y坐标。
通过这个函数我们就可以得到图像的宽度
b=(int(list1[0])-int(list1[2]))
有可能它们相减得到的数据为负数,但现实生活中不可能存在负数,所以我们取绝对值。
if b<0:
b=-b
其次我们只需要将像素宽度转化为实际宽度,我们k210采用的分辨率是22*224,感光元件为4,所以实际宽度为4/224×b
width_img=(4/224)*int(b)
L=int(width_True*0.75)/width_img/100 #物体实际的宽度
这样我们就可以算出大致的距离了,误差不会很大。
import sensor,image,lcd,time
import KPU as kpu
from machine import UART
from fpioa_manager import fm
lcd.init(freq=15000000)
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.set_hmirror(0)
sensor.run(1)
width_img=1
width_True=20
L=0
task = kpu.load("/sd/yolov3.kmodel")
f=open("anchors.txt","r")
anchor_txt=f.read()
L=[]
for i in anchor_txt.split(","):
L.append(float(i))
anchor=tuple(L)
f.close()
f=open("lable.txt","r")
lable_txt=f.read()
lable = lable_txt.split(",")
f.close()
fm.register(10, fm.fpioa.UART1_TX, force=True)
fm.register(11, fm.fpioa.UART1_RX, force=True)
uart_A = UART(UART.UART1, 115200, 8, 1, 0, timeout=1000, read_buf_len=4096)
anchor = (0.3691, 0.2575, 0.4528, 0.4739, 0.6996, 0.5839, 0.9164, 0.9705, 2.3887, 1.7223)
sensor.set_windowing((224, 224))
a = kpu.init_yolo2(task, 0.5, 0.3, 5, anchor)
classes=["9","1","4","2","3","8","5","6","7" ]
while(True):
img = sensor.snapshot()
code = kpu.run_yolo2(task, img)
if code:
for i in code:
a=img.draw_rectangle(i.rect())
a = lcd.display(img)
list1=list(i.rect())
b=(int(list1[0])-int(list1[2]))
if b<0:
b=-b
c=(list1[1]+list1[3])/2
width_img=(4/224)*int(b)
if width_img==0:
width_img=1
L=int(width_True*0.75)/width_img/100
#print("物体是:",classes[i.classid()])
#print("概率为:",100.00*i.value())
#print("坐标为:",b,c)
print("距离:",b)
for i in code:
lcd.draw_string(i.x(), i.y(), '%f'%L, lcd.RED, lcd.WHITE)
#lcd.draw_string(i.x(), i.y()+12, '%f'%i.value(), lcd.RED, lcd.WHITE)
#lcd.draw_string(50, 200,str(b), lcd.RED, lcd.WHITE)
#lcd.draw_string(110, 200,str(c), lcd.RED, lcd.WHITE)
uart_A.write(classes[i.classid()]+'\r\n')
uart_A.write(str(b)+'\r\n')
uart_A.write(str(c)+'\r\n')
else:
a = lcd.display(img)
uart_A.deinit()
del uart_A
a = kpu.deinit(task)