# Find Rects Example
#
# 这个例子展示了如何使用april标签代码中的四元检测代码在图像中找到矩形。 四元检测算法以非常稳健的方式检测矩形,并且比基于Hough变换的方法好得多。 例如,即使镜头失真导致这些矩形看起来弯曲,它仍然可以检测到矩形。 圆角矩形是没有问题的!
# (但是,这个代码也会检测小半径的圆)...
import sensor, image, time
from pyb import UART
from machine import LED
dark_exp=15000
sensor.reset()
sensor.set_pixformat(sensor.RGB565) # 灰度更快(160x120 max on OpenMV-M7)
#sensor.set_pixformat(sensor.GRAYSCALE)
sensor.set_framesize(sensor.QQVGA)
sensor.skip_frames(time = 2000)
sensor.set_auto_gain(False) # 关闭自动自动增益
sensor.set_auto_whitebal(False,(0,0,0)) # 关闭白平衡 第二个参数代表颜色
sensor.set_brightness(1500) # 设置图像亮度 越大越亮
sensor.set_auto_exposure(False,10000)#设置曝光时间
#定义计算两点距离的函数
def euler_distance(x1,y1,x2,y2):
return ((x1-x2)**2+(y1-y2)**2)**(1/2)
clock = time.clock()
uart = UART(3,115200)#串口通信,波特率为115200
thresholds_gray = [(70, 255)] # grayscale thresholds
thresholds_rgb = [(20, 100, 20, 127, -128, 127), # generic_red_thresholds//3
(5, 91, -128, -45, -7, 127), # generic_green_thresholds//4
(0, 100, -96, 127, -128, -24)] # generic_blue_thresholds//6
threshold_black=[(0,25,-10,10,-10,10)] #暂时没用
threshold_test=(100, 42, -58, 127, -21, 40)
#边缘检测卷积核还是锐化卷积核。。强调水平和垂直边缘。。的锐化
kernel_size = 1 # kernel width = (size*2)+1, kernel height = (size*2)+1
kernel = [-1, -1, -1,\
-1, +8, -1,\
-1, -1, -1]
thresholds_gray = [(70, 255)] # grayscale thresholds
recognize_rect_flag=0
recognize_red_pen_flag=0
#sensor.set_brightness(100) # 设置图像亮度 越大越亮
#sensor.set_auto_exposure(False,14000)
recognize_green_pen_flag=0 #暂时没用
rect_point1_list=[] #识别多次,内部是坐标列表
rect_point2_list=[]
rect_point3_list=[]
rect_point4_list=[]
avg_rect_point1=[0,0]
avg_rect_point2=[0,0]
avg_rect_point3=[0,0]
avg_rect_point4=[0,0]
recognize_rect_count=0 #识别计数
recognize_timeout_orign=10
recognize_timeout=10 #几帧没识别到转换阈值
while(True):
clock.tick()
img = sensor.snapshot()#.lens_corr(1.8)
if (uart.any()):
recv_data =(uart.read())
print(recv_data)
if (recv_data==b'r'):
recognize_rect_flag = 1
recognize_red_pen_flag=0
if(recv_data==b'q'):
recognize_red_pen_flag=1
recognize_rect_flag=0
#sensor.set_brightness(100) # 设置图像亮度 越大越亮
#sensor.set_auto_exposure(False,1000)
if(recv_data==b'p'):#恢复初始状态
sensor.set_auto_exposure(False,10000)
recognize_rect_flag=0
recognize_red_pen_flag=0
recognize_green_pen_flag=0 #暂时没用
rect_point1_list=[] #识别多次,内部是坐标列表
rect_point2_list=[]
rect_point3_list=[]
rect_point4_list=[]
avg_rect_point1=[0,0]
avg_rect_point2=[0,0]
avg_rect_point3=[0,0]
avg_rect_point4=[0,0]
recognize_rect_count=0 #识别计数
if recognize_rect_flag:
#print("test")
for r in img.find_rects(threshold = 5000):
corners=r.corners()
length1=euler_distance(corners[0][0],corners[0][1],corners[1][0],corners[1][1]) #左下 右下 底边
length2=euler_distance(corners[1][0],corners[1][1],corners[2][0],corners[2][1]) #右下 右上 右侧边
length3=euler_distance(corners[2][0],corners[2][1],corners[3][0],corners[3][1]) #右上 左上 顶边
length4=euler_distance(corners[3][0],corners[3][1],corners[0][0],corners[0][1]) #左上 左下 左侧边
long_edge=1
short_edge=1
#判断长短边
if length1>length2:
long_edge=length1
short_edge=length2
else:
long_edge=length2
short_edge=length1
strange_flag=0 #判断是不是奇形怪状
if(length1==0 or length2==0 or length3==0 or length4==0):#某一边为0
strange_flag=1
elif((length1/length3)>0.85 and (length1/length3)<1.15 and (length2/length4)>0.85 and (length2/length4)<1.15):
strange_flag=0 #对边长度误差在0.15比例范围以内
else:
strange_flag=1
# 最终滤波
if strange_flag==0 and long_edge>25 and short_edge>25 and long_edge/short_edge<1.6: #and x>20 and x<140 and y>15 and y<105 and w_h>0.4 and w_h<1.6 and height>20 and width>20
img.draw_rectangle(r.rect(),color=(255,0,0))
for p in r.corners():
img.draw_circle(p[0], p[1], 5, color = (0, 255, 0))
#img.draw_cross(p[0], p[1])
#img.save("./img{}.jpg".format(len(rect_point1_list)),quality=80)
#开始存入列表
recognize_rect_count+=1 #计数 并将每次所得坐标加入列表
rect_point1_list.append(corners[0])
rect_point2_list.append(corners[1])
rect_point3_list.append(corners[2])
rect_point4_list.append(corners[3])
print (corners)
if(recognize_rect_count>=5):#停止识别 五次
for i in range(recognize_rect_count): #求各个坐标的平均值
avg_rect_point1[0]+=rect_point1_list[i][0]
avg_rect_point1[1]+=rect_point1_list[i][1]
avg_rect_point2[0]+=rect_point2_list[i][0]
avg_rect_point2[1]+=rect_point2_list[i][1]
avg_rect_point3[0]+=rect_point3_list[i][0]
avg_rect_point3[1]+=rect_point3_list[i][1]
avg_rect_point4[0]+=rect_point4_list[i][0]
avg_rect_point4[1]+=rect_point4_list[i][1]
avg_rect_point1[0]=(avg_rect_point1[0]/recognize_rect_count)
avg_rect_point1[1]=(avg_rect_point1[1]/recognize_rect_count)
avg_rect_point2[0]=(avg_rect_point2[0]/recognize_rect_count)
avg_rect_point2[1]=(avg_rect_point2[1]/recognize_rect_count)
avg_rect_point3[0]=(avg_rect_point3[0]/recognize_rect_count)
avg_rect_point3[1]=(avg_rect_point3[1]/recognize_rect_count)
avg_rect_point4[0]=(avg_rect_point4[0]/recognize_rect_count)
avg_rect_point4[1]=(avg_rect_point4[1]/recognize_rect_count)
#矩形旋转一定角度会改变四个角点坐标的返回顺序,有顺时针和逆时针两种//找最大2个判断法 //左上是1号//顺时针排列
############
newdata=[[0,0],[0,0],[0,0],[0,0]]
data_dict={1:(avg_rect_point1[0],avg_rect_point1[1]),2:(avg_rect_point2[0],avg_rect_point2[1]),3:(avg_rect_point3[0],avg_rect_point3[1]),4:(avg_rect_point4[0],avg_rect_point4[1])}
one_sort=sorted(data_dict.items(),key = lambda x: x[1][0]) #按x坐标大小排序,返回列表
#data_dict.items():以列表的形式返回可遍历的元组数组;lambda x:定义x的值为x[1][0]
#偏左的两个点
first2=[]
first2.append(one_sort[0])
first2.append(one_sort[1])
#偏右的两个点
second2=[]#=[] #?!?
second2.append(one_sort[2])
second2.append(one_sort[3])
# 分别提取first2和second2中角点的索引和坐标,准备进行y坐标的排序
list_a = [first2[0][0]]+[first2[1][0]]
list_b = [first2[0][1]]+[first2[1][1]]
first2_dict = dict(zip(list_a, list_b)) # 将坐标打包成元组,再返回元组的列表,再将列表转成字典
list_a = [second2[0][0]]+[second2[1][0]]
list_b = [second2[0][1]]+[second2[1][1]]
second2_dict = dict(zip(list_a, list_b))
first2_sort=sorted(first2_dict.items(),key = lambda x: x[1][1],reverse=True) #y坐标 逆序排序
second2_sort=sorted(second2_dict.items(),key = lambda x: x[1][1]) #顺序排序
all_sort=first2_sort+second2_sort #无论任何角度摆放矩形都顺时针发送角点坐标
newdata[0][0]=all_sort[0][1][0]
newdata[0][1]=all_sort[0][1][1]
newdata[1][0]=all_sort[1][1][0]
newdata[1][1]=all_sort[1][1][1]
newdata[2][0]=all_sort[2][1][0]
newdata[2][1]=all_sort[2][1][1]
newdata[3][0]=all_sort[3][1][0]
newdata[3][1]=all_sort[3][1][1]
########
avg_rect_point1[0]=newdata[0][0]
avg_rect_point1[1]=newdata[0][1]
avg_rect_point2[0]=newdata[1][0]
avg_rect_point2[1]=newdata[1][1]
avg_rect_point3[0]=newdata[2][0]
avg_rect_point3[1]=newdata[2][1]
avg_rect_point4[0]=newdata[3][0]
avg_rect_point4[1]=newdata[3][1]
print("均值后点1:",avg_rect_point1[0],",",avg_rect_point1[1],"点2:",avg_rect_point2[0],",",avg_rect_point2[1],"点3:",avg_rect_point3[0],",",avg_rect_point3[1],"点4:",avg_rect_point4[0],",",avg_rect_point4[1])
#看看能不能用 #?
if(avg_rect_point1[1]>=89):
avg_rect_point1[1]-=1.5
if(avg_rect_point2[1]>=89):
avg_rect_point2[1]-=1.5
if(avg_rect_point3[1]>=89):
avg_rect_point3[1]-=1.5
if(avg_rect_point4[1]>=89):
avg_rect_point4[1]-=1.5
use_dev=1
if(use_dev):
#由于都是外框,所以设置往里偏像素
dev_k=0.03 #偏移系数,总的像素差乘它
is_reverse_xy=0 #xy偏移计算方向相反
is_use_single=0 #只是正常加一个固定数
#分别计算对角点x、y坐标之差
delta1_x=avg_rect_point3[0]-avg_rect_point1[0]
delta1_y=avg_rect_point3[1]-avg_rect_point1[1]
delta2_x=avg_rect_point4[0]-avg_rect_point2[0]
delta2_y=avg_rect_point4[1]-avg_rect_point2[1]
############################################################
#以下代码不起作用(bug、?
if is_reverse_xy:#真 x 和 y 的偏移方向相反
delta1_x=(round)(delta1_x*abs(delta1_y)/abs(delta1_x))
delta1_y=(round)(delta1_y*abs(delta1_x)/abs(delta1_y))
delta2_x=(round)(delta2_x*abs(delta2_y)/abs(delta2_x))
delta2_y=(round)(delta2_y*abs(delta2_x)/abs(delta2_y))
if is_use_single:
dev_k=1#?
if delta1_x>0 :
delta1_x=2
else:
delta1_x=-2
if delta1_y>0 :
delta1_y=2
else:
delta1_y=-2
if delta2_x>0 :
delta2_x=2
else:
delta2_x=-2
if delta2_y>0 :
delta2_y=2
else:
delta2_y=-2
#############################################################
avg_rect_point1[0]+=dev_k*delta1_x
avg_rect_point1[1]+=dev_k*delta1_y
avg_rect_point3[0]-=dev_k*delta1_x
avg_rect_point3[1]-=dev_k*delta1_y
avg_rect_point2[0]+=dev_k*delta2_x #-
avg_rect_point2[1]+=dev_k*delta2_y
avg_rect_point4[0]-=dev_k*delta2_x #+仅某一情况
avg_rect_point4[1]-=dev_k*delta2_y
#############################################################3
avg_rect_point1[0]=(round)(avg_rect_point1[0])
avg_rect_point1[1]=(round)(avg_rect_point1[1])
avg_rect_point2[0]=(round)(avg_rect_point2[0])
avg_rect_point2[1]=(round)(avg_rect_point2[1])
avg_rect_point3[0]=(round)(avg_rect_point3[0])
avg_rect_point3[1]=(round)(avg_rect_point3[1])
avg_rect_point4[0]=(round)(avg_rect_point4[0])
avg_rect_point4[1]=(round)(avg_rect_point4[1])
print("加偏移后点1:",avg_rect_point1[0],",",avg_rect_point1[1],"点2:",avg_rect_point2[0],",",avg_rect_point2[1],"点3:",avg_rect_point3[0],",",avg_rect_point3[1],"点4:",avg_rect_point4[0],",",avg_rect_point4[1])
img.draw_cross(avg_rect_point1[0], avg_rect_point1[1])
img.draw_cross(avg_rect_point2[0], avg_rect_point2[1])
img.draw_cross(avg_rect_point3[0], avg_rect_point3[1])
img.draw_cross(avg_rect_point4[0], avg_rect_point4[1])
img.save("./img{}.jpg".format(len(rect_point1_list)),quality=80)#保存图像
uart.write(bytearray([0xA5]))
uart.write(bytearray([avg_rect_point1[0]]))
uart.write(bytearray([avg_rect_point1[1]]))
uart.write(bytearray([avg_rect_point2[0]]))
uart.write(bytearray([avg_rect_point2[1]]))
uart.write(bytearray([avg_rect_point3[0]]))
uart.write(bytearray([avg_rect_point3[1]]))
uart.write(bytearray([avg_rect_point4[0]]))
uart.write(bytearray([avg_rect_point4[1]]))
led.on()
time.sleep_ms(500)
led.off()
##直接转换成暗色
#sensor.set_brightness(1000) # 设置图像亮度 越大越亮
sensor.set_auto_exposure(False,dark_exp)
#置回标志位
recognize_rect_flag=0
rect_point1_list=[]
rect_point2_list=[]
rect_point3_list=[]
rect_point4_list=[]
avg_rect_point1=[0,0]
avg_rect_point2=[0,0]
avg_rect_point3=[0,0]
avg_rect_point4=[0,0]
recognize_rect_count=0
break
if recognize_red_pen_flag:
max_area=0
max_index=0
get_blob=0
blobs = img.find_blobs([thresholds_rgb[0]],pixels_threshold=1, area_threshold=1, merge=True) #
for i in range(len(blobs)):
get_blob=1
####
#recognize_timeout=recognize_timeout_orign
###
if blobs[i].area()>max_area:
max_area=blobs[i].area()
max_index=i
if get_blob:
r=blobs[max_index]
img.draw_rectangle(r.rect())
img.draw_cross(r.cx(), r.cy())
#img.draw_keypoints([(r.cx(), r.cy(), int(math.degrees(r.rotation())))], size=20)
#print(r.cx(), r.cy())
uart.write(bytearray([0xAA]))
uart.write(bytearray([r.cx()]))
uart.write(bytearray([r.cy()]))
##########超时识别绿色
#if(recognize_timeout==0):
#print("timeout")
#max_area=0
#max_index=0
#get_blob=0
#blobs = img.find_blobs([thresholds_rgb[0],thresholds_rgb[1]],pixels_threshold=1, area_threshold=1, merge=True) #
#for i in range(len(blobs)):
#get_blob=1
#if blobs[i].area()>max_area:
#max_area=blobs[i].area()
#max_index=i
#if get_blob:
#r=blobs[max_index]
#img.draw_rectangle(r.rect())
#img.draw_cross(r.cx(), r.cy())
##img.draw_keypoints([(r.cx(), r.cy(), int(math.degrees(r.rotation())))], size=20)
##print(r.cx(), r.cy())
#uart.write(bytearray([0xAA]))
#uart.write(bytearray([r.cx()]))
#uart.write(bytearray([r.cy()]))
#if(get_blob==0 and recognize_timeout>0):
#recognize_timeout-=1
#print(clock.fps())
找了很多地方设置曝光时间都是这么写的,为什么报错了