Reputation: 89
My code for png image overlay over webcam. I want the faces to be detected only when they come inside an face overlay region. This will restrict unnecessary false positive faces to be detected from longer distances. Only if a persons face comes inside this region, will the face be detected, else no face detection. (FACE DETECTION STILL TO BE INCORPORATED)
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()
The problem with this code is that its terribly slow. How to speed this up ?
Upvotes: 0
Views: 325
Reputation: 143001
You don't have to create overlay
again and again inside while
-loop.
You can create it only once - before while
-loop. And then code works fast.
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()
BTW:
It was working so slow also because you was using for
-loops to move every pixel separatelly. If you would use numpy
functions to copy it then it could work much faster.
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]
Because for my camera (640x480) h_offset
is -30
so it needed some recalculations.
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()
Upvotes: 3