2018年3月26日 星期一

技術筆記 OpenMV

新購得OpenMV

新購得OpenMV

印表玩具
   STM32技術

緣由

起初是在kickstarter上看到OpenMV開源專案,參考軟硬體內容後,發現是個寶庫,開啟研究過程。他們第一代產品似乎有點延誤,當然還認為這產品會和許多新創品般無法出貨。但終究是順利量產,現在則是第二和三代產品。

第一代 : F4 f427 The OV2640 image sensor is capable of taking 320x240 8-bit Grayscale images or 320x240 16-bit RGB565 images at 60 FPS when the resolution is above 320x240 and 120 FPS when it is below. (關於2640有更多介紹如下  真要買這裡有連結)。

第二代 : F4,更換camera OV7725。

第三代 : F7,The OV7725 image sensor is capable of taking 640x480 8-bit Grayscale images or 640x480 16-bit RGB565 images at 60 FPS when the resolution is above 320x240 and 120 FPS when it is below。



由上而下分別是V3 V2 V1

研究資料後,就想取得實物操作。無奈單價高。官方二代價格239RMB 三代348RMB。網路上看到有人討論連結,也有販賣點連結二代159RMB  三代249RMB,價差約80RMB。賣家kevincoooool 名子是 xiangkezhi1,Q是 97354734。此人年紀輕輕(大學生),卻一手包辦設計、打板、焊接等項目,賣場內還有室內定位和JTAG等模組。

架構

OpenMV使用MCU為STM32F4和F7,有三大特點。

一、移植OpenCV:OpenCV開發語言為C,有其獨特資料格式和連結此資料格式的各式演算法,OpenMV內部有經過簡化過的OpenCV架構,實證可運作(連結)。

二、使用MicroPython:一直以來,受限於硬體資源,MCU都是C-Based,隨著MCU硬體日漸強大,開發者時程的壓縮,以及開發者程度不若以往。更簡單的開發語言應運而生,MicroPython以其小型化Kernel,簡易語法,IDE界面,讓開發變得更簡單。但當然,效能和程式碼體積是必須另外考量的項目。

三、多元模組:在STM基礎上,有許多模組可供使用,如Camera,LCD,WIFI,SD等等。

綜合以上三項目,以一個例子為總結,追蹤直線的小車(連結)




實際使用

參考資料:參考  討論區

Before you can start using your OpenMV Cam you’ll need to download and install OpenMV IDE. (win mac linux rasp )

IDE 包括  file menu   text editing   Running scripts    Frame Buffer Viewer   Histogram Display  Serial Terminal   Status Bar   Tools (QT)


IDE 運作畫面

單獨看個範例
import sensor, time, image
sensor.reset()   << sensor 就是camera
sensor.set_contrast(1)

sensor.set_gainceiling(16)
sensor.set_framesize(sensor.HQVGA)
sensor.set_pixformat(sensor.GRAYSCALE)
face_cascade = image.HaarCascade("frontalface", stages=25)
print(face_cascade)
clock = time.clock()
while (True):
    clock.tick()
    img = sensor.snapshot()
    objects = img.find_features(face_cascade, threshold=0.75, scale=1.35)
    for r in objects:
        img.draw_rectangle(r)
    print(clock.fps())


程式架構

openmv-master\firmware 部分已經compile完成的檔案,可以直接燒錄到Hardware中

openmv-master\usr

內部有HAAR的資料和Python控制範例
openmv-master\util  與上述重疊


openmv-master\src Makefile  主要編譯程序

openmv-master\src\cmsis ST 提供的標準週邊硬體函式庫是完全符合 CMSIS(Cotex Microcontroller Software Interface Standard)的。CMSIS 是 ARM 公司針對 CortexM 系列處理器定義的一個與晶片製造商無關的,獨立的硬體抽象層,基於符合CMSIS 的韌體函式庫開發程式,程式碼復用的好處是顯而易見的。只要其它晶片供應商的 CortexM 處理器也提供符合 CMSIS 的韌體函式庫,我們基於 STMicroelectronics的韌體函式庫開發的程式就很容易移植過去。

openmv-master\src\sthal 又區分為f4和f7  例如 stm32f4xx_hal_adc.c stm32f4xx_hal_dma.c

openmv-master\src\bootloader

------------openmv專屬------------

openmv-master\src\omv\

基本


main.c

Local filesystem and SD card
There is a small internal filesystem (a drive) on the openmvcam which is stored within the microcontroller’s flash memory.

When the openmvcam boots up, it needs to choose a filesystem to boot from.

    If there is no SD card,
         then it uses the internal filesystem as the boot filesystem,
    otherwise,
         it uses the SD card.
    After the boot, the current directory is set to /.

The boot filesystem is used for 2 things:

1. it is the filesystem from which the main.py files are searched for,
2. and it is the filesystem which is made available on your PC over the USB cable.

The filesystem will be available as a USB flash drive on your PC.
You can save files to the drive, and edit main.py.

Remember to eject the USB drive before you reset your pyboard.

Boot modes
On powerup, if powered by USB, the OpenMV Cam will run a bootloader program for about 3 seconds which allows OpenMV IDE to update the firmware without using DFU. After 3 seconds then bootloader will exit and then main.py will run. If not powered by USB then main.py will run immediantly.







sdcard_sdio.c
sdcard_spi.c
ff_wrapper.c File System Helper Functions
main.c
mutex.c
  This is a standard implementation of mutexs on ARM processors following the ARM guide. 連結
sccb.c  SCCB (I2C like) driver.
soft_i2c.c
stm32fxxx_hal_msp.c
xalloc.c 記憶體管理
sdram.c 記憶體管理
array.c 記憶體管理
fb_alloc.c Interface for using extra frame buffer RAM as a stack.
ringbuf.c Simple Ring Buffer implementation.

usbdbg.c  usb debug


ov2640.c CAMERA
ov7725.c CAMERA
ov9650.c CAMERA

sensor.c
    從camera取得需要的影像
    int sensor_snapshot(image_t *image, line_filter_t line_filter_func, void *line_filter_args)
    {
        主要控制,是否為JPEG
        起動HAL_DCMI_Start_DMA_MB(&DCMIHandle,DCMI_MODE_SNAPSHOT, addr, length, fb->h);
        讀取
        停止HAL_NVIC_DisableIRQ(DMA2_Stream1_IRQn);
        回傳的格式就是opencv格式
    }
    設定CAMERA讀取格式等



各目錄

openmv-master\src\omv\boards 區分為openmv 第一代 第二代 第三代設定檔。各有 omv_boardconfig.h omv_boardconfig.mk

openmv-master\src\fatfs FAT相關

openmv-master\src\winc1500 wifi模組 短期內用不到

openmv-master\src\omv\img 已經PORT好的OpenMV  內容太多,放在後面移植OpenCV說明

openmv-master\src\omv\py 已經PORT好的Python,也就是MicroPython的解譯介面

從PYTHON來看,有四種功能
1.基本micropython功能   (基本架構)
2.與開發板有關,如起動、關閉、頻率、SPI、、(測試使用,長期控制熱感應)
3.與擴展板有關,如LCD、網路
4.與視覺有關 就是下面py_image.c

也有十幾個python和C語言對接用的檔案 py_cpufreq.c py_fir.c py_gif.c py_helper.c

py_image.c 這是系統核心 影像處理 py_lcd.c py_mjpeg.c 

py_sensor.c 從camera取得影像,組合成為image
    py_sensor_snapshot 會取得影像
    if (sensor_snapshot((struct image*) py_image_cobj(image)...
py_time.c py_tof.c py_winc.c


-----------視覺有關------------------

py_image.c


有許多基本function,會連結到opencv的詳細funciton
static mp_obj_t py_image_find_edges(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
  py_image_load_cascade 這裡會呼叫opencv的haar讀取預設cascade內容
py_image_find_features 這裡會呼叫opencv的haar進行imlib_detect_objects
  py_image_find_eye 這裡會呼叫opencv的eye進行imlib_find_iris
  py_image_mean mean找背景差異處

對應宣告是
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_find_edges_obj, 2, py_image_find_edges);

static const mp_map_elem_t locals_dict_table[] = {
    XXXXX
    {MP_OBJ_NEW_QSTR(MP_QSTR_find_edges),(mp_obj_t)&py_image_find_edges_obj},
    { NULL, NULL },
};
STATIC MP_DEFINE_CONST_DICT(locals_dict, locals_dict_table);

static const mp_obj_type_t py_image_type = {
    xxxx
    .locals_dict = (mp_obj_t)&locals_dict,
};
這種結構可以直接和python功能結合

如何產生圖形


圖型怎麼進去呢
image_t *img = py_image_cobj(args[0]);
更確切的做法是
mp_obj_t py_image_load_image(mp_obj_t path_obj)
{
    mp_obj_t image_obj = py_image(0, 0, 0, 0);
    imlib_load_image(py_image_cobj(image_obj), mp_obj_str_get_str(path_obj));
    會提供圖檔在儲存體的位置,讀取出檔案
    return image_obj;
}

ROI是感興趣的區域範圍
rectangle_t roi;
py_helper_lookup_rectangle(kw_args, img, &roi);

移植OpenCV

OpenCV版本眾多,最新版是3.X。(目前由何版本移植不知) 從功能角度來看,大部份都看過一遍。接著就是移植到KEIL。同時有機會就深入opencv內容。

D:\openmv-master\openmv-master\src\omv\img

辨識東西
eye.c
通過HAAR找到眼睛 專門找眼珠??
imlib_find_iris  被 py_image.c的py_image_find_eye呼叫
find_gradients
filter_gradients
find_iris
haar.c
外部兩個入口
imlib_detect_objects  被py_image.c呼叫
run_cascade_classifier
eval_weak_classifier
  補充:OpenMV沒有EigenFaces
imlib_load_cascade  被py_image.c呼叫
imlib_load_cascade_from_file
imlib_load_cascade_from_flash

特殊影像處理??
lbp.c
  local binary pattern (LBP)
  被 py_image_find_lbp等使用
  被py_image_load_descriptor呼叫

LBP的基本思想是以图像中某个像素为中心,对相邻像素进行阈值比较。如果中心像素的亮度大于等于它的相邻像素,把相邻像素标记为1,否则标记为0。連結

LBP

morph.c 同樣可達到特殊影像處理,可透過封閉和擴散,讓影像變成另外的感覺 opencv介紹

偵測和背景不同的東西
mean.c
  感覺好像是作者自己寫的
  放在同一個地方,畫面有沒有變動,挑出變動處等等,連結
  被py_image的 py_image_mean 使用

移除掉NOISE
median.c Median filtering. 感覺和mean.c是一樣的東西
midpoint.c 似乎是同類

找形狀BLOB OPENCV介紹
blob.c
  imlib_find_blobs
  imlib_find_markers

分群 平均
kmeans.c
cluster_kmeans 根本沒人在用耶
cluster_alloc
cluster_free
cluster_reset
cluster_points
cluster_update

邊緣偵測
edge.c
也就是所謂canny,功能上可以做到模仿照片素描功能。
圖象的邊緣是指圖象局部區域亮度變化顯著的部分,該區域的灰度剖面一般可以看作是一個階躍,既從一個灰度值在很小的緩衝區域內急劇變化到另一個灰度相差較大的灰度值。圖象的邊緣部分集中了圖象的大部分信息,圖象邊緣的確定與提取對於整個圖象場景的識別與理解是非常重要的,同時也是圖象分割所依賴的重要特徵。
例如下面的圖,經過處理不同的左到右lowThread分別為0、50、100。



被py_image_find_edges呼叫使用
  imlib_edge_simple
    imlib_morph
    imlib_binary
    imlib_erode
  imlib_edge_canny
    //1. Noise Reduction with a 5x5 Gaussian filter
    imlib_morph
    //2. Finding Image Gradients
           使用到
            // Find magnitude
            int g = (int) fast_sqrtf(vx*vx + vy*vy);
            // Find the direction and round angle to 0, 45, 90 or 135
            int t = (int) fast_fabsf((atan2f(vy, vx)*180.0f/M_PI));
    // 3. Hysteresis Thresholding
    // 4. Non-maximum Suppression and output

原理是水平和垂直方向,分別計算出差距後,求得角度數值。歸類入不同區間。


找直線
hough.c
imlib_find_lines 被py_image_find_lines 使用

Mode Filter??不知道是什麼
mode.c 被py_image_mode使用

特徵點偵測
freak.c
  freak_find_keypoints 
    fast.c的fast_detect
      make_offsets
      fast9_detect
      nonmax_suppression
        alloc_keypoint
      fast9_score
        fast9_corner_score

看不太出來是辨識什麼
phasecorrelation.c 被py_image_find_displacement使用
  fft.c 快速傅立葉轉換 Fast Fourier Transforms
template.c
  Template matching with NCC (Normalized Cross Correlation) using exhaustive and diamond search.

影像基本功能
rectangle.c
  基本操作,將影像取差異和總合
  很多地方會使用
integral.c
  積分影像 類似計算出長條圖或是統計圖
integral_mw.c
  與integral類似吧
pool.c
  midpoint meanpoint
stats.c
  Generic image statistics functions.

圖片格式處理
bmp.c
    讀取和寫入BMP
gif.c
jpeg.c
mjpeg.c
    同理沿用
ppm.c
    PNM圖形格式

沒人用
point.c

字型
font.c

數學 基本演算法
fmath.c Fast approximate math functions.
fsort.c Fast 9 and 25 bin sort.
sincos_tab.c  只是宣告

基本架構元件
imlib.c
  opencv最基本功能
  imlib_draw_rectangle 可以在圖型上畫出方框   py_imange呼叫
  rgb2rgb_tab.c  只是RGB的宣告
  xyz_tab.c  只是數字的宣告
  yuv_tab.c  只是數字的宣告
  lab_tab.c  只是數字的宣告
  rainbow_tab.c

沒有留言:

張貼留言