主頁 > 軟體設計 > 【2020 電設G題 影像題解】

【2020 電設G題 影像題解】

2020-10-18 15:57:21 軟體設計

目錄

  • 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/ruanti/178238.html

標籤:其他

上一篇:楊明翰的英國碩士留學攻略V0.1

下一篇:2020年保研歷程匯總(計算機專業)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more