1.目标要求:识别出正方形、圆形、三角形的形状、边长、颜色。
2.算法思路:
while True:
clock.tick()
fs_cnt = fs_cnt + 1
img = sensor.snapshot().rotation_corr(z_rotation=180)
img.lens_corr(1.8)
img.bilateral(1)
#img.draw_cross(80, 60, color=(255,255,255))
# 初始化
x_location = 0
y_location = 0
shape = 0 # 0没检测到1圆形2正方形3三角形4篮球5足球6排球
color = 0 # 0没检测到1圆形2正方形3三角形4篮球5足球6排球
sidelen = 0 # 单位cm
area = 0
#识别圆形
for c in img.find_circles(threshold=2000, x_margin=10, y_margin=10, r_margin=10,
r_min=5, r_max=30, r_step=2):
area = (c.x() - c.r(), c.y() - c.r(), 2 * c.r(), 2 * c.r())
# area为识别到的圆的区域,即圆的外接矩形框
statistics = img.get_statistics(roi=area) # 像素颜色统计
#print(statistics)
#红色圆
if 0<statistics.l_mode()<100 and 20<statistics.a_mode()<127 and 10<statistics.b_mode()<127:
color = 1
sidelen =2 * c.r()
shape = 1
x_location = c.x()
y_location = c.y()
x_list[shape] = x_location
y_list[shape] = y_location
len_list[shape] = sidelen
area_list[shape] = 3.14*c.r()*c.r()
color_list[shape] = color
img.draw_cross(c.x(), c.y(), size=5, color=(255,0,255))
img.draw_circle(c.x(), c.y(), c.r(), color=(255, 0, 255))
#绿色圆
if 0<statistics.l_mode()<100 and -128<statistics.a_mode()<0 and 0<statistics.b_mode()<127:
color = 2
sidelen =2 * c.r()
shape = 1
x_location = c.x()
y_location = c.y()
x_list[shape] = x_location
y_list[shape] = y_location
len_list[shape] = sidelen
area_list[shape] = 3.14*c.r()*c.r()
color_list[shape] = color
img.draw_cross(c.x(), c.y(), size=5, color=(255,0,255))
img.draw_circle(c.x(), c.y(), c.r(), color=(255, 0, 255))
#蓝色圆
if 0<statistics.l_mode()<100 and -128<statistics.a_mode()<127 and -128<statistics.b_mode()<-2:
color = 3
sidelen =2 * c.r()
shape = 1
x_location = c.x()
y_location = c.y()
x_list[shape] = x_location
y_list[shape] = y_location
len_list[shape] = sidelen
area_list[shape] = 3.14*c.r()*c.r()
color_list[shape] = color
img.draw_cross(c.x(), c.y(), size=5, color=(255,0,255))
img.draw_circle(c.x(), c.y(), c.r(), color=(255, 0, 255))
#矩形识别
for d in img.find_rects(threshold=15500):
area = (d[0], d[1], d[2], d[3])
statistics1 = img.get_statistics(roi=area) # 像素颜色统计
print(statistics1)
xq = 0
xq = d[2] / d[3]
coners = d.corners()
sb = ((abs(coners[0][0] - coners[1][0]))**2 + (abs(coners[0][1]-coners[1][1])**2))**0.5
if 0<statistics1.l_mode()<100 and 20<statistics1.a_mode()<127 and 10<statistics1.b_mode()<127 and 0.8<xq<1.2:
color = 1
x_location = int(d[0] + d[2] / 2)
y_location = int(d[1] + d[3] / 2)
shape = 2
sidelen = sb
img.draw_rectangle(d.rect(), color=(255, 255, 0))
img.draw_cross(x_location, y_location, color=(255,255,0))
x_list[shape] = x_location
y_list[shape] = y_location
len_list[shape] = sidelen
area_list[shape] = d[2]*d[3]
color_list[shape] = color
if 0<statistics1.l_mode()<100 and -128<statistics1.a_mode()<-23 and -128<statistics1.b_mode()<127 and 0.8<xq<1.2:
color = 2
x_location = int(d[0] + d[2] / 2)
y_location = int(d[1] + d[3] / 2)
shape = 2
sidelen = sb
img.draw_rectangle(d.rect(), color=(255, 255, 0))
img.draw_cross(x_location, y_location, color=(255,255,0))
x_list[shape] = x_location
y_list[shape] = y_location
len_list[shape] = sidelen
area_list[shape] = d[2]*d[3]
color_list[shape] = color
if 0<statistics1.l_mode()<100 and -128<statistics1.a_mode()<127 and -128<statistics1.b_mode()<-2 and 0.8<xq<1.2:
color = 3
x_location = int(d[0] + d[2] / 2)
y_location = int(d[1] + d[3] / 2)
shape = 2
sidelen = sb
img.draw_rectangle(d.rect(), color=(255, 255, 0))
img.draw_cross(x_location, y_location, color=(255,255,0))
x_list[shape] = x_location
y_list[shape] = y_location
len_list[shape] = sidelen
area_list[shape] = d[2]*d[3]
color_list[shape] = color
#三角
for threshold_index in range(3):
blob1 = img.find_blobs([thresholds[threshold_index]], pixels_threshold=40)
xt = 0
if len(blob1)!=0 & shape == 0:
for b in blob1:
Solidty = b.solidity()
Roundness = b.roundness()
pixels = b.pixels()
xt = b.w()/b.h()
print(Solidty, Roundness, pixels, xt)
if 0.3<= Solidty <=0.815 and 0.5< xt <1.5 and Roundness < 0.9405 and pixels < 265:
shape = 3
color = threshold_index + 1
sidelen = (4*pixels/((3)**0.5))**0.5
x_location = int(b.x() + 0.5 * b.w())
y_location = int(b.y() + 0.5 * b.h())
img.draw_rectangle(b.x(), b.y(), b.w(), b.h(), color=(0, 255, 255))
img.draw_cross(x_location, y_location, color=(0,255,255))
x_list[shape] = x_location
y_list[shape] = y_location
len_list[shape] = sidelen
area_list[shape] = b.pixels()
color_list[shape] = color
#print(sidelen)
############################################################
# 数据清洗
shapeList[shape] += 1
# if x_location!= 0 | y_location != 0:
if fs_cnt%3 == 0 :
fs_cnt = 0
shape_result = shapeList.index(max(shapeList))
shapeList = [0, 0, 0, 0, 0, 0, 0]
x_location = x_list[shape_result]
y_location = y_list[shape_result]
sidelen = int(len_list[shape_result]/144.5*100*10)
area = int(area_list[shape_result])
color = color_list[shape_result]
#print(shape)
#print(sidelen)
#print(area)
#print(x_location, y_location)
#x_draw = int(x_location - 0.5*sidelen)
#y_draw = int(y_location - 0.5*sidelen)
if (x_location != 0 or y_location != 0) and sidelen != 0:
img.draw_string(x_location,y_location,str(shape_result), color=(255,165,0),scale=1.5)
#img.draw_string(x_draw,y_draw,str(x_location&','&y_location), color=(0,0,0), scale=1)
#print(sidelen)
data = bytearray([0x5a, 0x78, x_location, y_location, shape_result, sidelen, color, 0xb3])
print(data[6])
#print(data)
uart.write(data) # 发送
# 篮球
for blob_bask in img.find_blobs([basketball_thresholds],pixels_thresholds=1000):
pixel_bask = blob_bask.pixels()
if pixel_bask >200:
x_location = int(blob_bask[0]+0.5*blob_bask[2])
y_location = int(blob_bask[1]+0.5*blob_bask[3])
Radius = int(0.5*blob_bask[2]+0.5*blob_bask[3])
img.draw_circle(x_location,y_location,Radius,color=(255,0,0))
img.draw_cross(x_location,y_location,color=(255,0,0))
shape = 4
color = 4
sidelen = 24
# 排球
#if shape == 0 :
for c in img.find_circles(threshold = 2000, x_margin = 10, y_margin = 10, r_margin = 10,r_min = 6, r_max = 100, r_step = 2):
vball_yellow = img.find_blobs([volleyball_yellow_thresholds], invert=False)
#vball_blue = img.find_blobs([volleyball_blue_thresholds],invert=False)
#img.binary(volleyball_thresholds)
##bin_vball = img.find_rects(threshold = 20000)
vball = len(vball_yellow) #+ len(vball_blue)
if vball > MyVolleyball.yellow_cnt :
shape = 6
color = 6
sidelen = 22
x_location = c.x()
y_location = c.y()
x_list[shape] = x_location
y_list[shape] = y_location
img.draw_circle(x_location, y_location, c.r(), color=(255,255,0))
img.draw_cross(x_location, y_location, color=(255,255,0))
####################################################################
if shape == 0 :
for football in img.find_circles(threshold = 1400, x_margin = 10, y_margin = 10, r_margin = 10,r_min = 6, r_max = 100, r_step = 2):
fball = img.find_blobs([football_threshold])
if len(fball) > 3:
shape = 5
color = 5
sidelen = 22
x_location = c.x()
y_location = c.y()
img.draw_circle(x_location, y_location, c.r(), color=(0,0,0))
if x_location !=0 and y_location!= 0 and shape != 0:
print(shape)
#img.draw_
img.draw_string(x_location,y_location,str(shape), color=(255,165,0),scale=1.5)
#img.draw_string(x_draw,y_draw,str(x_location&','&y_location), color=(0,0,0), scale=1)
data = bytearray([0x5a, 0x5a, x_location, y_location, shape, sidelen, color, 0xb3])
print(data[4],data[5],data[6])
uart.write(data) # 发送
print("FPS %f" % clock.fps())
根据小孔成像原理,拟合出实际边长与像素变长的关系,采用工具MATLAB进行曲线拟合。
data = bytearray([0x5a, 0x78, x_location, y_location, shape_result, sidelen, color, 0xb3])
x_location,y_location 为色块中心坐标,sidelen 为边长。
1.存在误判,在三角形与圆形中会存在误判,是因为用的不是可调焦距的镜头,若对三角形进行三线段检测,会有太多杂物出现在视野中影响判断。
2.在三角形的识别中,镜头正对着图形对容易识别不到,所以在目标锁定的时候,先让舵机上抬一个角度就解决问题了。
1.2020 电设G题 图像题解
2.opencv/openmv识别三角形思路(识别多边形)
3.一种基于opencv的分辨检测圆形,三角形,矩形的思路