目錄
- 1、題目要求
- 2、解題
- 一、系統方案
- 1.1 技術路線
- 1.2 系統結構
- 1.3 方案論證比較
- 二、理論分析與計算
- 2.1 物體形狀的測量方法
- 2.2 物體尺寸的測量方法
- 三、誤差分析
- 3、影像代碼
1、題目要求


2、解題
本設計采用STM32F103ZET單片機作為主處理器,設計了非接觸物體尺寸形態測量系統,包括核心板模塊、主板降壓及管腳設計模塊、鍵盤輸入模塊、影像處理模塊、激光測距模塊、LCD彩屏模塊、蜂鳴器模塊、led燈模塊、以及機械模型構成,系統采用OpenMV4 H7 Cam攝像頭、STM32單片機、舵機構成倍訓反饋電路,根據激光測距反饋回的資訊,以及影像處理后反饋,控制舵機對方向及角度進行處理使攝像頭和激光對準識別物,利用影像的處理來判斷識別物的形狀和尺寸,再利用激光測距模塊測量出測量頭中心點與被測目標之間的距離,該系統具有良好的性能,且具有很好的穩定性,
一、系統方案
1.1 技術路線
本系統采用Open mv、云臺構成倍訓回路系統,其中Open mv獲得的位置資訊反饋到單片機,單片機根據位置資訊控制云臺轉向,達到目標之后,通過單片機控制激光測距模塊進行距離的測量和通過 Open mv進行影像的處理來判斷識別物的形狀及尺寸,
1.2 系統結構

總體結構分為3個部分:輸入輸出的顯示板、主控板、電源,其他模塊通過介面與主控板相連,各個模塊協調,共同非接觸物體尺寸形態測量的任務,
1.3 方案論證比較
1.3.1 機械結構的選擇
本系統設計中,由于攝像頭要尋找目標,所以位置會受到多方面因素影響,因此機械結構對此次設計也起著重要作用,
方案一:采用步進電機+舵機的云臺設計
步進電機的優點是步數可以精確控制,但是啟動頻率過高或負載過大易出現失步或堵轉的現象,造成作業不夠穩定,并且在慢速轉動時速度不夠平緩,不利于激光模塊以及攝像頭的穩定性
方案二:采用舵機+舵機的云臺設計
此次使用的為數字舵機,打角范圍約在300°,通過調控占空比改變舵機角度,更為精準,同時相比步進電機而言,更為穩定,對整體的結構穩定性更為有保障,能夠滿足轉向與平衡要求,
基于上述分析,本設計選擇方案二,
1.3.2測距模塊模塊的選擇
題目要求測量出測量頭中心點與被測目標之間的距離,所有測距模塊的選取決定了測量資料的準確性,
方案一:紅外測距模塊
紅外測距模塊是用紅外線為介質的測量系統,測量范圍廣,回應時間短,價格便宜,接線簡單,體積小便于安裝和使用,但市面上常見的紅外測距模塊大多都在1.5米距離內比較準確,但題目的最遠要求是3米,
方案二:激光測距模塊
激光測距模塊精度高,測速快,解析度高,測量距離遠(本設計采用的可達到40米),足以滿足題目3米的要求,是一款穩定、精準、偏室內應用的模塊,價格偏貴,
基于上述分析,本設計選擇方案二,
1.3.3 舵機供電的選擇
方案一:線性電源驅動,線性電源由于沒有采用開關器件,理論上不會產生任何開關噪聲,輸出電源非常干凈,但線性電源的效率極低,大電流時發熱嚴重,嚴重影響電源穩定性,線性電源普遍帶負載能力較弱,受輸入電壓的影響較大,本題中,舵機有時候需要瞬間大幅度運動,需要極大的功率支持,若使用線性電源會大大地降低系統的可靠性,
方案二:開關電源驅動,開關電源效率高,能夠驅動大功率器件,且輸出穩定不會收到輸入電壓的干擾,但由于其作業特點,輸出電壓中會含有一定頻率的噪聲,但可以在輸出端加旁路電容在一定程度上抑制噪聲,使其并不會對舵機正常作業造成影響,
因此根據本題中舵機的大功率需求,我們決定采用方案二,
1.3.4 顯示方案的選擇
方案一:OLED顯示屏模塊
OLED顯示螢屏可視角度大,功耗低,厚度薄,體積小,溫度范圍廣,結構及制程簡單等特點,比較適合小系統,但現成的OLED模塊的尺寸比較偏小,其次顏色比較單一,
方案二:LCD彩屏模塊
LCD彩屏模塊解析度較高,尺寸比較大,并且是彩色的,所以看起來比較清楚,本設計采用的STM32核心板上有LCD彩屏模塊所對應的FPC介面,連接起來比較方便,
基于上述分析,本設計選擇方案二,
二、理論分析與計算
2.1 物體形狀的測量方法
已知物體分為兩大類,一類是純色塊物體,另一類為球類物體
純色塊物體我們選擇先用LAB色域進行閾值分割,利用連通域演算法,獲取每張圖中每個連通域的面積、密度比、圓形度等引數,由于每個形狀的連通域在這些特征的分布不同,可以進行多分類操作,在后續測驗中我們又發現由于光照的影響,連通域的形變程度較嚴重,圓形與方形容易產生混淆,于是又加入了霍夫圓變換,先判斷圓再去對三角形與正方形進行二分類,這樣效果較好,
球類物體我們仍然選擇通過色域特征限制以及霍夫圓變換進行特征篩選,其中排球以及黑白足球由于顏色的不均勻導致兩種方法都出現比較嚴重的漏判,后來選擇利用連通域的篩選,確定不同色塊的位置組合,再通過聚類演算法,找出色塊密度最大的區域,進行框定,
2.2 物體尺寸的測量方法
通過激光測距獲取距離,由于不同色塊的連通域像素數目并不一致,使用邊長為40厘米的不同顏色的目標板進行標定,假設連通域像素個數與目標物體的實際面積在同一距離下呈現線性關系,所以只需要擬合出線性函式的系數k與距離的映射關系即可,這里我們用二次函式擬合曲線,結果如下:
2.2.1 影像連通域面積與現實面積的映射函式
Matlab擬合曲線圖:
藍色塊映射函式: 紅色塊映射函式: 綠色塊映射函式:
計算好面積系數k之后,利用k和連通域面積計算得出真實的物體面積,然后根據幾何物體的形狀(三角形、圓形、正方形)用不同的面積公式反算出邊長,
三、誤差分析
3.1識別誤差
原因:不同的光照下,對物塊的分割效果有較大差異,容易將背景中雜物誤識別為目標物體;不同的角度下,球體的表面特征有較大差異,容易出現球類漏判
改進措施:采用對光照魯棒性更高的分割演算法;采用對角度魯棒性更高的分類演算法;對于有限分類的任務,可考慮使用小型的神經網路訓練
3.2尺寸誤差
原因:公式為近似擬合,采樣資料不夠多且密集;計算尺寸所需要的變數之一:物塊像素個數,會隨著光照影響、角度影響而呈現幾十的上下浮動,
改進措施:多次采集資料,擬合公式;在公式的因變數中加入場景平均灰度值、角度值
3.3距離誤差
原因:傳感器精度有限;由于是懸掛,被測物體可能會前后飄動,
改進措施:采用更加精準的采樣儀器;在物體背面進行固定
3、影像代碼
#2020 年 TI 杯大學生電子設計競賽非接觸物體尺寸形態測量(G 題) openmv測驗代碼
# author:DYY
# school:HDU
import sensor, image, time
import math
from pyb import UART
import json
import ustruct
sensor.reset() # Initialize the camera sensor.
sensor.set_pixformat(sensor.RGB565) # or sensor.RGB565 565
sensor.set_framesize(sensor.QQVGA) # or sensor.QVGA (or others)
sensor.skip_frames(50) #跳過50frame,使新設定生效,并自動調節白平衡
sensor.set_auto_gain(False) #關閉自動自動增益,默認開啟的,在顏色識別中,一定要關閉白平衡,
sensor.set_auto_whitebal(False) #關閉白平衡,白平衡是默認開啟的,在顏色識別中,一定要關閉白平衡,
#引數初始化
fps_cnt=0
fps_cnt_set=10000
show_fps_set=15
target_x=0
target_y=0
shape = 0
graylight_x=0
graylight_y=0
distance=0
PI=3.14159
#防誤判變數
now_length = 0
last_length = 0
exist_times = 0
sum_length = 0
last_center_X = 0
last_center_Y = 0
tri_times=0
rect_times=0
circle_times=0
xy_times=0
xy_not_times=0
mode='A'
class Circle:
def __init__(self): #_init_(self),主要給類初始化一些屬性,物件創建時自動呼叫該方法執行
self.left_pixelsLimit = 3000
self.right_pixelsLimit = 50000
self.left_SolidtyLimit = 0.78
self.right_SolidtyLimit = 0.85
self.left_RoundnessLimit = 0.98
self.right_RoundnessLimit = 1
class Triangle:
def __init__(self): #_init_(self),主要給類初始化一些屬性,物件創建時自動呼叫該方法執行
self.left_pixelsLimit = 140
self.right_pixelsLimit = 1300
self.left_SolidtyLimit = 0.4
self.right_SolidtyLimit = 0.86
self.left_RoundnessLimit = 0.5
self.right_RoundnessLimit = 0.99
class Rectangle:
def __init__(self): #_init_(self),主要給類初始化一些屬性,物件創建時自動呼叫該方法執行
self.left_pixelsLimit = 380
self.right_pixelsLimit = 2300
self.left_SolidtyLimit = 0.8
self.right_SolidtyLimit = 1
self.left_RoundnessLimit = 0.58
self.right_RoundnessLimit = 1
MyCircle = Circle()
MyTriangle = Triangle()
MyRectangle = Rectangle()
#激光閾值
graylight_thred=(230,255)
#色塊閾值
#(88,-79,81)
green_threshold = (5,88,-73,-18,9,59) #(57,95,-80,-20,-25,32)
red_threshold = (5,91,17,124,-30,70) #(21,71,56,124,38,114)
blue_threshold = (5,70,-54,105,-80,-14) #(20,73,-46,112,-128,-31)
football_threshold = (0,99,-66,118,16,127)
white_black_football_threshold= (0,27,-127,127,-127,127)
vollyball_threshold = (0,99,-66,118,25,127)
vollyball_threshold_blue = (0,80,-20,37,30,70)
basketball_threshold = (0,99,14,127,7,64)
#獲取激光坐標函式
def get_graylight(grayMat,paint):
#global real_exist_times
#mask1=grayMat.binary([graylight_thred])
#計算連通域
center_X=0
center_Y=0
for blob in grayMat.find_blobs([graylight_thred], pixels_threshold=0, area_threshold=0, merge=True, margin=0):
pixels=blob.pixels()
Roundness= blob.roundness()
'''if(fps_cnt%show_fps_set==0):
print("圓形度",Roundness)
print("像素個數",pixels)'''
#光亮像素過大或者圓形度過小視作無
if pixels>=60 :
center_X=0
center_Y=0
else:
center_X=blob.cx()
center_Y=blob.cy()
#paint.draw_circle(center_X,center_Y,4, color =0, thickness = 3, fill = True)
return (center_X,center_Y)
#獲取形狀、目標像素長度、目標中心坐標函式
def get_shapeANDcolor(srcImg,color_thred):
center_X=0
center_Y=0
shape = 0
target_length=0
for blob in srcImg.find_blobs([color_thred], pixels_threshold=10, area_threshold=20, merge=True, margin=0):
pixels=blob.pixels() #獲取像素個數,用來判斷大小
print(pixels)
#首先用像素限制掉雜點
if(pixels >=MyTriangle.left_pixelsLimit):
Roundness= blob.roundness()#獲取連通域圓形度
Solidty = blob.solidity() #獲取連通域與它最小外接矩形的密度比
if(fps_cnt%show_fps_set==0):
print("pixels",pixels)
print("Roundness",Roundness)
print("Solidty",Solidty)
#條件限制
if(pixels<=MyTriangle.right_pixelsLimit and Solidty>=MyTriangle.left_SolidtyLimit and Solidty<=MyTriangle.right_SolidtyLimit and Roundness>=MyTriangle.left_RoundnessLimit and Roundness<=MyTriangle.right_RoundnessLimit):
srcImg.draw_rectangle(blob[0:4],color = (255, 0, 0)) #用矩形標記出目標顏色區域
srcImg.draw_cross(blob[5], blob[6]) #在目標顏色區域的中心畫十字形標記
center_X=blob.cx()
center_Y=blob.cy()
shape = 1
target_length = pixels
elif(pixels<=MyRectangle.right_pixelsLimit and Solidty>=MyRectangle.left_SolidtyLimit and Solidty<=MyRectangle.right_SolidtyLimit and Roundness>=MyRectangle.left_RoundnessLimit and Roundness<=MyRectangle.right_RoundnessLimit):
#srcImg.draw_rectangle(blob[0:4],color = (0, 255, 0)) #用矩形標記出目標顏色區域
#srcImg.draw_cross(blob[5], blob[6]) #在目標顏色區域的中心畫十字形標記
center_X=blob.cx()
center_Y=blob.cy()
shape = 3
target_length =pixels
else:
center_X=0
center_Y=0
shape = 0
target_length = 0
return (shape,center_X,center_Y,target_length)
#獲取最大可能色塊函式
def get_maxsize_color(srcImg):
R_MAXpixels=0
G_MAXpixels=0
B_MAXpixels=0
#尋找red最大連通域
for blob in srcImg.find_blobs([red_threshold], pixels_threshold=10, area_threshold=20, merge=True, margin=0):
pixels=blob.pixels() #獲取像素個數,用來判斷大小
R_MAXpixels = max(pixels,R_MAXpixels)
#尋找green最大連通域
for blob in srcImg.find_blobs([green_threshold], pixels_threshold=10, area_threshold=20, merge=True, margin=0):
pixels=blob.pixels() #獲取像素個數,用來判斷大小
G_MAXpixels = max(pixels,G_MAXpixels)
#尋找blue最大連通域
for blob in srcImg.find_blobs([blue_threshold], pixels_threshold=10, area_threshold=20, merge=True, margin=0):
pixels=blob.pixels() #獲取像素個數,用來判斷大小
B_MAXpixels = max(pixels,B_MAXpixels)
maxpixels=max(R_MAXpixels,G_MAXpixels,B_MAXpixels)
if(R_MAXpixels==maxpixels):
return red_threshold
elif(G_MAXpixels==maxpixels):
return green_threshold
else:
return blue_threshold
#獲取背景板左右邊界函式
def get_leftANDrightLINE(srcImg,center_X,center_Y):
grayimg =srcimg.to_grayscale()
canny_thred=13
cannyimg=grayimg.find_edges(image.EDGE_CANNY, threshold=(canny_thred,canny_thred*2))
cannyimg.dilate(1)
centerx = center_X
centery = center_Y
flag =0
right_x = 160
left_x = 0
for i in range(centerx,cannyimg.width()-1):
if(cannyimg.get_pixel(i,centery)==0 and cannyimg.get_pixel(i + 1,centery)==255):
flag+=1
if(flag == 1):
right_x = i
break
flag =0
for i in range(centerx,1,-1):
if(cannyimg.get_pixel(i,centery)==0 and cannyimg.get_pixel(i - 1,centery)==255):
flag+=1
if(flag == 1):
left_x = i
break
if(fps_cnt%show_fps_set==0):
print(right_x)
print(left_x)
return (left_x,right_x)
#防誤判函式,目標的尺寸,并且將值限制在30到40之間
def Prevent_misslength(now_length,last_length):
global exist_times
global sum_length
if last_length==0 and now_length==0:
sum_length=0
if abs(last_length-now_length)<=7 and now_length!=0 and last_length!=0:
sum_length+=now_length
exist_times+=1
else:
sum_length=0
exist_times=0
if(exist_times!=0):
result=sum_length/exist_times
if(result>=40):
result=40
elif(result<=30):
result=30
return result
else:
return 0
#防誤判函式,中心坐標
def Prevent_misstarget(point1_X,point1_Y,lastpoint1_X,lastpoint1_Y):
global xy_times
global xy_not_times
if point1_X==0 and point1_Y==0:
xy_not_times+=1
if point1_X==0 and point1_Y==0 and lastpoint1_X!=0 and lastpoint1_Y!=0:
point1_X=lastpoint1_X
point1_Y=lastpoint1_Y
if lastpoint1_X!=0 and lastpoint1_Y!=0 and (abs(lastpoint1_X-point1_X)>=20 or abs(lastpoint1_Y-point1_Y)>=20):
point1_X=lastpoint1_X
point1_Y=lastpoint1_Y
if xy_not_times>=10:
point1_X=0
point1_Y=0
xy_not_times=0
return point1_X,point1_Y
#白色足球檢測函式
def detect_whiteANDblack_football(srcimg):
img_new = srcimg.copy()
binimg=img_new.binary([white_black_football_threshold])
listX = []
listY = []
point_nums=0
for blob in binimg.find_blobs([(1,255)], pixels_threshold=5, area_threshold=5, merge=True, margin=2):
pixels=blob.pixels() #獲取像素個數,用來判斷大小
Solidity = blob.solidity()
#if(pixels>=4 and pixels<=48):
#print(Solidity)
#print(blob.w()/blob.h())
#print(pixels)
if(pixels>=4 and pixels<=48 and Solidity>=0.75 and 0.8<=blob.w()/blob.h()<=1.3 and 20<=blob.cy()<=100):
listX.append(blob.cx())
listY.append(blob.cy())
#srcimg.draw_rectangle(blob[0:4], color = (255, 0, 0)) #用矩形標記出目標顏色區域
#srcimg.draw_cross(blob[5], blob[6]) #在目標顏色區域的中心畫十字形標記
mean_X=0
mean_Y=0
if(len(listX)>=2):
#求密度最大的點
while(len(listX)>1):
#求mean_x,mean_y
mean_X = Get_Average(listX)
mean_Y = Get_Average(listY)
#找到點集中距離mean_X,mean_Y最大的點,并將它去除
max_distance=0
distance=0
max_i=0
for i in range(len(listX)):
distance = (listX[i]-mean_X)*(listX[i]-mean_X)+(listY[i]-mean_Y)*(listY[i]-mean_Y)
if distance>=max_distance:
max_i=i
del listX[max_i]
del listY[max_i]
#剩下點是球點
mean_X = Get_Average(listX)
mean_Y = Get_Average(listY)
#srcimg.draw_circle(mean_X,mean_Y,10, color = (255, 0, 0))
return (mean_X,mean_Y,len(listX))
#獲取平均數
def Get_Average(list):
sum = 0
for item in list:
sum += item
if(len(list)==0):
return 0
return int(sum/len(list))
#模型為簡化后的模型
def get_real_length(pixels,distance,color):
reallength = 0
if(color==1):
#藍色k
#0.3001 -2.0901 4.0956
ratio = 0.3001 * distance * distance -2.0901 * distance +4.0956
reallength = pixels/ratio
#reallength =reallength*0.8
elif(color==2):
#紅色k
#0.4336 -2.8160 5.1373
ratio = 0.4336 * distance * distance -2.8160 * distance +5.1373
reallength = pixels/ratio
#reallength =reallength*1.105
elif(color==3):
#綠色k
#0.4364 -2.8062 5.0621
ratio = 0.4364 * distance * distance -2.8062 * distance +5.0621
reallength = pixels/ratio
#reallength =reallength*0.99
else:
reallength=0
return reallength
#初始化時鐘
clock = time.clock() # Tracks FPS.
uart = UART(3,115200) #定義串口3變數
#設定串口
uart.init(115200, bits=8, parity=None, stop=0) # init with given parameters
uart1=UART(1,38400)
#我們要傳送的資料有:目標大小、形狀、幾何中心坐標 以及回車
def sending_data(length,shape,cx,cy,dis1,dis2,color): #發送函式
global uart
data = ustruct.pack("<bbbbbbbbb",
length,
shape,
cx,
cy,
dis1,
dis2,
color,
0x0D,
0x0A)
uart.write(data)
#主要接受的是模式
def recive_data(): #接收函式
global uart
global mode
if uart.any():
#接收位元組串
#tmp_data = uart.readline()
#接收字串
tmp_data = uart.readline().decode()
#如果想把回車換行去除掉,
#tmp_data = uart.readline().decode().strip()
#將形式為D=0.604m,90#的字串轉換為float型別的資料
#new_data = tmp_data[2,7]
#print(tmp_data)
#獲取mode編號
length = len(tmp_data)
if( 2<=length<=4 and tmp_data[0]=='Q'):
mode = tmp_data[length-1]
#print(mode)
return mode
def recive_distance(): #接收函式
global uart1
global distance
if uart1.any():
tmp_data = uart1.readline().decode()
#print(tmp_data)
if len(tmp_data)>=6 and tmp_data[0]=='D' and tmp_data[1]=='=' and tmp_data[2]>='0' and tmp_data[2]<='9'and tmp_data[4]>='0' and tmp_data[4]<='9'and tmp_data[5]>='0' and tmp_data[5]<='9':
distance=int(tmp_data[2])+int(tmp_data[4])*0.1+int(tmp_data[5])*0.01
#distance=int(distance*100)
print(distance)
return distance
#影像回圈
while(True):
clock.tick() # Track elapsed milliseconds between snapshots().
#【step 1:】獲取去畸變彩圖,這里采用的無畸變攝像頭
srcimg = sensor.snapshot()#.lens_corr(strength = 1.8, zoom = 1.0)
fps_cnt=fps_cnt+1
#flag=0時沒有圓
flag=0
#初始化引數
now_length = 0
circle_r=0
circle_x=0
circle_y=0
center_X=0
center_Y=0
shape=0
#left_line = 0
#right_line = 160
target_length = 0
#黑白足球黑塊初始化
black_nums=0
color_flag=0 #藍1 紅2 綠3
distance = recive_distance()
mode = recive_data()
#mode='C'
real_target_length=0
#flag_football=0:檢測黃色足球 flag_football=1:檢測黑白足球
flag_football = 1
#mode1是球類檢測
#mode0是幾何物體檢測
#print(mode)
target_pixels=0
if(mode == 'A' or mode == 'B'):
#觀察是否有圓
for c in srcimg.find_circles(threshold = 2700, 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 = srcimg.get_statistics(roi=area)#像素顏色統計
#print(statistics)
if(-73<statistics.a_mode()<-18 and 9<statistics.b_mode()<59):
color_flag = 3
elif(17<statistics.a_mode()<124 and -30<statistics.b_mode()<70):
color_flag = 2
elif(-54<statistics.a_mode()<105 and -80<statistics.b_mode()<-14):
color_flag = 1
if 1<=color_flag<=3:
#找到最大的圓作為我們的目標圓
flag = 1
if(c.r()>=circle_r):
circle_r = c.r()
circle_x = c.x()
circle_y = c.y()
#if(fps_cnt%show_fps_set==0):
#print(c)
#srcimg.draw_circle(circle_x,circle_y,circle_r, color = (255, 0, 0))
#為圓
if(flag == 1 ):
center_X = circle_x
center_Y = circle_y
target_pixels = PI*circle_r*circle_r
shape = 2
#不為圓,進行其他檢測
else:
#首先確定色塊顏色
color_thred = get_maxsize_color(srcimg)
if(color_thred==green_threshold):
color_flag = 3
elif(color_thred==blue_threshold):
color_flag = 1
elif(color_thred==red_threshold):
color_flag = 2
#print(color_thred)
#color_thred=red_threshold
#在該色域中尋找特征,然后得到形狀和中心坐標
(shape,center_X,center_Y,target_pixels) = get_shapeANDcolor(srcimg,color_thred)
else:
#先找籃球
ball_pixels = 0
for blob in srcimg.find_blobs([basketball_threshold], pixels_threshold=10, area_threshold=20, merge=True, margin=2):
pixels=blob.pixels() #獲取像素個數,用來判斷大小
#print(pixels)
#print(blob.w()/blob.h())
#print(blob.h())
if(pixels>=200 and pixels<=780 and 0.87<=blob.w()/blob.h()<=1.15 and 12<=blob.w()<=40 and 12<=blob.h()<=40 and 20<=blob.cy()<=100):
if(pixels>=ball_pixels):
ball_pixels=pixels
srcimg.draw_rectangle(blob[0:4]) #用矩形標記出目標顏色區域
#srcimg.draw_cross(blob[5], blob[6]) #在目標顏色區域的中心畫十字形標記
shape=4
center_X = blob.cx()
center_Y = blob.cy()
ball_pixels=0
if(shape==0):
#再找足球
#if(mode=='C'):
#第一種,純黃足球
for blob in srcimg.find_blobs([vollyball_threshold], pixels_threshold=10, area_threshold=20, merge=True, margin=2):
pixels=blob.pixels() #獲取像素個數,用來判斷大小
Roundness = blob.roundness()
#print(pixels)
#print(Roundness)
#print(pixels)
if(pixels>=120 and pixels<=600 and Roundness>=0.75 and 3<=blob.w()<=40 and 3<=blob.h()<=40 and 20<=blob.cy()<=100):
if(pixels>=ball_pixels):
srcimg.draw_rectangle(blob[0:4]) #用矩形標記出目標顏色區域
#srcimg.draw_cross(blob[5], blob[6]) #在目標顏色區域的中心畫十字形標記
shape=5
center_X = blob.cx()
center_Y = blob.cy()
#else:
if(shape==0):
#第二種,黑白足球
(center_X,center_Y,black_nums) = detect_whiteANDblack_football(srcimg)
if(center_X!=0 and center_Y!=0):
shape=5
ball_pixels=0
if(shape==0 and black_nums<=2):
img_new = srcimg.copy()
binimg=img_new.binary([vollyball_threshold,vollyball_threshold_blue])
dilateimg = binimg.dilate(3)
dilateimg = binimg.erode(2)
#再找排球
for blob in dilateimg.find_blobs([(1,255)], pixels_threshold=10, area_threshold=20, merge=True, margin=2):
pixels=blob.pixels() #獲取像素個數,用來判斷大小
#print(pixels)
#print(blob.w()/blob.h())
#print(pixels))
if(pixels>=110 and pixels<=500 and 3<=blob.w()<=40 and 3<=blob.h()<=40 and 0.7<=blob.w()/blob.h()<=1.3 and 20<=blob.cy()<=100 and 20<=blob.cx()<=140):
if(pixels>=ball_pixels):
srcimg.draw_rectangle(blob[0:4], color = (255, 0, 0)) #用矩形標記出目標顏色區域
#srcimg.draw_cross(blob[5], blob[6]) #在目標顏色區域的中心畫十字形標記
shape=6
center_X = blob.cx()
center_Y = blob.cy()
#else:
#print("NONE")
#計算尺寸
if(mode != 'C'):
real_target_length = get_real_length(target_pixels,distance,color_flag)
if(shape == 1):
real_target_length = math.sqrt(real_target_length*2.31)
elif(shape == 2):
real_target_length = math.sqrt(real_target_length*1.273)
elif(shape == 3):
real_target_length = math.sqrt(real_target_length)
#形狀防誤判
#shapeList 對應:無形狀、三角形、圓形、正方形、籃球、足球、排球
srcimg.draw_cross(80, 60,color = (0, 0, 0))
shape_result=shape
shapeList = [0,0,0,0,0,0,0]
shapeList[shape]+=1
if(fps_cnt%5==0):
shape_result=shapeList.index(max(shapeList))
shapeList = [0,0,0,0,0,0,0]
#中心防誤判措施
#(center_X,center_Y)=Prevent_misstarget(center_X,center_Y,last_center_X,last_center_Y)
srcimg.draw_cross(center_X, center_Y)
#srcimg.draw_cross(center_X,center_Y,color = (0, 255, 0))
print(shape)
#print(center_X,center_Y)
#print(real_target_length)
sending_data(int(real_target_length),shape_result,center_X,center_Y,int(distance),int(distance*100%100),color_flag)
last_center_X = center_X
last_center_Y = center_Y
分工:
硬體電路:苗百百
控制以及選單:下沙百人斬
影像:吊歪歪
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/178902.html
標籤:其他
上一篇:楊明翰的英國碩士留學攻略V0.1



