opencv-python計算兩張圖像的差異,探測物體的運動

背景

假設要實現人的面部或手部的運動檢測。

方法:先對攝像頭輸入的圖像進行處理,只保留符合人體膚色的像素,再計算視頻中此幀和上一幀圖像數據的差異。差異超過一定閾值即認爲畫面中的人體產生了運動。

代碼

from cv2 import cv2
import matplotlib.pyplot as plt

def cvt(img):  # 膚色提取
    YCrCb = cv2.cvtColor(img, cv2.COLOR_BGR2YCR_CB)  # 轉換至YCrCb空間
    # 人體膚色在YCrCb空間的粗略映射
    skin = cv2.inRange(YCrCb, np.array([0, 133, 77]), np.array([255, 173, 127]))
    res = cv2.bitwise_and(YCrCb, YCrCb, mask=skin)
    return res

cap = cv2.VideoCapture(0)
cap.set(3, 640)
cap.set(4, 480)
firstlaunch = True # 首次運行的標誌
prev_frame = None # 用於保存上一幀圖像
plt.ion() # 交互模式,使繪製的直方圖可以不斷變化

while True:
    ret, frame_read = cap.read()
    frame_read = cv2.flip(frame_read, 1)
    frame_read = cv2.medianBlur(frame_read, 5)
    frame_read = cv2.GaussianBlur(frame_read, (5, 5), 0)
    # 提取膚色,然後再轉化爲灰度圖
    present_frame = cvt(frame_read)
    present_frame = cv2.cvtColor(present_frame, cv2.COLOR_YCrCb2BGR)
    present_frame = cv2.cvtColor(present_frame, cv2.COLOR_BGR2GRAY)
    if not firstlaunch:
        sub = cv2.subtract(present_frame, prev_frame)
        hist = cv2.calcHist([sub], [0], None, [256], [0, 255])
        # 只統計灰度值6-100的部分,這只是隨意取的
        # 可以自己實驗調整找到適合的範圍
        diff = np.sum(hist[6:100]) # 統計產生變化的像素點個數
        print(diff)
        plt.plot(hist[6:100], color='red') # 繪製直方圖
        plt.ylim([0, 6000])
        plt.show()
        cv2.imshow('preview', sub)
    else:
        firstlaunch = False # 首次運行的標誌
    cv2.waitKey(10)
    if not firstlaunch:
        plt.clf() # 清除直方圖圖像
    prev_frame = present_frame.copy() # 存儲此幀

plt.close('all')
cap.release()

效果

當人頭部基本保持靜止時,統計數值基本不超過10000

頭部靜止時的直方圖,此時統計值爲3710

頭部靜止時的直方圖

當人的頭部或手部產生運動時,統計數值上升爲一萬至數萬。

頭部運動時的直方圖,此時統計值爲18591

頭部運動時的直方圖

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章