第三十四章 image圖像濾波實驗
在上一章節中,介紹了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(3*3)、2(5*5)或更高值。
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(3*3)、2(5*5)或更高值。
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(3*3)、2(5*5)或更高值。
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.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按鍵還能夠切換處理方式,如下圖所示: