(Opencv)在HSV顏色空間下做目標檢測以及目標跟蹤

2020-09-20 11:00:46

原視訊:https://www.youtube.com/watch?v=3D7O_kZi8-o

我們有一張包含有不同種顏色球的圖片,使用HSV顏色空間對某一種顏色的球做檢測

大體框架

import cv2
import numpy as np

def nothing(x):
    pass
while True:
	# 讀取的為BGR顏色空間
    frame = cv2.imread('smarties.png')
    cv2.imshow("frame", frame)
    # 等待1ms 檢測ESC按鍵
    key = cv2.waitKey(1)
    if key == 27:
        break

cv2.destroyAllWindows()

將圖片顏色空間從BGR轉換為HSV

hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

以藍色為例,根據經驗設定顏色範圍的的大小閾值

l_b = np.array([110,50,50])
u_b = np.array([130,255,255])

讓圖片不在範圍內的畫素顏色值變為0,範圍之內的變為255,製作遮罩

mask = cv2.inRange(hsv, l_b, u_b)

對白色範圍進行保留

res = cv2.bitwise_and(frame, frame, mask=mask)

顯示圖片

cv2.imshow("frame", frame)
cv2.imshow("mask", mask)
cv2.imshow("res", res)

完整程式碼

import cv2
import numpy as np
def nothing(x):
    pass
while True:
    # 讀取的為BGR顏色空間
    frame = cv2.imread('smarties.png')
    # 將圖片顏色空間從BGR轉換為HSV
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
    l_b = np.array([110,50,50])
    u_b = np.array([130,255,255])
    mask = cv2.inRange(hsv, l_b, u_b)
    res = cv2.bitwise_and(frame, frame, mask=mask)
    cv2.imshow("frame", frame)
    cv2.imshow("mask", mask)
    cv2.imshow("res", res)
    key = cv2.waitKey(1)
    if key == 27:
        break
cv2.destroyAllWindows()

效果

下面我們通過滑動條來改變閾值,達到識別不同顏色的效果

cv2.namedWindow("Tracking")
cv2.createTrackbar("LH", "Tracking", 0, 255, nothing)
cv2.createTrackbar("LS", "Tracking", 0, 255, nothing)
cv2.createTrackbar("LV", "Tracking", 0, 255, nothing)
cv2.createTrackbar("UH", "Tracking", 255, 255, nothing)
cv2.createTrackbar("US", "Tracking", 255, 255, nothing)
cv2.createTrackbar("UV", "Tracking", 255, 255, nothing)
while True:
    l_h = cv2.getTrackbarPos("LH", "Tracking")
    l_s = cv2.getTrackbarPos("LS", "Tracking")
    l_v = cv2.getTrackbarPos("LV", "Tracking")
    u_h = cv2.getTrackbarPos("UH", "Tracking")
    u_s = cv2.getTrackbarPos("US", "Tracking")
    u_v = cv2.getTrackbarPos("UV", "Tracking")
    l_b = np.array([l_h, l_s, l_v])
    u_b = np.array([u_h, u_s, u_v])

完整程式碼

import cv2
import numpy as np
def nothing(x):
    pass
cv2.namedWindow("Tracking")
cv2.createTrackbar("LH", "Tracking", 0, 255, nothing)
cv2.createTrackbar("LS", "Tracking", 0, 255, nothing)
cv2.createTrackbar("LV", "Tracking", 0, 255, nothing)
cv2.createTrackbar("UH", "Tracking", 255, 255, nothing)
cv2.createTrackbar("US", "Tracking", 255, 255, nothing)
cv2.createTrackbar("UV", "Tracking", 255, 255, nothing)
while True:
    # 讀取的為BGR顏色空間
    frame = cv2.imread('smarties.png')
    # 將圖片顏色空間從BGR轉換為HSV
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
    l_h = cv2.getTrackbarPos("LH", "Tracking")
    l_s = cv2.getTrackbarPos("LS", "Tracking")
    l_v = cv2.getTrackbarPos("LV", "Tracking")
    u_h = cv2.getTrackbarPos("UH", "Tracking")
    u_s = cv2.getTrackbarPos("US", "Tracking")
    u_v = cv2.getTrackbarPos("UV", "Tracking")
    l_b = np.array([l_h, l_s, l_v])
    u_b = np.array([u_h, u_s, u_v])
    mask = cv2.inRange(hsv, l_b, u_b)
    res = cv2.bitwise_and(frame, frame, mask=mask)
    cv2.imshow("frame", frame)
    cv2.imshow("mask", mask)
    cv2.imshow("res", res)
    key = cv2.waitKey(1)
    if key == 27:
        break
cv2.destroyAllWindows()

效果

進階:使用下面的程式碼可以使用攝像頭實時監測

import cv2
import numpy as np
def nothing(x):
    pass
cap = cv2.VideoCapture(1)
cv2.namedWindow("Tracking")
cv2.createTrackbar("LH", "Tracking", 0, 255, nothing)
cv2.createTrackbar("LS", "Tracking", 0, 255, nothing)
cv2.createTrackbar("LV", "Tracking", 0, 255, nothing)
cv2.createTrackbar("UH", "Tracking", 255, 255, nothing)
cv2.createTrackbar("US", "Tracking", 255, 255, nothing)
cv2.createTrackbar("UV", "Tracking", 255, 255, nothing)
while True:
    _,frame=cap.read()
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
    l_h = cv2.getTrackbarPos("LH", "Tracking")
    l_s = cv2.getTrackbarPos("LS", "Tracking")
    l_v = cv2.getTrackbarPos("LV", "Tracking")
    u_h = cv2.getTrackbarPos("UH", "Tracking")
    u_s = cv2.getTrackbarPos("US", "Tracking")
    u_v = cv2.getTrackbarPos("UV", "Tracking")
    l_b = np.array([l_h, l_s, l_v])
    u_b = np.array([u_h, u_s, u_v])
    mask = cv2.inRange(hsv, l_b, u_b)
    res = cv2.bitwise_and(frame, frame, mask=mask)
    cv2.imshow("frame", frame)
    cv2.imshow("mask", mask)
    cv2.imshow("res", res)
    key = cv2.waitKey(1)
    if key == 27:
        break
cap.release()
cv2.destroyAllWindows()

簡單應用:拿著物體運動,並給物體帶上面具

import cv2
import numpy as np
from numba import jit
def nothing(x):
    pass
cap = cv2.VideoCapture(1)
cv2.namedWindow("Tracking")
cv2.createTrackbar("LH", "Tracking", 0, 255, nothing)
cv2.createTrackbar("LS", "Tracking", 0, 255, nothing)
cv2.createTrackbar("LV", "Tracking", 0, 255, nothing)
cv2.createTrackbar("UH", "Tracking", 255, 255, nothing)
cv2.createTrackbar("US", "Tracking", 255, 255, nothing)
cv2.createTrackbar("UV", "Tracking", 255, 255, nothing)
img_mask=cv2.imread('mask.png')
apply=False
draw=True
@jit
def covert(res,img_mask):
    pos=[0,0]
    height=res.shape[0]
    width=res.shape[1]
    h=img_mask.shape[0]
    w=img_mask.shape[1]
    for i in range(height):
        for j in range(width):
            if res[i, j].all() > 0:
                pos = [i, j]
            res[i, j] = 255
    if pos[0]!=0 and pos[1]!=0:
        for i in range(h):
            for j in range(w):
                if pos[0] - int(h / 2) + i < height and pos[1] - int(w / 2) + j < width:
                    res[pos[0] - int(h / 2) + i, pos[1] - int(w / 2) + j] = img_mask[i, j]
while True:
    # 讀取的為BGR顏色空間
    #frame = cv2.imread('smarties.png')
    _,frame=cap.read()
    # 將圖片顏色空間從BGR轉換為HSV
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
    l_h = cv2.getTrackbarPos("LH", "Tracking")
    l_s = cv2.getTrackbarPos("LS", "Tracking")
    l_v = cv2.getTrackbarPos("LV", "Tracking")
    u_h = cv2.getTrackbarPos("UH", "Tracking")
    u_s = cv2.getTrackbarPos("US", "Tracking")
    u_v = cv2.getTrackbarPos("UV", "Tracking")
    l_b = np.array([l_h, l_s, l_v])
    u_b = np.array([u_h, u_s, u_v])
    mask = cv2.inRange(hsv, l_b, u_b)
    res = cv2.bitwise_and(frame, frame, mask=mask)
    if apply:
        covert(res,img_mask)
    cv2.imshow("frame", frame)
    cv2.imshow("mask", mask)
    cv2.imshow("res", res)
    key = cv2.waitKey(1)
    if key == 27:
        break
    if key== 32:
        apply=not apply
cap.release()
cv2.destroyAllWindows()

效果