OpenMv學(xué)習(xí)總結(jié)(滿滿干貨)

本文主要記錄了學(xué)習(xí)OpenMv過程中的點(diǎn)滴。它跟OpenCv其實(shí)是完全不同的兩個(gè)東西,大家可不要被迷惑噢。

具體可以參考[1]: https://docs.singtown.com/micropython/zh/latest/openmvcam/openmvcam/quickref.html "Openmv"

OpenMv簡(jiǎn)介

簡(jiǎn)單來說,OpenMv就是一個(gè)可編程的攝像頭,通過使用python語言,專門用作嵌入式當(dāng)中的視覺感光元件。下面將介紹Openmv使用過程中的常用知識(shí)。

感光元件

感光元件即sensor模塊,與攝像頭有關(guān)。看如下例子:

import sensor#引入感光元件的模塊
sensor.reset()#初始化感光元件
sensor.set_pixformat(sensor.RGB565)#設(shè)置為彩色,用到其它參數(shù)時(shí)再上官方文檔里找,下同
sensor.set_framesize(sensor.QVGA)#設(shè)置圖像的大小
sensor.skip_frames()#跳過n張照片,在更改設(shè)置后,跳過一些幀,等待感光元件變穩(wěn)定。

while(True):
    img = sensor.snapshot()#拍攝一張照片,img為一個(gè)image對(duì)象

ROI區(qū)域

sensor.set_framesize(sensor.VGA) # 高分辨率
sensor.set_windowing((640, 80)) #取中間的640*80區(qū)域

獲取/設(shè)置像素點(diǎn)

img = sensor.snapshot()
img.get_pixel(10,10)
img.set_pixcel(10,10,(255,0,0))#設(shè)置坐標(biāo)(10,10)的像素點(diǎn)為紅色(255,0,0)

圖像的運(yùn)算

  • image.invert() 圖像取反

  • image.nand(image) 圖像之間進(jìn)行與非運(yùn)算

  • image.nor(image) 圖像之間進(jìn)行或非運(yùn)算

  • image.xor(image)圖像之間進(jìn)行異或運(yùn)算

  • image.difference(image) 此函數(shù)通常用來做移動(dòng)檢測(cè)

畫圖

image.draw_line(line_tuple, color=White) 在圖像中畫一條直線,其中l(wèi)ine_tuple的格式為(x0, y0, x1, y1),即從某點(diǎn)到某點(diǎn)的直線

image.draw_rectangle(rect_tuple, color=White) 在圖像中畫一個(gè)矩形框,其中rect_tuple 的格式是 (x, y, w, h)。

這里只舉如上兩個(gè)例子,其它的用到再去查即可。

添加自定義模塊

OpenMv存在一個(gè)文件系統(tǒng),根目錄下有一個(gè)main.py,把你需要導(dǎo)入的自定義模塊復(fù)制到根目錄下即可。

操作LED

from pyb import LED

led = LED(1) # 紅led
led.toggle()
led.on()#亮
led.off()#滅

操作IO口

from pyb import Pin

p_out = Pin('P7', Pin.OUT_PP)#設(shè)置p_out為輸出引腳
p_out.high()#設(shè)置p_out引腳為高
p_out.low()#設(shè)置p_out引腳為低
p_in = Pin('P7', Pin.IN, Pin.PULL_UP)#設(shè)置p_in為輸入引腳,并開啟上拉電阻
value = p_in.value() # get value, 0 or 1#讀入p_in引腳的值

可以看出,pyb模塊里各種外設(shè)的操作和32類似,易上手。

控制舵機(jī)

from pyb import Servo

s1 = Servo(1) # servo on position 1 (P7)
s1.angle(45) # move to 45 degrees
s1.angle(-60, 1500) # move to -60 degrees in 1500ms
s1.speed(50) # for continuous rotation servos

具體需要用到哪個(gè)舵機(jī)還是需要參照原理圖的結(jié)構(gòu)。

定時(shí)器

from pyb import Timer

tim = Timer(4, freq=1000)
tim.counter() # get counter value
tim.freq(0.5) # 0.5 Hz
tim.callback(lambda t: pyb.LED(1).toggle())  //類似于32的回調(diào)函數(shù)

IO中斷

from pyb import Pin, ExtInt

callback = lambda e: print("intr")
ext = ExtInt(Pin('P7'), ExtInt.IRQ_RISING, Pin.PULL_NONE, callback)

PWM輸出

from pyb import Pin, Timer

p = Pin('P7') # P7 has TIM4, CH1
tim = Timer(4, freq=1000)
ch = tim.channel(1, Timer.PWM, pin=p)
ch.pulse_width_percent(50)

UART

from pyb import UART

uart = UART(3, 9600)
uart.write('hello')
uart.read(5) # read up to 5 bytes

Openmv應(yīng)用(尋找色塊)

image.find_blobs(thresholds, roi=Auto, x_stride=2, y_stride=1, invert=False, area_threshold=10, pixels_threshold=10, 
merge=False, margin=0, threshold_cb=None, merge_cb=None)
  • Thresholds是你想識(shí)別的顏色的闕值,注意它是一個(gè)列表對(duì)象。
  • roi即你感興趣的區(qū)域。
  • x_stride 就是查找的色塊的x方向上最小寬度的像素,y_stride 就是查找的色塊的y方向上最小寬度的像素,默認(rèn)為2。
  • invert反轉(zhuǎn)闕值。
  • area_threshold 面積閾值,如果色塊被框起來的面積小于這個(gè)值,會(huì)被過濾掉。
  • pixels_threshold 像素個(gè)數(shù)閾值,如果色塊像素?cái)?shù)量小于這個(gè)值,會(huì)被過濾掉。
  • merge 合并,如果設(shè)置為True,那么合并所有重疊的blob為一個(gè)。
  • margin 邊界,如果設(shè)置為1,那么兩個(gè)blobs如果間距1一個(gè)像素點(diǎn),也會(huì)被合并。

顏色闕值的結(jié)構(gòu)

red = (minL, maxL, minA, maxA, minB, maxB)

但是OpenMv如此強(qiáng)大,在IDE工具欄里的Machine Vision中有闕值調(diào)試工具,效果圖如下:

效果

BLOB色塊對(duì)象

  • blob.rect() 返回這個(gè)色塊的外框——矩形元組(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() 返回色塊的像素?cái)?shù)量(int),也可以通過blob[4]來獲取。
  • blob.cx() 返回色塊的外框的中心x坐標(biāo)(int),也可以通過blob[5]來獲取。
  • blob.cy() 返回色塊的外框的中心y坐標(biāo)(int),也可以通過blob[6]來獲取。
  • blob.area() 返回色塊的外框的面積。應(yīng)該等于(w * h)

能看到這里的人真不容易啊,你們都是大學(xué)霸?。?!

OpenMv學(xué)習(xí)之串口的使用

先來看如下一段代碼:

# Blob Detection and uart transport
import sensor, image, time
from pyb import UART
import json

sensor.reset() # Initialize the camera sensor.
sensor.set_pixformat(sensor.RGB565) # use RGB565.
sensor.set_framesize(sensor.QQVGA) # use QQVGA for speed.
sensor.skip_frames(10) # Let new settings take affect.
sensor.set_auto_whitebal(False) # turn this off.
clock = time.clock() # Tracks FPS.

uart = UART(3, 115200)

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

    blobs = img.find_blobs([yellow_threshold])
    if blobs:
        print('sum :', len(blobs))
        output_str = json.dumps(blobs) # 在這里串口發(fā)送的數(shù)據(jù)中我們用了json格式,因?yàn)樗褂闷饋砗?jiǎn)單方便,但缺點(diǎn)是占用的資源較多
        for b in blobs:
            # Draw a rect around the blob.
            img.draw_rectangle(b.rect()) # rect
            img.draw_cross(b.cx(), b.cy()) # cx, cy

        print('you send:',output_str)
        uart.write(output_str+'\n')
    else:
        print('not found!')

在這里,我們用串口來不斷發(fā)送blob數(shù)據(jù),而尋找色塊的過程跟opencv的思路相似,在前邊也介紹過,只不過在openmv中更簡(jiǎn)便。

當(dāng)用openmv的串口發(fā)送完數(shù)據(jù)后,接收端需要進(jìn)行相應(yīng)的解析才能得到想要的數(shù)據(jù),前提是你需要知道發(fā)送數(shù)據(jù)的格式并撰寫相應(yīng)的函數(shù)。

本文結(jié)束,謝謝閱讀

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容