一、學習目標
- 了解什么是ROI
- 了解floodFill的使用方法
如有錯誤歡迎指出~
目錄
[python opencv 計算機視覺零基礎到實戰] 一、opencv的helloworld
[【python opencv 計算機視覺零基礎到實戰】二、 opencv文件格式與攝像頭讀取] 一、opencv的helloworld
[[python opencv 計算機視覺零基礎到實戰] 三、numpy與圖像編輯] 一、opencv的helloworld
[[python opencv 計算機視覺零基礎到實戰] 四、了解色彩空間及其詳解] 一、opencv的helloworld
[[python opencv 計算機視覺零基礎到實戰] 五、對象追蹤] 一、opencv的helloworld
[python opencv 計算機視覺零基礎到實戰] 六、圖像運算
[python opencv 計算機視覺零基礎到實戰] 七、邏輯運算與應用
二、了解OpenCV中圖像ROI的顏色填充
2.1 了解ROI是什么
ROI指的是region of Interest,翻譯過來就是你所感興趣的區域。弱在一張圖片中,你感興趣的是某一個區域,那么這個區域就可以稱為ROI。我們通過一些方法選取了該區域后,可以進行操作;例如顏色填充、圖像變換等編輯。
先有一張圖如下:
我們對這張圖的激光雕刻機部分感興趣,那么就可以選取該部分。如何進行選取呢?我們可以通過代碼得知該圖片的大小:
import cv2
img = cv2.imread(r"C:\Users\Administrator\Desktop\1.jpg")
print(img.shape)
得到該圖片的高寬分別為447與755。
我們可以通過粗略的丈量得知激光雕刻機應在整個圖片的正中央,那么寬應該為一半,大致在200到400之間;由于圖片中激光雕刻機位于圖片偏下部分,所以可以粗略得知高度在200至400之間。這時我們可以直接讀取圖片后獲取指定的行列得到該區域圖片。
import cv2img = cv2.imread(r'C:\Users\Administrator\Desktop\1.jpg')#讀取
cv2.namedWindow("Image",cv2.WINDOW_NORMAL)#創建一個窗口
cv2.imshow("Image", img)#顯示圖像roi=img[200:400,200:400]
cv2.imshow("roi", roi)#顯示圖像cv2.waitKey (0)#等待關閉
cv2.destroyAllWindows()#destroy
以上代碼讀取圖片后,通過選取圖片區域進行ROI選擇。img[200:400,200:400]代碼中,第一個200:400指的是200指400行,第二個200:400指的是200至400列。通過兩個選取的行與列的交叉區域則是所選擇的ROI區域。圖示如下,紅色框框表示列,紫色框框表示行,其中重疊區域則是ROI選擇區域。
以上代碼在運行結果如下:
從結果中,我們可以知道,該值的列選擇還應該往右邊移動一部分,由于我們是200指400這個區域,那么我們現在應該移動的訪問從圖片上看,應該是接近300指500。修改代碼。
roi=img[200:400,280:450]
運行后最后得到如下結果:
我們得到ROI內容后,可以對該部分的內容進行編輯,例如轉為灰度圖像:
gray_roi = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)
cv2.imshow("gray_roi", gray_roi)#顯示圖像
結果如下:
也可以將轉換后的圖片與原圖進行結合,只需要將轉換后的圖片值對原圖該區域的值進行替換即可,完整代碼如下:
import cv2img = cv2.imread(r'C:\Users\Administrator\Desktop\1.jpg')#讀取
cv2.namedWindow("Image",cv2.WINDOW_NORMAL)#創建一個窗口
cv2.imshow("Image", img)#顯示圖像roi=img[200:400,280:450]
cv2.imshow("roi", roi)#顯示圖像gray_roi = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)
cv2.imshow("gray_roi", gray_roi)#顯示圖像gray_roi_rgb = cv2.cvtColor(gray_roi, cv2.COLOR_GRAY2BGR)#灰度圖像轉RGB
img[200:400,280:450]=gray_roi_rgb
cv2.imshow("Image2", img)#顯示圖像cv2.waitKey (0)#等待關閉
cv2.destroyAllWindows()#destroy
在以上代碼中需要注意的是,灰度圖像必須轉為RGB圖形才能對原圖進行賦值。以上代碼中灰度轉RGB圖像的代碼為:
gray_roi_rgb = cv2.cvtColor(gray_roi, cv2.COLOR_GRAY2BGR)
最終運行結果如下:
2.2 泛洪填充及floodFill使用方法
泛洪填充指指定起始點,通過該像素點所鏈接的周圍像素點在所指定的顏色值范圍內進行顏色填充。該操作需要一個遮罩或者說掩膜進行運算處理。
首先我們依舊開始讀取一張圖像:
import cv2
import numpy as npimg = cv2.imread(r"C:\Users\Administrator\Desktop\1.jpg")
cv2.imshow("img", img)
接著通過copy方法可以快速復制一張圖片:
copyimg = image.copy()
由于我們需要建立一個遮罩,這個遮罩跟原圖片大小一致,所以代碼可以寫成如下:
h, w = copyimg.shape[:2]
mask = np.zeros([h + 2, w + 2], np.uint8)
以上代碼通過shape獲取了原圖片的高寬,接著通過zeros創建一個與原圖大小一致的純黑圖片。那為什么要加2呢?因為接下來我們需要對圖片進行顏色填充,官方的規定要+2,具體什么原因我本人沒有進行深究,按照官方要求來就可以了。
那問題來了,遮罩是什么?還記得我們在邏輯運算應用那一個小節中,通過色彩提取后,可以得到目標對象的顏色范圍,這個顏色范圍是一張黑白圖片,白色為選取的區域,黑色為不選取的區域,這時我們通過將提取出來的圖片作為遮罩對圖片進行bitwise_and運算,這時就可以還原出原本色彩,摳選出原圖中的圖像內容。其實遮罩的作用就是如此,我們通過zeros創建一張純黑圖片后,使用floodFill函數對指定目標進行填充;在填充之前,將進行一定的計算。由于floodFill函數將會選取出目標點,該目標點將作用在這張純黑色的遮罩圖片中,該純黑圖片將會對計算后選取的點進行指的變換,該區域就會變成白色,最終得到顏色填充的區域,進行填充。
我們首先看一下floodFill函數,floodFill函數接收7個參數,函數原型如下:
floodFill(image, mask, seedPoint, newVal, loDiff=None, upDiff=None, flags=None)
- image為傳入的圖像參數
- mask為遮罩
- seedPoint為選中的顏色填充的起始點
- newVal填充的顏色像素值
- loDiff選中起始點的顏色像素值的最低范圍,例如是紅色,那么紅色減去該值后得到最低的取值范圍
- upDiff選中起始點的顏色像素值的最高范圍,例如是紅色,那么紅色加該值后得到最高的取值范圍
- flags為CV_FLOODFILL_FIXED_RANGE或者CV_FLOODFILL_MASK_ONLY
,兩者填充方式不一樣,當前示例將講解CV_FLOODFILL_FIXED_RANGE。若選擇CV_FLOODFILL_FIXED_RANGE,則會比較像素點與其實像素點,若在顏色值的范圍內,則進行填充。
此時我們調用floodFill方法,傳入圖片,遮罩,起始點,填充的顏色值,最低值,最高值與填充模式。
cv2.floodFill(copyimg, mask, (220,420), (0, 255, 255), (5, 5, 5), (5, 5 ,5), cv2.FLOODFILL_FIXED_RANGE)
copyimg為圖片;mask為遮罩;220,420為起始點;0, 255, 255為填充的顏色,為黃色;5, 5, 5為選中的起始點減去該顏色值,判斷周圍的顏色是否低于該值;5, 5 ,5為選中的起始點加上該顏色值,判斷周圍的顏色是否高于該值。最終的完整代碼如下:
img = cv2.imread(r"C:\Users\Administrator\Desktop\1.jpg")
cv2.imshow(“img”, img)
在復制圖像上進行操作
import cv2
import numpy as npimg = cv2.imread(r"C:\Users\Administrator\Desktop\1.jpg")
cv2.imshow("img", img)
copyimg = img.copy()
h, w = copyimg.shape[:2]
mask = np.zeros([h + 2, w + 2], np.uint8)
cv2.floodFill(copyimg, mask, (220,420), (0, 255, 255), (5, 5, 5), (5, 5 ,5), cv2.FLOODFILL_FIXED_RANGE)
cv2.imshow("fill_color", copyimg)cv2.waitKey (0)#等待關閉
cv2.destroyAllWindows()#destroy
運行結果如下:
我們現在可以證明220,420是否是起始點,我們可以換一個值,例如0,0。若在左上角進行顏色填充那么則判斷正確:
我們也可以改變填充值的選擇范圍,將2個5,5,5改為50,50,50,可以明顯看到效果:
cv2.floodFill(copyimg, mask, (0,0), (0, 255, 255), (50,50, 50), (50, 50 ,50), cv2.FLOODFILL_FIXED_RANGE)
這時候的相關所鏈接的顏色范圍擴大,那么所能填充的范圍也肯定是擴大,運行結果如下:
其中顏色值可以可以進行修改,修改方法不再贅述。
該系列文章首發于ebaina
三、總結
- 了解了ROI是感興趣的選擇范圍
- 了解了ROI可以通過圖片內容進行選擇,并且可以與原圖進行結合
- 了解了泛洪填充的方法
- 初步了解了mask遮罩以及floodFill函數的使用方法