Python 60行代碼使用 OpenCV 識別雪深

前兩天跟一個朋友吃飯,聊到他在作的圖像識別測量雪深,對此深感興趣,找時間就把 OpenCV 瞭解一下。python

識別標杆上紅色刻度的數量。spa

研究了一下午,話很少說,直接開始演示吧。code

import cv2
# 讀取圖片
img = cv2.imread("./snow.jpeg")

首先,將紅色部分提取,則須要將原圖進行顏色空間轉換,轉換類型使用 BGR2HSV 方法。圖片

HSV 是一種將RGB色彩模型中的點在圓柱座標系中的表示法。H 爲色相,是色彩的基本屬性,S 爲飽和度,V 爲明度。

從網上查了下,紅色區域的 H 值在 [0,10] 和 [170,180],使用 inRange 方法將紅色範圍內外的顏色區分開ip

hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
mask1 = cv2.inRange(hsv_img, np.array([0, 70, 50]), np.array([10, 255, 255]))
mask2 = cv2.inRange(hsv_img, np.array([170, 70, 50]), np.array([180, 255, 255]))
mask = mask1 | mask2

mask 顯示效果以下路由

圖片描述

此時,圖像上除了刻度外,還有些地方呈現白色,須要將這些雜質過濾掉,同時也要將垂直部分的白色去掉,須要通過先膨脹再腐蝕再膨脹三個過程。爲何要這樣呢?由於這樣才能過濾掉雜質以及垂直方向的紅線部分,以至達到效果,具體看下面的代碼和圖。get

dilated = cv2.dilate(mask, cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)), iterations=2)
# 建立一個水平的結構元素,進行腐蝕和膨脹
hline = cv2.getStructuringElement(cv2.MORPH_RECT, (int(dilated.shape[1] / 32), 1), (-1, -1))
# 腐蝕掉多餘的白色部分
temp = cv2.erode(dilated, hline)
# 使白色部分膨脹
dst_img = cv2.dilate(temp, hline)

效果以下:博客

圖片描述
獲得提取後的部分,發現還有一個問題,左右刻度有些連結在了一塊兒,此時須要分割。分割的方式是先計算一下寬度,得出中點寬度值,在此原圖對應的中點寬度畫一條黑線(不過效率有點低啊😊it

def get_mid_width(mask):
    """
    獲取白色輪廓區域的中間寬度
    """
    min_width = mask.shape[1]
    max_width = 0
    for line in mask:
        """
        處理圖片爲白色輪廓區域,計算輪廓區域寬度的中間值
        """
        indexes = list(filter(lambda i: line[i] != 0, range(len(line))))
        if len(indexes) != 0:
            if min_width > indexes[0]:
                min_width = indexes[0]
            if max_width < indexes[-1]:
                max_width = indexes[-1]
        else:
            continue
    mid_width = int((min_width + max_width) / 2)
    return mid_width

mid_width = get_mid_width(dst_img)
# 在圖片上畫一條黑線,用來分割左右紅線區域,避免膨脹的時候連在一塊兒
cv2.line(img, (mid_width, 0), (mid_width, img.shape[0]), (0, 0, 0), 20)

獲得以下圖:io

圖片描述
而後重複上面的提取紅色部分並過濾的步驟,獲得以下圖:

圖片描述
此時已經完成90%了,剩下的就是獲取每一個輪廓,以及把輪廓在原圖上描繪出來

contours, _ = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 獲取輪廓
# 畫上全部輪廓
cv2.drawContours(img_source, contours, -1, (0, 0, 0), 3)
imS = cv2.resize(img_source, (540, 960))
cv2.imshow('result', imS)
cv2.waitKey(0)
cv2.destroyAllWindows()

最終效果

圖片描述

是否是很簡單呢?!整理完才60行代碼,不過這只是簡單的實現,一旦涉及到有比較大的雜質或者標杆傾斜以及其餘狀況,都會影響識別率。

個人博客:時空路由器
原文地址:Python 60行代碼使用 OpenCV 識別雪深

相關文章
相關標籤/搜索