网络摄像头上的水印叠加非常慢

Watermark overlay on webcam is terribly slow

我的 png 图像覆盖网络摄像头的代码。 我希望只有当人脸进入人脸覆盖区域时才能检测到人脸。 这将限制从更远的距离检测到不必要的误报面孔。 只有当人脸进入这个区域时,才会检测到人脸,否则不检测人脸。 (面部检测仍有待整合)

import numpy as np
import cv2,os

def image_resize(image, width = None, height = None, inter = cv2.INTER_AREA):
     dim = None
    (h, w) = image.shape[:2]
    if width is None and height is None:
        return image
    if width is None:
        r = height / float(h)
        dim = (int(w * r), height)
    else:
        r = width / float(w)
        dim = (width, int(h * r))
    resized = cv2.resize(image, dim, interpolation = inter)
    return resized


cap = cv2.VideoCapture(0)

img_path = 'face.png'
logo = cv2.imread(img_path, -1)
watermark = image_resize(logo, height=500)
watermark = cv2.cvtColor(watermark, cv2.COLOR_BGR2BGRA)

while(True):
    # Capture frame-by-frame
    ret, frame = cap.read()
    frame = cv2.cvtColor(frame, cv2.COLOR_BGR2BGRA)
    frame_h, frame_w, frame_c = frame.shape
    overlay = np.zeros((frame_h, frame_w, 4), dtype='uint8')
  
    watermark_h, watermark_w, watermark_c = watermark.shape
    offset = 10
    h_offset = frame_h - watermark_h - offset
    w_offset = frame_w - watermark_w - offset

    for i in range(0, watermark_h):
        for j in range(0, watermark_w):
            overlay[h_offset + i, w_offset+ j] = watermark[i,j]

    cv2.addWeighted(overlay, 0.75, frame, 1.0, 0, frame)

    frame = cv2.cvtColor(frame, cv2.COLOR_BGRA2BGR)
    # Display the resulting frame
    cv2.imshow('frame',frame)
    if cv2.waitKey(20) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

这段代码的问题是它非常慢。如何加快速度?

您不必在 while 循环中一次又一次地创建 overlay
您只能创建一次 - 在 while 循环之前。然后代码运行速度很快。

import os
import numpy as np
import cv2

def image_resize(image, width = None, height = None, inter = cv2.INTER_AREA):
    dim = None
    (h, w) = image.shape[:2]
    if width is None and height is None:
        return image
    if width is None:
        r = height / float(h)
        dim = (int(w * r), height)
    else:
        r = width / float(w)
        dim = (width, int(h * r))
    resized = cv2.resize(image, dim, interpolation = inter)
    return resized

# --- main ---

cap = cv2.VideoCapture(0)

img_path = 'face.png'

logo = cv2.imread(img_path, -1)

watermark = image_resize(logo, height=500)
watermark = cv2.cvtColor(watermark, cv2.COLOR_BGR2BGRA)
watermark_h, watermark_w, watermark_c = watermark.shape

# read first frame to get shape

ret, frame = cap.read()
frame_h, frame_w, frame_c = frame.shape
print(frame_h, frame_w)

overlay = np.zeros((frame_h, frame_w, 4), dtype='uint8')

offset = 10
h_offset = frame_h - watermark_h - offset
w_offset = frame_w - watermark_w - offset

for i in range(0, watermark_h):
    for j in range(0, watermark_w):
        overlay[h_offset + i, w_offset+ j] = watermark[i,j]

while True:
    # Capture frame-by-frame
    ret, frame = cap.read()
    
    frame = cv2.cvtColor(frame, cv2.COLOR_BGR2BGRA)    
 
    cv2.addWeighted(overlay, 0.75, frame, 1.0, 0, frame)

    frame = cv2.cvtColor(frame, cv2.COLOR_BGRA2BGR)

    # Display the resulting frame
    cv2.imshow('frame',frame)

    if cv2.waitKey(20) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

顺便说一句:

它运行如此缓慢也是因为您使用了 for 循环来分别移动每个像素。如果您使用 numpy 函数来复制它,那么它可以工作得更快。

overlay[h_offset:h_offset+watermark_h, w_offset:w_offset+watermark_w] = watermark[h_start:h_start+watermark_h, w_start:w_start+watermark_w]

因为我的相机 (640x480) h_offset-30 所以需要重新计算。

import os
import numpy as np
import cv2

def image_resize(image, width = None, height = None, inter = cv2.INTER_AREA):
    dim = None
    (h, w) = image.shape[:2]
    if width is None and height is None:
        return image
    if width is None:
        r = height / float(h)
        dim = (int(w * r), height)
    else:
        r = width / float(w)
        dim = (width, int(h * r))
    resized = cv2.resize(image, dim, interpolation = inter)
    return resized

# --- main ---

cap = cv2.VideoCapture(0)

img_path = 'face.png'

logo = cv2.imread(img_path, -1)

watermark = image_resize(logo, height=500)
watermark = cv2.cvtColor(watermark, cv2.COLOR_BGR2BGRA)
watermark_h, watermark_w, watermark_c = watermark.shape
print(watermark_h, watermark_w, watermark_c)

while True:

    # Capture frame-by-frame
    ret, frame = cap.read()
    
    frame = cv2.cvtColor(frame, cv2.COLOR_BGR2BGRA)    
    frame_h, frame_w, frame_c = frame.shape
    print(frame_h, frame_w)

    overlay = np.zeros((frame_h, frame_w, 4), dtype='uint8')

    offset = 10
    h_start = 0
    w_start = 0
    h_offset = frame_h - watermark_h - offset
    w_offset = frame_w - watermark_w - offset

    print('before:', h_offset, h_offset+watermark_h, w_offset, w_offset+watermark_w)

    print('h_offset:', h_offset)
    if h_offset < 0:
        h_start = -h_offset
        watermark_h -= h_start
        h_offset = 0 

    print('after:', h_offset, h_offset+watermark_h, w_offset, w_offset+watermark_w)

    overlay[h_offset:h_offset+watermark_h, w_offset:w_offset+watermark_w] = watermark[h_start:h_start+watermark_h, w_start:w_start+watermark_w]
 
    cv2.addWeighted(overlay, 0.75, frame, 1.0, 0, frame)

    frame = cv2.cvtColor(frame, cv2.COLOR_BGRA2BGR)
    
    # Display the resulting frame
    cv2.imshow('frame',frame)
    
    if cv2.waitKey(20) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()