久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 3025|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

[OpenMV學(xué)習(xí)筆記(一)]識別色塊并與STM32通信傳輸中心坐標(biāo)

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:1015992 發(fā)表于 2022-4-6 00:09 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
1.前言
一直有想要寫些東西的想法正好最近比較閑以及大創(chuàng)項目和電賽備賽需要用到OpenMV所以就記錄一下學(xué)習(xí)過程。因為小白第一次寫文章有什么錯誤希望大家包含在評論區(qū)指正。
2.硬件連接
2.1、Openmv端

這里OpenMV端僅作為數(shù)據(jù)的發(fā)送端,所以只需要共地,以及OpenMV的TX(P4)與開發(fā)板的RX端連接即可。
2.2、STM32端


將開發(fā)板連接STM芯片RX端與轉(zhuǎn)串口TX端的跳帽取下,再將OpenMV的TX端(P4)與STM的RX連接。如果使用USB轉(zhuǎn)TTL則將TTL的RX端與STM的TX端連接,STM的RX端與OpenMV的TX端(P4)連接,然后共地,這樣就可以在串口調(diào)試助手中查看數(shù)據(jù)的傳輸情況了。
3.代碼
3.1、OpenMV端

# Blob Detection and uart transport
import sensor, image, time, math, pyb
from pyb import UART
import json
import ustruct
# For color tracking to work really well you should ideally be in a very, very,
# very, controlled enviroment where the lighting is constant...A
yellow_threshold   = (8, 22, -60, -3, 127, -128)
# You may need to tweak the above settings for tracking green things...
# Select an area in the Framebuffer to copy the color settings.


sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)       #設(shè)置圖像大小QVGA大小為320*240,所以中心坐標(biāo)應(yīng)該是(160,120)
sensor.skip_frames(time = 2000)
sensor.set_auto_gain(False)             # must be turned off for color tracking
sensor.set_auto_whitebal(False)         # must be turned off for color tracking
red_threshold_01=(66, 31, -58, -24, 127, -128)
clock = time.clock()


uart = UART(3, 115200)
uart.init(115200, bits=8, parity=None, stop=1) # OpenMV端初始化與STM端配置一樣即可。

#**************************傳輸數(shù)據(jù)的函數(shù)************************************
def sending_data(cx,cy):
    global uart;
    #frame=[0x2C,18,cx%0xff,int(cx/0xff),cy%0xff,int(cy/0xff),0x5B];
    #data = bytearray(frame)
    data = ustruct.pack("<bbhhb",               #格式為倆個字符倆個短整型(2字節(jié))
                   0x2C,                        #幀頭1
                   0x12,                        #幀頭2
                   int(cx), # up sample by 4    #數(shù)據(jù)1
                   int(cy), # up sample by 4    #數(shù)據(jù)2
                   0x5B)
    uart.write(data);   #必須要傳入一字節(jié)的數(shù)組,這個函數(shù)似乎不能發(fā)送單個字節(jié),必須得一次發(fā)送多個字節(jié)
#**************************************************************************

#**************************找到最大的色塊函數(shù)*******************************#
def find_max(blobs):
    max_size=0
    for blob in blobs:
        if blob.pixels() > max_size:
            max_blob=blob
            max_size = blob.pixels()
    return max_blob
#**************************************************************************#


while(True):
    img = sensor.snapshot() # Take a picture and return the image.

    blobs = img.find_blobs([yellow_threshold])
    if blobs:
        max_blob=find_max(blobs)
        #print('sum :', len(blobs))
        img.draw_rectangle(max_blob.rect())
        img.draw_cross(max_blob.cx(), max_blob.cy())
        output_str="[%d,%d]" % (max_blob.cx(),max_blob.cy())

        print('you send:',output_str)            #打印色塊中心點坐標(biāo)到串行終端便于數(shù)據(jù)核驗
        sending_data(max_blob.cx(),max_blob.cy())#發(fā)送色塊框的中心點坐標(biāo)
        #FH = bytearray([0x2C,0x12,blobs[0].cx(),blobs[0].cy(),0x5B])

        #uart.write(FH)
    else:
        print('not found!')
        sending_data(567,789)#如果沒有找到符合條件的色塊,那么發(fā)送一個不可能出現(xiàn)的坐標(biāo)
        #FH = bytearray([0x2C,0x12,0x77,0x55,0x5B])

        #uart.write(FH)

顏色識別:
        這里只需要使用閾值編輯器,將想要識別的顏色調(diào)節(jié)到純白色如下圖所示,然后將下面的LAB閾值填入 red_threshold_01=() 即可。



獲取中心坐標(biāo):
blob.rect() 返回這個色塊的外框——矩形元組(x, y, w, h),可以直接在 image.draw_rectangle中使用。
blob.x() 返回色塊的外框的x坐標(biāo)(int),也可以通過blob[0]來獲取。
blob.y() 返回色塊的外框的y坐標(biāo)(int),也可以通過blob[1]來獲取。
blob.w() 返回色塊的外框的寬度w(int),也可以通過blob[2]來獲取。
blob.h() 返回色塊的外框的高度h(int),也可以通過blob[3]來獲取。
blob.pixels() 返回色塊的像素數(shù)量(int),也可以通過blob[4]來獲取。
blob.cx() 返回色塊的外框的中心x坐標(biāo)(int),也可以通過blob[5]來獲取。
blob.cy() 返回色塊的外框的中心y坐標(biāo)(int),也可以通過blob[6]來獲取。

   
3.2、STM32端


void DEBUG_USART_IRQHandler(void)                                
{
    uint8_t com_data;
        uint8_t i;
        static uint8_t   RxCounter1=0;
        static uint16_t  RxBuffer1[7]={0};
        static uint8_t   RxState = 0;   
//        static uint8_t   RxFlag1 = 0;

        if( USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)         //接收中斷  
        {
                USART_ClearITPendingBit(USART1,USART_IT_RXNE);       //清除中斷標(biāo)志
                com_data = USART_ReceiveData(DEBUG_USARTx );
            
                if(RxState==0&&com_data==0x2C)          //0x2c幀頭
                {
                    RxState=1;
                    RxBuffer1[RxCounter1++]=com_data;     //RxBuffer1[0]==0x2c RxCounter1==1
                }
        
                else if(RxState==1&&com_data==0x12)     //0x12幀頭
                {
                    RxState=2;
                    RxBuffer1[RxCounter1++]=com_data;     //RxBuffer1[0]==0x12 RxCounter1==2
                }
        
                else if(RxState==2)                     //開始接收有效數(shù)據(jù)
                {
                    RxBuffer1[RxCounter1++]=com_data;     //全部接收完,RxCounter1==7

                    if(RxCounter1>=7||com_data == 0x5B)  //RxBuffer1接受滿了,接收數(shù)據(jù)結(jié)束
                    {
                      RxState=3;
//                        RxFlag1=1;
                        Cx=(RxBuffer1[RxCounter1-4]<<8)+(RxBuffer1[RxCounter1-5]);    //RxBuffer1[2]是openmv發(fā)送的第一個數(shù)據(jù)的低八位,RxBuffer1[3]是openmv發(fā)送的第一個數(shù)據(jù)的高八位
                        Cy=(RxBuffer1[RxCounter1-2]<<8)+(RxBuffer1[RxCounter1-3]);    //RxBuffer1[4]是openmv發(fā)送的第二個數(shù)據(jù)的低八位,RxBuffer1[5]是openmv發(fā)送的第二個數(shù)據(jù)的高八位
                    printf("X=%d,Y=%d\n",Cx,Cy);
                    delay_ms(300);       //延時防止大量數(shù)據(jù)造成上位機卡頓
                    }
                }
        
                else if(RxState==3)        //檢測是否接受到結(jié)束標(biāo)志
                {
                        if(RxBuffer1[RxCounter1-1] == 0x5B)
                        {
                                    USART_ITConfig(DEBUG_USARTx,USART_IT_RXNE,DISABLE);//關(guān)閉DTSABLE中斷
//                                    if(RxFlag1)
//                                    {
//                                    
//                                    OLED_ShowNum(0,0,Cx,3,1,2);
//                                    OLED_ShowNum(0,2,Cy,3,1,2);
//                                    
//                                    }
//                                    RxFlag1 = 0;
                                    RxCounter1 = 0;
                                    RxState = 0;
                                    USART_ITConfig(DEBUG_USARTx,USART_IT_RXNE,ENABLE);
                        }
                        else   //接收錯誤
                        {
                                    RxState = 0;
                                    RxCounter1=0;
                                    for(i=0;i<7;i++)
                                    {
                                            RxBuffer1[ i]=0xff;      //將存放數(shù)據(jù)數(shù)組清零
                                    }
                        }
                }
   
                else   //接收異常
                {
                        RxState = 0;
                        RxCounter1=0;
                        for(i=0;i<7;i++)
                        {
                                RxBuffer1[ i]=0xff;      //將存放數(shù)據(jù)數(shù)組清零
                        }
                }

        }

}
            
看到這里或許會存在疑問,為什么我們發(fā)送五個數(shù)據(jù)卻要定義一個七位的數(shù)據(jù)的接收數(shù)組呢?在OpenMV端的發(fā)送函數(shù)里面有一個"<bbhhb"的數(shù)據(jù)聲明,其中b表示C語言的signed char類型占一個字節(jié)八位二進(jìn)制數(shù),h表示C語言的short類型占兩個字節(jié)十六位二進(jìn)制數(shù)。而我們的OpenMV一次只能發(fā)送一個字節(jié)八位二進(jìn)制數(shù),因此實際傳輸?shù)臄?shù)據(jù)為:數(shù)據(jù)幀1->數(shù)據(jù)幀2->數(shù)據(jù)1的低八位->數(shù)據(jù)1的高八位->數(shù)據(jù)2的低八位->數(shù)據(jù)2的高八位->數(shù)據(jù)幀3。至于為什么數(shù)據(jù)要使用兩個字節(jié),那是因為我們選擇的是QVGA即320*240大小的圖像,因此數(shù)據(jù)將會超過255即一個字節(jié)八位二進(jìn)制數(shù)。
4.查看結(jié)果



左邊是OpenMV IDE串行終端的數(shù)據(jù),右邊是調(diào)試助手中的數(shù)據(jù)。可以發(fā)現(xiàn)雖然延時導(dǎo)致部分?jǐn)?shù)據(jù)沒有被打印出來但是調(diào)試助手中的數(shù)據(jù)全部來自串行終端,所以代碼正確。
## 5.總結(jié)
代碼部分參考了[這篇文章]寫的很好很詳細(xì)。完整的工程代碼可以去[Gitee下載]。

評分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏1 分享淘帖 頂 踩
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 色吧久久 | 亚洲精选一区二区 | 91动漫在线观看 | 中国美女撒尿txxxxx视频 | 日韩成人性视频 | 日韩成人免费av | 国产精品一区二区三区在线 | 午夜精品一区二区三区在线视频 | 女人精96xxx免费网站p | 欧美日韩久久精品 | 黄色大片免费网站 | www.日韩| 国产蜜臀97一区二区三区 | 亚洲中午字幕 | 欧美激情久久久 | 成人天堂噜噜噜 | 亚洲成人免费 | 日韩国产精品一区二区三区 | 一区二区日韩 | 一二三四在线视频观看社区 | 国内精品久久精品 | 亚洲欧美自拍偷拍视频 | 久久国产成人精品国产成人亚洲 | 97人人澡人人爽91综合色 | 欧美日韩国产在线观看 | 精品国产乱码久久久久久丨区2区 | www.日本在线 | 日韩成人免费av | 久久精品福利视频 | 国产美女自拍视频 | 国产一区欧美 | 男人视频网站 | 99精品欧美一区二区蜜桃免费 | 午夜免费在线电影 | 亚洲国产精品福利 | 精品国产91乱码一区二区三区 | 99色在线视频 | h视频在线免费观看 | 美女久久 | 日日摸天天添天天添破 | 日本三级网站在线 |