第三十八章 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模組中碼識別的使用。
本章分為如下幾個小節:
38.1 image模組碼識別方法介紹
38.2 硬體設計
38.3 程式設計
38.4 執行驗證
38.1 image模組碼識別方法介紹
image模組為Image物件提供了find_barcodes()方法,用於識別影像中的條形碼,find_barcodes()方法如下所示:
image.find_barcodes(roi)
find_barcodes()方法用於識別影像中的條形碼,並會返回一個image.barcode物件列表,由於條形碼的特殊性,條形碼是一維影像,所以只需在一個方向上有較高的解析度,而在另一個方向上秩序較低的解析度。
roi指的是對Image物件感興趣的區域,若未指定,即為影像矩形。
find_barcode()方法會返回一個image.barcode物件列表。
find_barcode()方法的使用示例如下所示:
import image
img = image.Image(size=(320, 240))
barcodes = img.find_barcode()
if barcodes:
print("%s" % (barcodes[0].payload))
image模組為Image物件提供了find_datamatrices()方法,用於識別影像中的DM碼,find_datamatrices()方法如下所示:
image.find_datamatrices(roi, effort=200)
find_datamatrices()方法用於識別影像中的DM碼,並返回一個image.datamatrix物件列表,該方法要求被識別影像中的DM碼需要比較平展。
roi指的是對Image物件感興趣的區域,若未指定,即為影像矩形。
effort指的是用於控制查詢DM碼匹配的時間,預設為200,這應該適用於大部分的使用場景,需要注意的是,當該引數配置為160以下,可能無法進行任何的DM碼識別,並且當該引數可配置的最大值為240。
find_datamatrices()方法會返回一個image.datamatrix物件列表。
find_datamatrices()方法的使用示例如下所示:
import image
img = image.Image(size=(320, 240))
datamatrices = img.find_datamatrices()
if datamatrices:
print("%s" % (datamatrices[0].payload))
image模組為Image物件提供了find_qrcodes()方法,用於識別影像中的二維碼,並返回一個image.rqcode物件列表,find_rqcodes()方法如下所示:
image.find_rqcodes(roi)
find_rqcodes()方法用於識別影像中的二維碼,並返回一個image.rqcode物件列表,該方法要求被識別影像中的二維碼需要比較平展。
roi指的是對Image物件感興趣的區域,若未指定,即為影像矩形。
find_rqcodes()方法會返回一個image.rqcode物件列表。
find_rqcodes()方法的使用示例如下所示:
import image
img = image.Image(size=(320, 240))
rqcodes = img.find_rqcodes()
if rqcodes:
print("%s" % (rqcodes[0].payload))
image模組為Image物件提供了find_apriltags()方法,用於識別影像中的AprilTag碼,並返回一個image.apriltag物件列表,find_apriltags()方法如下所示:
image.find_apriltags(roi, families=image.TAG36H11, fx, fy, cx, cy)
find_apriltags()方法用於識別影像中的AprilTag碼,與二維碼相比,AprilTag碼可在更遠距離、較差光線和更扭曲的影像環境下被檢測並識別,AprilTag碼可以應對所有種類的影像失真問題,而二維碼不能,但是AprilTag碼只能作為數字ID編碼的載體。
roi指的是對Image物件感興趣的區域,若未指定,即為影像矩形。
families指的是要解碼的標籤家族的位掩碼,可以用邏輯或來同時指定解碼多種標籤家族,必須是image模組中定義號的標籤家族常量,如下表所示:
表38.1.1 image模組提供的標籤家族常量
fx和fy指的是以畫素為單位的相機X和Y方向的焦距。
cx和cy指的是影像的中心X和Y座標,即image.width() // 2和image.height() //2,而不是roi.width() // 2和roi.height() // 2。
find_airiltags()方法會返回一個image.apriltag物件列表。
find_airiltags()方法的使用示例如下所示:
import image
img = image.Image(size=(320, 240))
apriltags = img.find_apriltags(families=image.TAG36H11)
if apriltags:
print("%d" % (apriltags[0].id))
38.2 硬體設計
38.2.1 例程功能
- 獲取攝像頭輸出的影像,並使用image模組對影像進行碼識別,並在影像上繪製識別到的內容,然後將影像顯示在LCD上。
- 當KEY0按鍵被按下後,切換image模組識別影像中不同種類的碼。
38.2.2 硬體資源
本章實驗內容,主要講解image模組的使用,無需關注硬體資源。
38.2.3 原理圖
本章實驗內容,主要講解image模組的使用,無需關注原理圖。
38.3 程式設計
38.3.1 image模組影像碼識別方法介紹
有關image模組影像碼識別方法的介紹,請見第38.1小節《image模組影像碼識別方法介紹》。
38.3.2 程式流程圖
圖38.3.2.1image影像碼識別實驗流程圖
38.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 math
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: "Barcode",
2: "DataMatrices",
3: "QRCode",
4: "AprilTag"
}
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:
# 條形碼識別
roi = (img.width() // 2 - 120, img.height() // 2 - 80, 240, 160)
gray = img.copy(roi).to_grayscale()
img.draw_rectangle(roi, color=(0, 255, 0))
barcodes = gray.find_barcodes((0, 0, gray.width(), gray.height()))
if barcodes:
img.draw_string(10, 30, barcodes[0].payload(), color=(255, 0, 0), scale=1.6)
elif type == 2:
# DM碼識別
roi = (img.width() // 2 - 100, img.height() // 2 - 100, 200, 200)
gray = img.copy(roi).to_grayscale()
img.draw_rectangle(roi, color=(0, 255, 0))
datamatrices = gray.find_datamatrices((0, 0, gray.width(), gray.height()))
if datamatrices:
img.draw_string(10, 30, datamatrices[0].payload(), color=(255, 0, 0), scale=1.6)
elif type == 3:
# 二維碼識別
roi = (img.width() // 2 - 100, img.height() // 2 - 100, 200, 200)
gray = img.copy(roi).to_grayscale()
img.draw_rectangle(roi, color=(0, 255, 0))
qrcodes = gray.find_qrcodes((0, 0, gray.width(), gray.height()))
if qrcodes:
img.draw_string(10, 30, qrcodes[0].payload(), color=(255, 0, 0), scale=1.6)
elif type == 4:
# AprilTag識別
roi = (img.width() // 2 - 100, img.height() // 2 - 100, 200, 200)
gray = img.copy(roi).to_grayscale()
img.draw_rectangle(roi, color=(0, 255, 0))
apriltags = gray.find_apriltags((0, 0, gray.width(), gray.height()), families=image.TAG36H11)
if apriltags:
def shot_degrees(axis, y, rotation):
degrees = (180 * rotation) / math.pi
img.draw_string(10, y, "{:s}:{:.0f}".format(axis, degrees), color=(255, 0, 0), scale=1.6)
img.draw_string(10, 30, "ID:{:d}".format(apriltags[0].id()), color=(255, 0, 0), scale=1.6)
shot_degrees("X", 50, apriltags[0].x_rotation())
shot_degrees("Y", 70, apriltags[0].y_rotation())
shot_degrees("Z", 90, apriltags[0].z_rotation())
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上繪製識別到碼的資訊,最後在LCD顯示影像。
38.4 執行驗證
將DNK210開發板連線CanMV IDE,點選CanMV IDE上的“開始(執行指令碼)”按鈕後,便能看到LCD上顯示了攝像頭輸出的影像,並能看一個綠色的識別框,但將對應的碼移入識別框後,能夠看到LCD的左上角顯示了識別到的結果,按下KEY0按鍵還能夠切換識別碼的種類,以識別不同種類的碼,如下圖所示:
圖38.4.1 條形碼識別
圖38.4.2 DM碼識別
圖38.4.3 二維碼識別
圖38.4.4 AprilTag碼識別