ROI是Region Of Interest的簡寫,字面義是感興趣的區域,或者說是需要進行某種操作的「目標區域」。
如果想要對ROI區域進行操作,首先要選中並獲取到這個區域。
最簡單的方式就是利用Numpy的數組索引切片來獲取到一個矩形ROI(當然其他形狀的ROI或許更加適合具體情況下的某些Object,但是顯然無法通過如此簡單的方法就能獲取,必須經過有一定復雜度的算法才能得到)。
假設某張image寬高形狀是[400, 400],通道數為3,那麼如果想要選中中間的一個寬高[40, 40]的物體,可以用下面這個切片索引
img[180:220, 180:220, :]
參考:OpenCV: Miscellaneous Image Transformations-floodfill()
泛洪填充的典型應用:填充和目標像素的取值相近的鄰近區域;類似Adobe Photoshop中的魔法棒工具所實現的功能。
實現泛洪填充的API是floodfill(),語法如下
cv.floodFill(image, mask, seedPoint, newVal[, loDiff[, upDiff[, flags]]]) ->retval, image, mask, rect
講點宏參數方面的問題
我們通過floodfill()的官方API文檔也可以知道,flags是有低、中、高八位的;而高八位是由宏參數定義的。
在學習C語言的時候,我們講過用define命令可以定義宏對象,比如把常用到的3.1415926...這個常數π給定義為PI,這樣我們就不用時刻把這麼長的一串數字打出來了,或者對於記憶不好的同學,也不用記π的小數點後是哪些數字了。
為了讓各位人類更方便地進行編程,不用記住那些意義不直觀的數字組合,OpenCV的開發人員把高八位的幾種選項對應的數值,預定義了幾個宏參數,我們程序員只需將宏參數字符串傳入API。
最後講一個錯誤, 大家執行下面的代碼;會發現mask沒有什麼變化,而image也發生了改變。
import cv2 as cv
import numpy as np
def fill_binary():
image = np.zeros([400, 400, 3], np.uint8)
image[100:300, 100:300, :] = 255
cv.imshow("fill_binary", image)
mask = np.ones([402, 402, 1], np.uint8)
mask[101:301, 101:301] = 0
print(np.sum(mask))
cv.floodFill(image, mask, (200, 200), (0, 0, 255), 4 | (127 << 8) | cv.FLOODFILL_MASK_ONLY)
cv.imshow("filled binary", image)
print(np.sum(mask))
print(np.unique(mask))
cv.imshow("mask", mask)
fill_binary()
cv.waitKey(0)
cv.destroyAllWindows()
這是因為,在flags參數前面還有兩個loDiff和upDiff參數;如果不給這兩個參數傳值,又不以關鍵詞參數的形式給參數flags傳值,函數就會誤將flags的值傳入loDiff,顯然是錯誤的。
修改成下面正確的版本後。
import cv2 as cv
import numpy as np
def fill_binary():
image = np.zeros([400, 400, 3], np.uint8)
image[100:300, 100:300, :] = 255
cv.imshow("fill_binary", image)
mask = np.ones([402, 402, 1], np.uint8)
mask[101:301, 101:301] = 0
print(np.sum(mask))
cv.floodFill(image, mask, (200, 200), (0, 0, 255), flags=4 | (127 << 8) | cv.FLOODFILL_MASK_ONLY)
cv.imshow("filled binary", image)
print(np.sum(mask))
print(np.unique(mask))
cv.imshow("mask", mask)
fill_binary()
cv.waitKey(0)
cv.destroyAllWindows()
這才對了!