---
# System prepended metadata

title: MaixPy+MaixDuino 範例測試
tags: [' 測試報告', ' MaixDuinom', ' K210', MaixPy]

---

---
tags: MaixPy, 測試報告, K210, MaixDuinom
robots: K210, MaixDuinom, MaixPy, 影像辨識, 人臉辨識, 人臉偵測
lang: zh-tw
---

# MaixPy+MaixDuino 範例測試

## 前置作業

1. 安裝韌體燒錄軟體 [KFlash]()
1. 安裝 [MaixPy 韌體](https://dl.sipeed.com/MAIX/MaixPy/release/master/)
3. 首先需要下載 [MaixPy 範例檔](https://github.com/sipeed/MaixPy_scripts)。

:::info
MaixPy 是從 OpenMV 改過來的, 所以有許多基本功能在 [MainxPy 的文件](https://maixpy.sipeed.com/zh/)是沒有詳細說明的, 要找 [OpenMV 的文件](http://docs.openmv.io/)。
:::

## 人臉偵測

- 原始文章為 [MaixPy run face detection (tiny yolo v2)](https://blog.sipeed.com/p/675.html)。
- 精簡版 MaixPy 韌體及訓練後 model [maixpy_yolo2](https://en.bbs.sipeed.com/uploads/default/original/1X/b29f5206df383ebad3b2e5c62f2870862a106994.zip) 下載：

    ```
    PS D:\temp\maixpy_yolo2> dir


    Directory: D:\temp\maixpy_yolo2

    Mode                 LastWriteTime         Length Name
    ----                 -------------         ------ ----
    -a---         2019/3/23 下午 07:39         336534 face_3M.kfpkg
    -a---         2019/3/24 上午 01:13        1116352 maixpy_yolo2.bin
    ```

1. 燒錄韌體檔, MaixPy 的範例常常會因為要載入的 Model 檔比較大, 所以搭配精簡版的 MainPy 韌體, 不過這裡我燒錄跟著 model 一起的韌體會有問題, 所以直接燒錄完整版的 MaixPy 韌體, 裡面已經在指定位址放有人臉偵測所需要的 model 檔了：

    ![](https://i.imgur.com/Ybe72QL.png)

1. 燒錄 model 檔：

    ![](https://i.imgur.com/85yOU52.png)

    :::info
    .kfpkg 檔不需要指定位址, 直接燒錄即可。
    :::
    

1. 開啟 machine_vision\demo_find_face.py 範例檔：

    ```python=1
    #refer to http://blog.sipeed.com/p/675.html
    import sensor
    import image
    import lcd
    import KPU as kpu

    lcd.init()
    sensor.reset()
    sensor.set_pixformat(sensor.RGB565)
    sensor.set_framesize(sensor.QVGA)
    sensor.run(1)
    task = kpu.load(0x300000) # you need put model(face.kfpkg) in flash at address 0x300000
    # task = kpu.load("/sd/face.kmodel")
    anchor = (1.889, 2.5245, 2.9465, 3.94056, 3.99987, 5.3658, 5.155437, 6.92275, 6.718375, 9.01025)
    a = kpu.init_yolo2(task, 0.5, 0.3, 5, anchor)
    while(True):
        img = sensor.snapshot()
        code = kpu.run_yolo2(task, img)
        if code:
            for i in code:
                print(i)
                a = img.draw_rectangle(i.rect())
        a = lcd.display(img)
    a = kpu.deinit(task)
    ```
    
    :::info
    MaixPy 的範例不知道為什麼很喜歡接收傳回值, 範例中的 a 其實都不會再用到, 但是都會在叫用函式或是方法實用 a 接收傳回值, 如果不喜歡, 也可以改掉。
    :::

    :::info
    如果你覺得燒錄 model 檔, 在程式中以指定位址載入 model 資料很麻煩, 可以把程式中的第 12 行：
    
    ```python=11
    task = kpu.load(0x300000) # you need put model(face.kfpkg) in flash at address 0x300000
    ```
    
    改掉, 先將 .kmodel 格式的 model 檔放在 MicroSD 卡的根路徑下, 插入控制板, 即可用以下程式載入 model：
    
    ```python=11
    task = kpu.load("/sd/face.kmodel")    
    ```
    
    :::
    
1. 執行後即可偵測人臉：

    ![](https://i.imgur.com/jR0o2pN.png)

## 物件分類

- 原始文章：[MaixPy Run 20-classes object detection based on tiny-yolov2 in 30 lines~](https://blog.sipeed.com/p/677.html)
- 韌體、範例、模型下載 [maixpy_20class.zip](https://en.bbs.sipeed.com/uploads/default/original/1X/fb175ec3815db07fc98a4f250b8ba7e2fef53c3c.zip)

1. 燒錄 model 檔：

    ![](https://i.imgur.com/l9hoNKw.png)

2. 此範例可沿用韌體, 不用特別去燒錄隨 model 檔下載的精簡版韌體, 開啟範例後有地方要修改一下：

    ```python=24
        if code:
            for i in code:
                a=img.draw_rectangle(i.rect())
                a = lcd.display(img)
                for i in code:
                    lcd.draw_string(i.x(), i.y(), classes[i.classid()], lcd.RED, lcd.WHITE)
                    lcd.draw_string(i.x(), i.y()+12, '%f1.3'%i.value(), lcd.RED, lcd.WHITE)
        else:
            a = lcd.display(img)
    ```

    原來程式第 28 這裡應該是多了迴圈, 把迴圈去掉, 只需要把辨識出來的物件名稱和信心指數秀出來就可以了。另外, 這裡是單獨將上述資訊顯示在 LCD 上, IDE 的即時畫面看不到, 因此也一併修改成先將辨識結果的資訊寫到 img 上, 最後在將 img 顯示在 LCD 上。修正過的程式如下：
    
    ```python=1
    import sensor,image,lcd,time
    import KPU as kpu

    lcd.init(freq=15000000)
    sensor.reset()
    sensor.set_pixformat(sensor.RGB565)
    sensor.set_framesize(sensor.QVGA)
    sensor.set_vflip(1)
    sensor.run(1)
    clock = time.clock()
    classes = ['aeroplane', 'bicycle', 'bird', 'boat', 'bottle', 'bus', 'car', 'cat', 'chair', 'cow', 'diningtable', 'dog', 'horse', 'motorbike', 'person', 'pottedplant', 'sheep', 'sofa', 'train', 'tvmonitor']
    task = kpu.load(0x500000)
    anchor = (1.889, 2.5245, 2.9465, 3.94056, 3.99987, 5.3658, 5.155437, 6.92275, 6.718375, 9.01025)
    kpu.init_yolo2(task, 0.5, 0.3, 5, anchor)
    while(True):
        clock.tick()
        img = sensor.snapshot()
        code = kpu.run_yolo2(task, img)
        print(clock.fps())
        if code:
            for i in code:
                img.draw_rectangle(i.rect())
                img.draw_string(i.x(), i.y(), classes[i.classid()], (255,0,0))
                img.draw_string(i.x(), i.y()+12, '%f1.3'%i.value(), (255,0,0))
        lcd.display(img)
    kpu.deinit(task)
    ```

    :::warning
    如果修改程式碼要重新執行程式, 會出現記憶體不足的錯誤：
    
    ![](https://i.imgur.com/oIR3MBk.png)

    只能按一下板子上的 `RESET` 鈕, 在 IDE 中重新連線後再執行。
    :::

1. 執行後會再找到的物件標示方框, 並在方框左上角顯示物件名稱與信心指數：

    ![](https://i.imgur.com/VSDmmQY.png)
    
    [展示影片](https://www.youtube.com/watch?v=A1f3IDwHGMU)


## 手寫數字辨識

- 原文 [Run MNIST on MaixPy in 30 lines code](https://blog.sipeed.com/p/668.html)
- 模型、範例檔案 [mnist maixpy.zip](https://en.bbs.sipeed.com/uploads/default/original/1X/117fd26dce539def92e28a6cea5a907368ed6df8.zip)

1. 燒錄 model 檔：

    ![](https://i.imgur.com/wWeIDOF.png)

2. 複製原文出處的程式檔執行：

    ```python
    import sensor,lcd,image
    import KPU as kpu
    lcd.init()
    sensor.reset()
    sensor.set_pixformat(sensor.RGB565)
    sensor.set_framesize(sensor.QVGA)
    sensor.set_windowing((224, 224))    #set to 224x224 input
    sensor.set_hmirror(0)               #flip camera
    task = kpu.load(0x200000)           #load model from flash address 0x200000
    sensor.run(1)
    while True:
        img = sensor.snapshot()
        lcd.display(img,oft=(0,0))      #display large picture
        img1=img.to_grayscale(1)        #convert to gray
        img2=img1.resize(28,28)         #resize to mnist input 28x28
        a=img2.invert()                 #invert picture as mnist need
        a=img2.strech_char(1)           #preprocessing pictures, eliminate dark corner
        lcd.display(img2,oft=(224,32))  #display small 28x28 picture
        a=img2.pix_to_ai();             #generate data for ai
        fmap=kpu.forward(task,img2)     #run neural network model
        plist=fmap[:]                   #get result (10 digit's probability)
        pmax=max(plist)                 #get max probability
        max_index=plist.index(pmax)     #get the digit
        lcd.draw_string(224,0,"%d: %.3f"%(max_index,pmax),lcd.WHITE,lcd.BLACK)  #show result
        a = img.draw_rectangle(5,0,70,12,(0,0,0), fill=True)
        a = img.draw_string(10,0,"%d: %.3f"%(max_index,pmax),(255,255,255))  #show result
        #a = lcd.display(img)      #display large picture
    ```
    
    執行結果：
    
    ![](https://i.imgur.com/l3fGmQn.png) ![](https://i.imgur.com/Yih2FnB.png) 
    ![](https://i.imgur.com/nPDqaZk.png) ![](https://i.imgur.com/Qn3jOyE.png)
    ![](https://i.imgur.com/bp1zxgj.png) ![](https://i.imgur.com/B9Z7ilO.png)

    辨識失敗的結果：
    
    ![](https://i.imgur.com/cgcuUFL.png) ![](https://i.imgur.com/1EYiaCN.png)

    [展示影片](https://www.youtube.com/watch?v=jX0bXy5m5jY)
    
## 人臉即時辨識

- 原文在[MaixPy實現人臉識別](https://blog.sipeed.com/p/1338.html#more-1338)
- 下載 [key_gen](https://en.bbs.sipeed.com/uploads/default/original/1X/bca0832bed92a1ada63bd05327688784e2ef14d1.zip) 韌體

1. 燒錄 key_gen 韌體後重新開機, 即可在序列埠終端機視窗中看到序號：

    ![](https://i.imgur.com/mjmBbyB.png)
    
2. 到 [Maix AIOT 平台](https://www.maixhub.com/)註冊帳號後, 進入善心人士貢獻的[人臉辨識模式頁面](https://www.maixhub.com/index.php/index/index/detail/id/235.html)捲到最底下按下載鈕：
    
    ![](https://i.imgur.com/4t5rpi6.png)

    在頁面中輸入剛剛看到的序號：
    
    ![](https://i.imgur.com/XqMJD69.png)

    按下提交後必須等待一段時間 (約 30 秒) 才會開始下載。
    
1. 燒錄剛剛下載取得的 .kfpkg 檔：

    ![](https://i.imgur.com/qpPQhUQ.png)

1. 開啟 MaixPy 範例檔中 machine_vision\demo_face_recognition.py 檔案, 不過這份程式有誤, 程式中只有 10 個人名代號, 但是在按下板子上的 `BOOT` 鈕記錄人臉時, 並不會檢查是否已經超過 10 個人臉, 所以會導致第 11 張臉時程式掛掉。另外, 也沒有處理按鈕的 debounce：

    ```python=16
    def check_key():
        global last_key_state
        global key_pressed 
        val=key_gpio.value()
        if last_key_state == 1 and val == 0:
            key_pressed=1
        else:
            key_pressed=0
        last_key_state = val
    ```
    
    ```python=93
    if key_pressed == 1:
        key_pressed = 0
        record_ftr = feature
        record_ftrs.append(record_ftr)
    break
    ```
    
    因此, 我把程式改掉了：
    
    ```python=1
    # Download model from: https://www.maixhub.com/index.php/index/index/detail/id/235
    import sensor,image,lcd
    import KPU as kpu
    import time
    from Maix import FPIOA,GPIO
    task_fd = kpu.load(0x200000)
    task_ld = kpu.load(0x300000)
    task_fe = kpu.load(0x400000)
    clock = time.clock()
    key_pin=16
    fpioa = FPIOA()
    fpioa.set_function(key_pin,FPIOA.GPIO7)
    key_gpio=GPIO(GPIO.GPIO7,GPIO.IN)
    last_key_state=1
    key_pressed=0
    def check_key():
        global last_key_state
        global key_pressed
        val=key_gpio.value()
        print(val)
        key_pressed=0
        if last_key_state == 1 and val == 0:
            time.sleep(0.02)
            val=key_gpio.value()
            if val == 0:
                key_pressed=1
        last_key_state = val

    lcd.init()
    sensor.reset()
    sensor.set_pixformat(sensor.RGB565)
    sensor.set_framesize(sensor.QVGA)
    sensor.set_hmirror(1)
    sensor.set_vflip(1)
    sensor.run(1)
    anchor = (1.889, 2.5245, 2.9465, 3.94056, 3.99987, 5.3658, 5.155437, 6.92275, 6.718375, 9.01025) #anchor for face detect
    dst_point = [(44,59),(84,59),(64,82),(47,105),(81,105)] #standard face key point position
    a = kpu.init_yolo2(task_fd, 0.5, 0.3, 5, anchor)
    img_lcd=image.Image()
    img_face=image.Image(size=(128,128))
    a=img_face.pix_to_ai()
    record_ftr=[]
    record_ftrs=[]
    names = ['Mr.1', 'Mr.2', 'Mr.3', 'Mr.4', 'Mr.5', 'Mr.6', 'Mr.7', 'Mr.8', 'Mr.9' , 'Mr.10']
    while(1):
        check_key()
        img = sensor.snapshot()
        clock.tick()
        code = kpu.run_yolo2(task_fd, img)
        if code:
            for i in code:
                # Cut face and resize to 128x128
                a = img.draw_rectangle(i.rect())
                face_cut=img.cut(i.x(),i.y(),i.w(),i.h())
                face_cut_128=face_cut.resize(128,128)
                a=face_cut_128.pix_to_ai()
                #a = img.draw_image(face_cut_128, (0,0))
                # Landmark for face 5 points
                fmap = kpu.forward(task_ld, face_cut_128)
                plist=fmap[:]
                le=(i.x()+int(plist[0]*i.w() - 10), i.y()+int(plist[1]*i.h()))
                re=(i.x()+int(plist[2]*i.w()), i.y()+int(plist[3]*i.h()))
                nose=(i.x()+int(plist[4]*i.w()), i.y()+int(plist[5]*i.h()))
                lm=(i.x()+int(plist[6]*i.w()), i.y()+int(plist[7]*i.h()))
                rm=(i.x()+int(plist[8]*i.w()), i.y()+int(plist[9]*i.h()))
                a = img.draw_circle(le[0], le[1], 4)
                a = img.draw_circle(re[0], re[1], 4)
                a = img.draw_circle(nose[0], nose[1], 4)
                a = img.draw_circle(lm[0], lm[1], 4)
                a = img.draw_circle(rm[0], rm[1], 4)
                # align face to standard position
                src_point = [le, re, nose, lm, rm]
                T=image.get_affine_transform(src_point, dst_point)
                a=image.warp_affine_ai(img, img_face, T)
                a=img_face.ai_to_pix()
                #a = img.draw_image(img_face, (128,0))
                del(face_cut_128)
                # calculate face feature vector
                fmap = kpu.forward(task_fe, img_face)
                feature=kpu.face_encode(fmap[:])
                reg_flag = False
                scores = []
                for j in range(len(record_ftrs)):
                    score = kpu.face_compare(record_ftrs[j], feature)
                    scores.append(score)
                max_score = 0
                index = 0
                for k in range(len(scores)):
                    if max_score < scores[k]:
                        max_score = scores[k]
                        index = k
                if max_score > 85:
                    a = img.draw_string(i.x(),i.y(), ("%s :%2.1f" % (names[index], max_score)), color=(0,255,0),scale=2)
                else:
                    a = img.draw_string(i.x(),i.y(), ("X :%2.1f" % (max_score)), color=(255,0,0),scale=2)
                if key_pressed == 1:
                    key_pressed = 0
                    if len(record_ftrs) < len(names):
                        print("record feature %d" % len(record_ftrs))
                        record_ftr = feature
                        record_ftrs.append(record_ftr)
                break
        fps =clock.fps()
        #print("%2.1f fps"%fps)
        a = lcd.display(img)
        #kpu.memtest()

    #a = kpu.deinit(task_fe)
    #a = kpu.deinit(task_ld)
    #a = kpu.deinit(task_fd)
    ```

    執行後若看到有找到臉的五點特徵, 就可以按 `BOOT` 記錄, 之後就會跟記錄的特徵比對, 來判別是哪一張臉。

    [展示影片](https://www.youtube.com/watch?v=-gzSJug8_fM)

    :::warning
    這程式沒有很穩, 跑一跑很容易當掉：
    
    
    :::


