這篇文章應用計算機視覺和圖像處理技術,展示了檢測烤箱開關狀態的過程。在生活中,有時你會粗心大意忘關烤箱之類的廚房電器,這潛在很大的危險。因此作者採用 Python 和 OpenCV,通過家庭攝像頭獲取的圖像來自動識別烤箱是否開著,進而可以觸發警報。
「我忘關烤箱了嗎?」
這個問題常常會在最不方便的時候出現在你的腦子裡。
有時是當你剛剛走出家門的時候。 有時是當你在上班路上的時候。 有時是當你坐在飛機上準備度個長假的時候……
解決這個問題的方法是多種多樣的:
橡皮筋的方法大聲說或唱出來(就像 Samuel L. Jackson 一樣)當你離開家去度假的時候,給烤箱在內的電器列個清單或做個標記。 或者,我們也許有更好的做法……
在本教程中,我們會嘗試利用技術手段解決這個問題。
Github 裡有完整代碼。
問題定義
對我們而言,我們需要確定一個信號,用於判斷烤箱的開關狀態。在我的廚房裡,這個信號就是頂部標記著「烤箱開」字樣的紅色燈。
當紅色燈亮的時候,烤箱是開著的:
當紅色燈滅的時候,烤箱是關著的:
預備條件
確保你的電腦上安裝了以下應用:
OpenCV 3.0Python 2.7Numpy 1.9
安裝 OpenCV3.0 和 Python 2.7
如果你尚未安裝 OpenCV,請按照 Adrian Rosebrock 的完美教程,在 OSX 系統上安裝 OpenCV 3.0 和 Python 2.7+。我在安裝步驟裡增加了一些自己的注釋,以防你在 OSX 上編譯 OpenCV 3.0時遇到問題。
步驟
如果你已經成功在你的環境中安裝了 OpenCV,我們就可以開始判斷烤箱開關的數據分析了。
加載需要的包
argparse —— 參數處理庫。numpy —— 高度優化的數值運算庫。OpenCV 在數組結構中使用 numpy。cv2 —— OpenCV 中圖像處理庫。
import argparseimport numpy as npimport cv2
載入圖片
image = cv2.imread(image_path)
圖片降噪
我們為了給圖片降噪,需要對輸入圖片進行平滑處理。這樣會更容易在圖片中定位目標。使用 medianBlur 函數,把光圈大小定為 3 。數字越大意味著圖像會越模糊。
blur_image = cv2.medianBlur(image, 3)
把圖片顏色轉為 HSV 格式
HSV —— 色度、飽和度和純度(亮度)。HSV 可以讓我們提取出一個彩色對象,因為它比 BGR 格式(譯者註:與我們常說的RBG色彩模型類似,三個字母分別代表紅藍綠三色)更容易表徵顏色。
把圖片轉為 HSV 格式可以讓我們通過色度(一個值而不是三個值),來確定圖片中的一個顏色。
以下是實現方式:
hsv_image = cv2.cvtColor(blur_image, cv2.COLOR_BGR2HSV)
執行結果如下圖:
檢測圖片中的顏色
為了檢測我們想要的顏色,我們可以查看烤箱燈圖片中顏色的直方圖。
我們可以看出,紅色在圖片中佔統治地位。紅色有兩個高峰 —— 一個幅度高,一個幅度低。這些顏色值轉變為色度範圍從 0 到10,以及從 160 到 180 (針對紅色)。
在 HSV 圖片中針對每一個色度範圍,我們可以創建一個遮罩,來去掉所有不在選定範圍的無關顏色。
def create_hue_mask(image, lower_color, upper_color):lower = np.array(lower_color, np.uint8) upper = np.array(upper_color, np.uint8) # Create a mask from the colors mask = cv2.inRange(image, lower, upper) output_image = cv2.bitwise_and(image, image, mask = mask) return output_image# Get lower red huelower_red_hue = create_hue_mask(hsv_image, [0, 100, 100], [10, 255, 255])# Get higher red huehigher_red_hue = create_hue_mask(hsv_image, [160, 100, 100], [179, 255,255])
結果如下:
接下來把這些圖片合併在一起,以抓取所有紅色色度。
full_image = cv2.addWeighted(lower_red_hue, 1.0, higher_red_hue, 1.0, 0.0)
結果如下:
發現圖片中的圓圈
現在我們的圖片上僅有紅色色度,接著我們需要判定紅燈是否開啟(即是否存在紅色色度的那個圓圈)。我們需要在新圖中發現圓圈,不過首先需要把圖片轉換成灰度圖(因為 HoughCircles 函數的輸入要求是灰度圖)。
檢測圖片中的圓圈需要以下參數(使用 OpenCV中 的 HoughCircles 函數):
灰度圖輸入。HOUGH_GRADIENT 是用來檢測圓圈的方法(目前僅有的一個方法)。累加器和圖片解析度的反比。在本例中,為1.2。待檢測圓圈圓心的最小距離,本例中為100。
#Convert image to grayscaleimage_gray = cv2.cvtColor(full_image, cv2.COLOR_BGR2GRAY)#Find circles in the imagecircles = cv2.HoughCircles(image_gray, cv2.HOUGH_GRADIENT, 1.2, 100)
結果
此時就可以檢查是否有圓圈了。如果有就意味著至少有一個烤箱燈亮著。如果找不到圓圈就意味著沒有燈亮,烤箱關著。
為了證明此結論,我們可以用下述代碼在原圖中畫圓圈:
# Draw the circles on the original imagecircles = np.round(circles[0, :]).astype("int")for (center_x, center_y, radius) in circles:cv2.circle(image, (center_x, center_y), radius, (0, 255, 0), 4)
結果如下:
下一步
接下來還有很多可以做的,比如:
檢測特定燈的開啟,用以了解烤箱的真實狀態。建立一個服務以便遠程檢查烤箱狀態。把該功能加入樹莓派(譯者註:基於Linux的迷你開發板),我們就擁有可以警告烤箱關閉與否的小型設備。
全部樣例代碼可以在 Github 中找到。
Github連結:https://github.com/kazuar/opencv_light_detection
End