《DNK210使用指南 -CanMV版 V1.0》第三十五章 image影像特徵檢測實驗

正点原子發表於2024-11-05

第三十五章 image影像特徵檢測實驗

1)實驗平臺:正點原子DNK210開發板

2)章節摘自【正點原子】DNK210使用指南 - CanMV版 V1.0

3)購買連結:https://detail.tmall.com/item.htm?&id=782801398750

4)全套實驗原始碼+手冊+影片下載地址:http://www.openedv.com/docs/boards/k210/ATK-DNK210.html

5)正點原子官方B站:https://space.bilibili.com/394620890

6)正點原子K210技術交流企鵝群:605557868

在上一章節中,介紹了image模組中影像濾波方法給的使用,本章將繼續介紹image模組中影像特徵檢測方法的使用。透過本章的學習,讀者將學習到image模組中影像特徵檢測的使用。
本章分為如下幾個小節:
35.1 image模組影像特徵檢測方法介紹
35.2 硬體設計
35.3 程式設計
35.4 執行驗證

35.1 image模組影像特徵檢測方法介紹
image模組為Image物件提供了find_edges()方法,用於檢測影像中的邊緣特徵,find_edges()方法如下所示:

image.find_edges(edge_type, threshold=(100, 200))

find_edges()方法用於檢測影像中的邊緣特徵,該方法會將影像變為黑白,僅將邊緣畫素保留為白色,需要注意的是該方法僅支援灰度影像。
edge_type指的是邊緣檢測演算法的選擇,可以是image.EDGE_SIMPLE(簡單的閾值高通濾波演算法)或image.EDGE_CANNY(Canny邊緣檢測演算法)。
threshold指的是一個包含一個低閾值和一個高閾值的二值元組,可以透過調整閾值來控制邊緣質量,預設為(100, 200)。
find_edges()方法會返回經過處理的Image物件。
find_edges()方法的使用示例如下所示:

import image
img = image.Image(size=(320, 240))
img.to_grayscale()
img.find_edges(image.EDGE_SIMPLE, threshold=(100, 255))

image模組為Image物件提供了find_circles()方法,用於檢測影像中的圓形特徵,find_circles()方法如下所示:

image.find_circles(roi, x_stride=2, y_stride=1, threshold=2000, x_margin=10, y_margin=10, 
r_margin=10, r_min=2, r_max, r_step=2)

find_circles()方法用於檢測影像中的圓形特徵,該方法使用霍夫變換在影像中查詢圓。
roi指的是對Image物件感興趣的區域,若未指定,即為影像矩形。
x_stride和y_stride指的是霍夫變換時需要跳過的X和Y畫素的數量,若已知被檢測圓的半徑較大,可以增加該引數。
threshold指的是霍夫變換閾值,只返回大於或等於閾值的圓。
x_margin、y_margin和r_margin指的是控制所檢測的圓的合併,圓畫素為x_margin、y_margin和r_margin的部分合並。
r_min和r_max指的是圓半徑的閾值,只返回半徑在閾值間的圓。
r_step指的是檢測時的半徑步進。
find_cricles()方法會返回一個image.circle物件列表
find_circles()方法的使用示例如下所示:

import image
img = image.Image(size=(320, 240))
circles = img.find_circles((0, 0, img.width(), img.height()), x_stride=2, y_stride=2, threshold=3800,
 x_margin=50, y_margin=50, r_margin=50, r_min=60, r_max=80, r_step=5)
for c in circles:
    img.draw_circle(c.x(), c.y(), c.r(), color=(255, 0, 0), thickness=2)

image模組為Image物件提供了find_lines()方法,用於檢測影像中的直線特徵,find_lines()方法如下所示:

image.find_lines(roi, x_stride=2, y_stride=1, threshold=1000, theta_margin=25, rho_margin=25)

find_lines()方法用於檢測影像中的直線特徵,該方法使用霍夫變換在影像中查詢直線。
roi指的是對Image物件感興趣的區域,若未指定,即為影像矩形。
x_stride和y_stride指的是霍夫變換時需要跳過的X和Y畫素的數量,若已知被檢測直線較大,可以增加該引數。
threshold指的是霍夫變換閾值,只返回大於或等於閾值的直線。
theta_margin和rho_margin指的是所檢測直線的合併,直線角度為theta_margin的部分和直線p值為rho_margin的部分合並。
find_lines()方法會返回image.line物件列表。
find_lines()方法的使用示例如下所示:

import image
img = image.Image(size=(320, 240))
lines = img.find_lines((0, 0, img.width(), img.height()), x_stride=2, y_stride=1, threshold=1000, theta_margin=25, rho_margin=25)
for l in lines:
    img.draw_line(l.line(), color=(255, 0, 0), thickness=2)

image模組為Image物件提供了find_hog()方法,用於檢測影像中的定向梯度特徵,find_hog()方法如下所示:

image.find_hog(roi, size=8)

find_hog()方法用於用HoG(定向梯度直方圖)線替換影像中的畫素,需要注意的是該方法僅支援灰度影像。
roi指的是對Image物件感興趣的區域,若未指定,即為影像矩形。
size指的是HoG的尺寸。
find_hog()方法會返回經過處理的Image物件。
find_hog()方法的使用示例如下所示:

import image
img = image.Image(size=(320, 240))
img.find_hog((0, 0, img.width(), img.height()), size=8)

35.2 硬體設計
35.2.1 例程功能

  1. 獲取攝像頭輸出的影像,並使用image模組對影像進行一些特徵檢測後,將影像顯示在LCD上。
  2. 當KEY0按鍵被按下後,切換image模組對影像的特徵檢測方式。
    35.2.2 硬體資源
    本章實驗內容,主要講解image模組的使用,無需關注硬體資源。
    35.2.3 原理圖
    本章實驗內容,主要講解image模組的使用,無需關注原理圖。
    35.3 程式設計
    35.3.1 image模組影像特徵檢測方法介紹
    有關image模組影像特徵檢測方法的介紹,請見第35.1小節《image模組影像特徵檢測方法介紹》。
    35.3.2 程式流程圖

    圖35.3.2.1image影像特徵檢測實驗流程圖

35.3.3 main.py程式碼
main.py中的指令碼程式碼如下所示:

from board import board_info
from fpioa_manager import fm
from maix import GPIO
import time
import lcd
import sensor
import image
import gc
lcd.init()
sensor.reset()
sensor.set_framesize(sensor.QVGA)
sensor.set_pixformat(sensor.RGB565)
sensor.set_hmirror(False)
type = 0
type_dict = {
    0: "Normal",
    1: "Edge",
    2: "Circle",
    3: "Line",
    4: "HoG"
}
fm.register(board_info.KEY0, fm.fpioa.GPIOHS0)
key0 = GPIO(GPIO.GPIOHS0, GPIO.IN, GPIO.PULL_UP)
def key_irq_handler(key):
    global key0
    global type
   time.sleep_ms(20)
    if key is key0 and key.value() == 0:
       type = type + 1
       if type == len(type_dict):
           type = 0
key0.irq(key_irq_handler, GPIO.IRQ_FALLING, GPIO.WAKEUP_NOT_SUPPORT, 7)
while True:
    img= sensor.snapshot()
    if type == 0:
       # 原圖
       pass
    elif type == 1:
       # 邊緣檢測
       gray = img.to_grayscale(copy=True)
       gray.find_edges(image.EDGE_SIMPLE, threshold=(100, 255))
       img.draw_image(gray, 0, 0, mask=gray)
       del gray
    elif type == 2:
       # 圓形檢測
       circles = img.find_circles((0, 0, img.width(), img.height()), x_stride=2, y_stride=2, threshold=3800, 
x_margin=50, y_margin=50, r_margin=50, r_min=60, r_max=80, r_step=5)
       for c in circles:
           img.draw_circle(c.x(), c.y(), c.r(), color=(255, 0, 0), thickness=2)
    elif type == 3:
       # 直線檢測
       lines = img.find_lines((0, 0, img.width(), img.height()), x_stride=2, y_stride=1, threshold=1000, 
theta_margin=25, rho_margin=25)
       for l in lines:
           img.draw_line(l.line(), color=(255, 0, 0), thickness=2)
    elif type == 4:
       img.to_grayscale()
       # HoG檢測
       img.find_hog((0, 0, img.width(), img.height()), size=8)
    else:
       type = 0
    img.draw_string(10, 10, type_dict[type], color=(255, 0, 0), scale=1.6)
    lcd.display(img)
    gc.collect()

可以看到一開始是先初始化了LCD、攝像頭和中斷按鍵,並且按下中斷按鍵可以切換影像特徵檢測的方式。
接著在一個迴圈中不斷地獲取攝像頭輸出的影像,因為獲取到的影像就是Image物件,因此可以直接呼叫image模組為Image物件提供的各種方法,然後就是對影像進行特徵檢測,最後在LCD顯示影像以及檢測到的特徵。

35.4 執行驗證
將DNK210開發板連線CanMV IDE,點選CanMV IDE上的“開始(執行指令碼)”按鈕後,便能看到LCD上顯示了處理後的攝像頭影像,按下KEY0按鍵還能夠切換特徵檢測方式,如下圖所示:

圖35.4.1 攝像頭原圖影像

圖35.4.2 邊緣檢測

圖35.4.3 圓形檢測

圖35.4.4 直線檢測

圖35.4.5 HoG檢測

相關文章