1 背景
所以,我在這裏。乘坐Amtrak 158火車,經過長途旅行後回家。
很熱。AC幾乎無法工作。嬰兒在我旁邊尖叫,而陪伴的母親卻孤注一擲地看着窗外,清楚地質疑生孩子是否是正確的人生決定。
最重要的是,Wi-Fi無法正常工作。
幸運的是,我帶來了Game Boy和Pokemon遊戲系列。
當我將可信賴的Blue版本滑入我的Game Boy時,我想:也許我可以做一點計算機視覺相關的工作,而不是與Gary Oak對抗第一千次。
老實說,僅使用顏色就能夠分割每個遊戲卡帶真的不是很酷嗎?
拿起一杯涼爽的水來對抗不能用的AC,並用一對耳塞擋住哭泣的孩子。因爲在這篇文章中,我將向您展示如何使用OpenCV和Python進行顏色檢測。
OpenCV和python版本:
- Python 2.7/Python
- OpenCV 2.4.X/OpenCV 3.0+
2 OpenCV和Python顏色檢測
讓我們開始吧。
打開您喜歡的編輯器並創建一個名爲detect_color.py
的文件:
# import the necessary packages
import numpy as np
import argparse
import cv2
# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", help = "path to the image")
args = vars(ap.parse_args())
# load the image
image = cv2.imread(args["image"])
我們將從第2-4行導入必要的程序包開始,使用NumPy
進行數值處理,使用argparse
解析命令行參數,並使用cv2
進行OpenCV綁定。
然後,第7-9行處理解析我們的命令行參數。我們只需要一個--image
即可,它是image
在磁盤上的存儲路徑。
然後,在第12行上,從磁盤加載image
。
現在,這是有趣的部分。
我們希望能夠檢測到圖像中的每個Game Boy墨盒。這意味着我們必須識別圖像中的紅色,藍色,黃色和灰色。
讓我們繼續定義以下顏色列表:
# define the list of boundaries
boundaries = [
([17, 15, 100], [50, 56, 200]),
([86, 31, 4], [220, 88, 50]),
([25, 146, 190], [62, 174, 250]),
([103, 86, 65], [145, 133, 128])
]
我們在這裏要做的就是在RGB顏色空間中定義一個boundaries
列表(或者說BGR,因爲OpenCV將圖像表示爲NumPy數組以相反的順序),其中列表中的每個條目都是一個具有兩個值的元組:下限和上限列表。
例如,讓我們看一下元組([17, 15, 100], [50, 56, 200])
。
在這裏,我們說圖像中所有具有R>=100,B>=15和G>=17以及R<=200,B<=56和G<=50的像素將被視爲紅色。
現在我們有了boundaries
列表,我們可以使用cv2.inRange
函數執行實際的顏色檢測了。
讓我們來看看:
# loop over the boundaries
for (lower, upper) in boundaries:
# create NumPy arrays from the boundaries
lower = np.array(lower, dtype = "uint8")
upper = np.array(upper, dtype = "uint8")
# find the colors within the specified boundaries and apply
# the mask
mask = cv2.inRange(image, lower, upper)
output = cv2.bitwise_and(image, image, mask = mask)
# show the images
cv2.imshow("images", np.hstack([image, output]))
cv2.waitKey(0)
我們開始在第2行上遍歷boundaries
的上限和下限,然後在第4行和第5行上將上限和下限轉換爲NumPy數組。這兩行似乎可以省略,當您使用OpenCV的Python綁定時,OpenCV期望這些限制爲NumPy數組。此外,由於這些像素值在[0, 256]範圍內,因此我們可以使用無符號8位整型數據類型。
要使用OpenCV執行實際的顏色檢測,請看我們在第9行使用的cv2.inRange
函數。
cv2.inRange
函數需要三個參數:
- 第一個是要執行顏色檢測的圖像
- 第二個是要檢測的顏色的下限
- 第三個是要檢測的顏色的上限
調用cv2.inRange
之後,將返回一個二進制掩碼,其中白色像素(255)表示落入上限和下限範圍內的像素,而黑色像素(0)則不屬於該範圍。
注意:我們正在RGB顏色空間中執行顏色檢測。但是您也可以在HSV或L*a*b*
顏色空間中輕鬆地執行此操作。您只需要調整各個顏色空間的上限和下限即可。
爲了創建輸出圖像,我們在第10行上應用了mask
。該行僅調用cv2.bitwise_and
,僅顯示圖像中在mask
中具有相應白色(255)值的像素。
最後,我們在第13和14行上輸出圖像顯示。
不錯。只有14行代碼,其中絕大多數是導入,參數解析和註釋。
讓我們繼續運行腳本:
$ python detect_color.py --image pokemon_games.png
如果您的環境配置正確(意味着您已安裝了帶有Python綁定的OpenCV),則輸出圖像爲:
3 總結
在這篇博客文章中,我向您展示瞭如何使用OpenCV和Python執行顏色檢測。
要檢測圖像中的顏色,您需要做的第一件事就是爲像素值定義上限和下限。
定義上限和下限後,然後調用cv2.inRange方法,該方法將返回一個mask,指定哪些像素落入指定的上限和下限範圍內。
最後,現在有了mask,您可以使用cv2.bitwise_and
函數將其應用於圖像。
我的火車離家只有幾站路,所以我最好把這篇文章整理一下。希望你覺得它有用!
4 完整代碼
# import the necessary packages
import numpy as np
import argparse
import cv2
# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", help = "path to the image")
args = vars(ap.parse_args())
# load the image
image = cv2.imread(args["image"])
# define the list of boundaries
boundaries = [
([17, 15, 100], [50, 56, 200]),
([86, 31, 4], [220, 88, 50]),
([25, 146, 190], [62, 174, 250]),
([103, 86, 65], [145, 133, 128])
]
# loop over the boundaries
for (lower, upper) in boundaries:
# create NumPy arrays from the boundaries
lower = np.array(lower, dtype = "uint8")
upper = np.array(upper, dtype = "uint8")
# find the colors within the specified boundaries and apply
# the mask
mask = cv2.inRange(image, lower, upper)
output = cv2.bitwise_and(image, image, mask = mask)
# show the images
cv2.imshow("images", np.hstack([image, output]))
cv2.waitKey(0)