忘關烤箱了?我用 Python 和 OpenCV 來幫忙!

jopen 8年前發布 | 22K 次閱讀 Python OpenCV Python開發

這篇文章應用計算機視覺和圖像處理技術,展示了檢測烤箱開關狀態的過程。在生活中,有時你會粗心大意忘關烤箱之類的廚房電器,這潛在很大的危險。因此作者采用 Python 和 OpenCV,通過家庭攝像頭獲取的圖像來自動識別烤箱是否開著,進而可以觸發警報。

“我忘關烤箱了嗎?”

這個問題常常會在最不方便的時候出現在你的腦子里。

有時是當你剛剛走出家門的時候。 有時是當你在上班路上的時候。 有時是當你坐在飛機上準備度個長假的時候……

解決這個問題的方法是多種多樣的:

  1. 橡皮筋的方法
  2. 大聲說或唱出來(就像  Samuel L. Jackson 一樣)
  3. 當你離開家去度假的時候,給烤箱在內的電器列個清單或做個標記。 或者,我們也許有更好的做法……

在本教程中,我們會嘗試利用技術手段解決這個問題。

Github 里有完整代碼。

問題定義

對我們而言,我們需要確定一個信號,用于判斷烤箱的開關狀態。在我的廚房里,這個信號就是頂部標記著“烤箱開”字樣的紅色燈。

當紅色燈亮的時候,烤箱是開著的:

當紅色燈滅的時候,烤箱是關著的:

預備條件

確保你的電腦上安裝了以下應用:

  1. OpenCV 3.0
  2. Python 2.7
  3. Numpy 1.9

安裝 OpenCV3.0 和 Python 2.7

如果你尚未安裝 OpenCV,請按照 Adrian Rosebrock 的完美教程,在 OSX 系統上安裝 OpenCV 3.0 和 Python 2.7+。我在安裝步驟里增加了一些自己的注釋,以防你在 OSX 上編譯 OpenCV 3.0時遇到問題。

步驟

如果你已經成功在你的環境中安裝了 OpenCV,我們就可以開始判斷烤箱開關的數據分析了。

加載需要的包

  1. argparse —— 參數處理庫。
  2. numpy —— 高度優化的數值運算庫。OpenCV 在數組結構中使用 numpy。
  3. cv2 —— OpenCV 中圖像處理庫。

Python

import argparse
import numpy as np
import cv2
import argparse
import numpyas np
import cv2

載入圖片

Python

image = cv2.imread(image_path)
image = cv2.imread(image_path)

圖片降噪

我們為了給圖片降噪,需要對輸入圖片進行平滑處理。這樣會更容易在圖片中定位目標。使用 medianBlur 函數,把光圈大小定為 3 。數字越大意味著圖像會越模糊。

Python

blur_image = cv2.medianBlur(image, 3)
blur_image = cv2.medianBlur(image, 3)

把圖片顏 色轉為 HSV 格式

HSV —— 色度、飽和度和純度(亮度)。HSV 可以讓我們提取出一個彩色對象,因為它比 BGR 格式(譯者注:與我們常說的RBG色彩模型類似,三個字母分別代表紅藍綠三色)更容易表征顏色。

把圖片轉為 HSV 格式可以讓我們通過色度(一個值而不是三個值),來確定圖片中的一個顏色。

以下是實現方式:

Python

hsv_image = cv2.cvtColor(blur_image, cv2.COLOR_BGR2HSV)
hsv_image = cv2.cvtColor(blur_image, cv2.COLOR_BGR2HSV)

執行結果如下圖:

檢測圖 片中的顏色

為了檢測我們想要的顏色,我們可以查看烤箱燈圖片中顏色的直方圖。

我們可以看出,紅色在圖片中占統治地位。紅色有兩個高峰 —— 一個幅度高,一個幅度低。這些顏色值轉變為色度范圍從 0 到10,以及從 160 到 180 (針對紅色)。

在 HSV 圖片中針對每一個色度范圍,我們可以創建一個遮罩,來去掉所有不在選定范圍的無關顏色。

Python

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 hue
lower_red_hue = create_hue_mask(hsv_image, [0, 100, 100], [10, 255, 255])

# Get higher red hue
higher_red_hue = create_hue_mask(hsv_image, [160, 100, 100], [179, 255, 255])
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 hue
lower_red_hue = create_hue_mask(hsv_image, [0, 100, 100], [10, 255, 255])
 
# Get higher red hue
higher_red_hue = create_hue_mask(hsv_image, [160, 100, 100], [179, 255, 255])

結果如下:

接下來把這些圖片合并在一起,以抓取所有紅色色度。

Python

full_image = cv2.addWeighted(lower_red_hue, 1.0, higher_red_hue, 1.0, 0.0)
full_image = cv2.addWeighted(lower_red_hue, 1.0, higher_red_hue, 1.0, 0.0)

結果如下:

發現圖片中的圓圈

現在我們的圖片上僅有紅色色度,接著我們需要判定紅燈是否開啟(即是否存在紅色色度的那個圓圈)。我們需要在新圖中發現圓圈,不過首先需要把圖片轉換成灰度圖(因為 HoughCircles 函數的輸入要求是灰度圖)。

檢測圖片中的圓圈需要以下參數(使用 OpenCV中 的 HoughCircles 函數):

  1. 灰度圖輸入。
  2. HOUGH_GRADIENT 是用來檢測圓圈的方法(目前僅有的一個方法)。
  3. 累加器和圖片分辨率的反比。在本例中,為1.2。
  4. 待檢測圓圈圓心的最小距離,本例中為100。

    Python

    #Convert image to grayscale
    image_gray = cv2.cvtColor(full_image, cv2.COLOR_BGR2GRAY)
    #Find circles in the image
    
    circles = cv2.HoughCircles(image_gray, cv2.HOUGH_GRADIENT, 1.2, 100)
    #Convert image to grayscale
    image_gray = cv2.cvtColor(full_image, cv2.COLOR_BGR2GRAY)
    #Find circles in the image
     
    circles = cv2.HoughCircles(image_gray, cv2.HOUGH_GRADIENT, 1.2, 100)

結果

此時就可以檢查是否有圓圈了。如果有就意味著至少有一個烤箱燈亮著。如果找不到圓圈就意味著沒有燈亮,烤箱關著。

為了證明此結論,我們可以用下述代碼在原圖中畫圓圈:

Python

# Draw the circles on the original image
circles = 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)
# Draw the circles on the original image
circles = 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)

結果如下:

下一步

接下來還有很多可以做的,比如:

  1. 檢測特定燈的開啟,用以了解烤箱的真實狀態。
  2. 建立一個服務以便遠程檢查烤箱狀態。
  3. 把該功能加入樹莓派(譯者注:基于Linux的迷你開發板),我們就擁有可以警告烤箱關閉與否的小型設備。

全部樣例代碼可以在 Github 中找到。 寫于2015年,8月2日

來自: http://python.jobbole.com/84127/

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!