《DNK210使用指南 -CanMV版 V1.0》第三十四章 image影像濾波實驗

正点原子發表於2024-10-28

第三十四章 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模組中影像濾波的使用。
本章分為如下幾個小節:
34.1 image模組影像濾波方法介紹
34.2 硬體設計
34.3 程式設計
34.4 執行驗證

34.1 image模組影像濾波方法介紹
image模組為Image物件提供了histeq()方法,用於對影像進行直方圖均衡處理,histeq()方法如下所示:

image.histeq(adaptive=False, clip_limit=-1)

histeq()方法用於對影像進行直方圖均衡處理,直方圖均衡處理能夠使得影像中的對比度和亮度標準化。
adaptive指的是是否使用自適應直方圖均衡演算法,自適應直方圖均衡演算法通常比非自適應直方圖均衡演算法效果更好,但需要更長的執行時間,當為False時,使用非自適應直方圖均衡演算法,當為True時,使用自適應直方圖均衡演算法,預設為False。
clip_limit指的是自適應均衡對比度,預設為-1。
histeq()方法會返回經過處理的Image物件。
histeq()方法的使用示例如下所示:

import image
img = image.Image(size=(320, 240))
img.histeq(adaptive=True, clip_limit=3)

image模組為Image物件提供了gaussian()方法,用於對影像進行模糊濾波處理,gaussian()方法如下所示:

image.gaussian(size, unsharp=False, mul, add=0, threshold=False, offset=0, invert=False, mask)

gaussian()方法用於對影像進行模糊濾波處理,具體的實現方式是使用平滑高斯核對影像進行卷積。
size指的是卷積核的大小,可為1(33)、2(55)或更高值。
unsharp指的是執行非銳化掩膜操作,從而提高邊緣的影像清晰度。
mul指的是用以與卷積結果相乘的數字,若不設定,則使用預設的自動值,該值將放置卷積輸出中的縮放,可以進行全域性對比度調整。
add指的是用來與每個畫素卷積結果相加的數值,可以進行全域性亮度調整。
threshold指的是是否開啟影像的自適應閾值處理,開啟後可以根據環境畫素的亮度,將畫素設定為1或者0。
offset指的是開啟影像的自適應閾值處理後,如何將畫素設定為1,若為負數,則會將更多的畫素設定為1,若為正數,則僅將最強對比度的畫素設定為1。
invert指的是是否反轉二進位制影像的輸出結果。
mask指的是另一個用作繪圖操作的畫素級掩碼的影像,掩碼應該是一個只有黑色和白色畫素的影像,並且因該與所處理的Image物件具有相同的大小,僅有掩碼中設定的畫素會被修改。
gaussian()方法會返回經過處理的Image物件。
gaussian()方法的使用示例如下所示:

import image
img = image.Image(size=(320, 240))
img.gaussian(2)

image模組為Image物件提供了cartoon()方法,用於對影像進行卡通濾波處理,cartoon()方法如下所示:

image.cartoon(seed_threshold=0.05, floating_threshold=0.05, mask)

cartoon()方法用於對影像進行卡通濾波處理,對影像進行卡通濾波後,還會使用flood-fills演算法填充影像中的所有畫素區域,透過使影像的所有區域顏色變平來有效地從影像中去除紋理,為了獲得最佳效果,影像應具有大量對比度,以使區域不會太容易相互滲透。
seed_threshold指的是填充區域中的畫素與原始起始畫素的差異。
floating_threshold指的是填充區域中的畫素與任何相鄰畫素的差異。
mask指的是另一個用作繪圖操作的畫素級掩碼的影像,掩碼應該是一個只有黑色和白色畫素的影像,並且因該與所處理的Image物件具有相同的大小,僅有掩碼中設定的畫素會被修改。
cartoon()方法會返回經過處理的Image物件。
cartoon()方法的使用示例如下所示:

import image
img = image.Image(size=(320, 240))
img.cartoon(seed_threshold=0.2, floating_threshold=0.05)

image模組為Image物件提供了binary()方法,用於對影像進行二值濾波處理,binary()方法如下所示:

image.binary(thresholds, invert=False, zero=False, mask)

binary()方法用於對影像進行二值濾波處理,二值濾波處理後的影像中的所有畫素會被設定為黑色或白色。
thresholds指的是閾值列表,方法會根據畫素值是否在閾值列表中的閾值內,來決定將畫素這是為黑色或者白色。
invert指的是是否對閾值進行反轉操作。
zero指的是將閾值畫素清零,並使不在閾值列表中的畫素保持不變。
mask指的是另一個用作繪圖操作的畫素級掩碼的影像,掩碼應該是一個只有黑色和白色畫素的影像,並且因該與所處理的Image物件具有相同的大小,僅有掩碼中設定的畫素會被修改。
binary()方法會返回經過處理的Image物件。
binary()方法的使用示例如下所示:

import image
img = image.Image(size=(320, 240))
img.binary([(25, 94, -12, 32, -71, -12)], invert=True, zero=True)

image模組為Image物件提供了laplacian()方法,用於對影像進行邊緣濾波處理,laplacian()方法如下所示:

image.laplacian(size, sharpen=False, mul, add=0, threshold=False, offset=0, invert=False, mask)

laplacian()方法用於對影像進行邊緣濾波處理,具體的實現方式是使用拉普拉斯核對影像進行卷積。
size指的是卷積核的大小,可為1(33)、2(55)或更高值。
sharpen指的是是否改為銳化想,而不是僅輸出未經過閾值處理的邊緣檢測影像,增加摺積核大小然後增加影像清晰度。
mul指的是用以與卷積結果相乘的數字,若不設定,則使用預設的自動值,該值將放置卷積輸出中的縮放,可以進行全域性對比度調整。
add指的是用來與每個畫素卷積結果相加的數值,可以進行全域性亮度調整。
threshold指的是是否開啟影像的自適應閾值處理,開啟後可以根據環境畫素的亮度,將畫素設定為1或者0。
offset指的是開啟影像的自適應閾值處理後,如何將畫素設定為1,若為負數,則會將更多的畫素設定為1,若為正數,則僅將最強對比度的畫素設定為1。
invert指的是是否反轉二進位制影像的輸出結果。
mask指的是另一個用作繪圖操作的畫素級掩碼的影像,掩碼應該是一個只有黑色和白色畫素的影像,並且因該與所處理的Image物件具有相同的大小,僅有掩碼中設定的畫素會被修改。
laplacian()方法會返回經過處理的Image物件。
laplacian()方法的使用示例如下所示:

import image
img = image.Image(size=(320, 240))
img.laplacian(1)

image模組為Image物件提供了morph()方法,用於對影像進行卷積處理,morph()方法如下所示:

image.morph(size, kernel, mul, add=1, threshold=False, offset=0, invert=False, mask)

morph()方法用於對影像進行卷積處理,需要提供卷積操作使用的卷積核。
size指的是卷積核的大小,可為1(33)、2(55)或更高值。
mul指的是用以與卷積結果相乘的數字,若不設定,則使用預設的自動值,該值將放置卷積輸出中的縮放,可以進行全域性對比度調整。
add指的是用來與每個畫素卷積結果相加的數值,可以進行全域性亮度調整。
threshold指的是是否開啟影像的自適應閾值處理,開啟後可以根據環境畫素的亮度,將畫素設定為1或者0。
offset指的是開啟影像的自適應閾值處理後,如何將畫素設定為1,若為負數,則會將更多的畫素設定為1,若為正數,則僅將最強對比度的畫素設定為1。
invert指的是是否反轉二進位制影像的輸出結果。
mask指的是另一個用作繪圖操作的畫素級掩碼的影像,掩碼應該是一個只有黑色和白色畫素的影像,並且因該與所處理的Image物件具有相同的大小,僅有掩碼中設定的畫素會被修改。
morph()方法會返回經過處理的Image物件。
morph()方法的使用示例如下所示:

import image
kernrl = [
    -1,  0,  1,
    -2,  0,  2,
    -1,  0,  1
]
img = image.Image(size=(320, 240))
img.morph(1, kernrl)

image模組為Image物件提供了negate()方法,用於對影像進行畫素翻轉處理,negate()方法如下所示:

image.negate()

negate()方法用於對影像進行畫素翻轉處理,處理的速度非常快速,且能夠對每個顏色通道的畫素值進行數值轉換。
negate()方法會返回經過處理的Image物件。
negate()方法的使用示例如下所示:

import image
img = image.Image(size=(320, 240))
img.negate()

image模組為Image物件提供了rotation_corr()方法,用於對影像進行透視矯正處理,rotation_corr()方法如下所示:

image.rotation_corr(x_rotation=0, y_rotation=0, z_rotation=0, x_translation=0, y_translation=0, zoom=1,
 fov=60, corners)

roataion_corr()方法用於對影像進行透視矯正處理,透過對影像進行三維旋轉來糾正影像中的透視問題。
x_rotation、y_rotation和z_rotation指的是影像繞X、Y和Z軸旋轉的角度度數,即分別對應上下旋轉、左右旋轉和平面旋轉。
x_translation和y_translation指的是影像旋轉後沿X或Y轉平移的單位數,因為轉換應用於三維空間,因此單位並不是畫素。
zoom指的是影像縮放的倍數,預設為1。
fov指的是在進行二維到三維投影時,在三維空間旋轉影像之前內部使用的視場,當這個值接近0時,影像將被放置在距離視口無限遠的地方,當這個值接近180時,影像將被放置在視口中,通常,不應該改變這個引數的預設值,但可以透過修改它來改變二維到三維的對映效果。
corners指的是一個擁有四個(x, y)tuples的list,代表四個corner用來建立四點對應單應性,將第一個corner對映到(0, 0),第二個corner(image_width-1, 0),第三個corner(image_width-1, image_height-1)和第四個corner(0, image_height-1),然後在影像被重新對映後應用三維旋轉旋轉,這個引數允許使用rotation_corr()方法來做一些事情,比如鳥瞰圖轉換。
rotation_corr()方法會返回經過處理的Image物件。
rotation_corr()方法的使用示例如下所示:

import image
img = image.Image(size=(320, 240))
target_point = [
    (-50, -50),
    (img.width()-1, 0),
    (img.width()-1+50, img.height()-1+50),
    (0, img.height()-1)
]
img.rotation_corr(corners=target_point)

image模組為Image物件提供了replace()方法,用於對影像進行映象和翻轉處理,replace()方法如下所示:

image.replace(hmirror=False, vflip=False, mask)

replace()方法用於對影像進行映象和翻轉處理。
hmirror指的是是否對影像進行水平映象處理。
vflip指的是是否對影像進行垂直翻轉處理。
mask指的是另一個用作繪圖操作的畫素級掩碼的影像,掩碼應該是一個只有黑色和白色畫素的影像,並且因該與所處理的Image物件具有相同的大小,僅有掩碼中設定的畫素會被修改。
replace()方法會返回經過處理的Image物件。
replace()方法的使用示例如下所示:

import image
img = image.Image(size=(320, 240))
img.replace(hmirror=True)

34.2 硬體設計
34.2.1 例程功能

  1. 獲取攝像頭輸出的影像,並使用image模組對影像進行一些處理後,將影像顯示在LCD上。
  2. 當KEY0按鍵被按下後,切換image模組對影像的處理方式。
    34.2.2 硬體資源
    本章實驗內容,主要講解image模組的使用,無需關注硬體資源。
    34.2.3 原理圖
    本章實驗內容,主要講解image模組的使用,無需關注原理圖。

34.3 程式設計
34.3.1 image模組影像濾波方法介紹
有關image模組影像濾波方法的介紹,請見第34.1小節《image模組影像濾波方法介紹》。
34.3.2 程式流程圖

圖34.3.2.1image影像濾波實驗流程圖

34.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 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: "AdaptiveHistogram Equalization",
    2: "Blur",
    3: "Cartoon",
    4: "Binary",
    5: "Edge",
    6: "Kernel",
    7: "Negative",
    8: "PerspectiveCorrection",
    9: "Mirror &Flip"
}
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:
       # 直方圖均衡
       img.histeq(adaptive=True, clip_limit=3)
    elif type == 2:
       # 模糊濾波
       img.gaussian(2)
    elif type == 3:
       # 卡通濾波
       img.cartoon(seed_threshold=0.2,floating_thresholds=0.05)
    elif type == 4:
       # 二值濾波
       img.binary([(25, 94, -12, 32, -71, -12)], invert=True, zero=True)
    elif type == 5:
       # 邊緣濾波
       img.laplacian(1)
    elif type == 6:
       kernrl = [
           -1,  0,  1,
           -2,  0,  2,
           -1,  0,  1
       ]
       # 影像卷積
       img.morph(1, kernrl)
    elif type == 7:
       # 畫素翻轉
       img.negate()
    elif type == 8:
       target_point = [
           (-50, -50),
           (img.width()-1, 0),
           (img.width()-1+50, img.height()-1+50),
           (0, img.height()-1)
       ]
       # 透視矯正
       img.rotation_corr(corners=target_point)
    elif type == 9:
       # 映象和翻轉
       img.replace(hmirror=True, vflip=True)
    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顯示處理好後的影像。

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

圖34.4.1 攝像頭原圖影像


圖34.4.2 直方圖均衡處理後影像


圖34.4.3 模糊濾波處理後影像


圖34.4.4 卡通濾波處理後影像


圖34.4.5 二值濾波處理後影像


圖34.4.6 邊緣濾波處理後影像


圖34.4.7 影像卷積處理後影像


圖34.4.8 畫素翻轉處理後影像


圖34.4.9 透視矯正處理後影像


圖34.4.10 映象和翻轉處理後影像

相關文章