I was trying to make faster my frames in opencv, it was so slow using it normal, so I decided to ask it here Make faster videocapture opencv the answer was to use multi threading to make it faster, so I code it like this
# The same genderrecognition.py code but with multi-threading to make it faster and fix the the lag of the other one
from tensorflow.keras.preprocessing.image import img_to_array
from tensorflow.keras.models import load_model
import numpy as np
import cv2
import os
import cvlib as cv
# open webcam and initiate the cam
webcam = cv2.VideoCapture(0, cv2.CAP_DSHOW)
# opencv class
class VideoStream:
def __init__(self):
# read frame from webcam
self.status, self.frame = webcam.read()
webcam.set(cv2.CAP_PROP_FPS, 1000)
self.frame = cv2.flip(self.frame, 1)
print("videostream working")
# face detection class
class face_detection:
def __init__(self):
# use VideoStream Class variables
self.videostream = VideoStream()
self.frame = self.videostream.frame
# apply face detection
self.face, self.confidence = cv.detect_face(self.frame)
# loop through detected faces
for self.idx, self.f in enumerate(self.face):
# get the corner point of the rectangle
self.startX, self.startY = self.f[0], self.f[1]
self.endX, self.endY = self.f[2], self.f[3]
cv2.rectangle(self.frame, (self.startX, self.startY), (self.endX, self.endY), (0,255,0), 2)
self.face_crop = np.copy(self.frame[self.startY:self.endY, self.startX:self.endX])
if self.face_crop.shape[0] < 10 or self.face_crop.shape[1] < 10:
continue
# preprocessing for gender detection model
self.face_crop = cv2.resize(self.face_crop, (96,96))
self.face_crop = self.face_crop.astype("float") / 255.0
self.face_crop = img_to_array(self.face_crop)
self.face_crop = np.expand_dims(self.face_crop, axis=0)
GFR()
print("face_detection working")
# gender recognition class
class GFR:
def __init__(self):
self.model = load_model("C:/Users/berna/Desktop/Programming/AI_ML_DL/Projects/FaceGenderRecognition/gender_detection.model")
self.facedetection = face_detection()
self.face_crop = self.facedetection.face_crop
self.classes = ['hombre', 'mujer']
self.startX, self.startY = self.facedetection.startX, self.facedetection.startY
self.endX, self.endY = self.facedetection.endX, self.facedetection.endY
self.frame = self.facedetection.frame
# apply the gender detection face with the model
self.conf = model.predict(self.face_crop)[0]
# get label with max acc
self.idx = np.argmax(self.conf)
self.label = self.classes[self.idx]
self.label = "{}: {:.2f}".format(self.label, self.conf[self.idx] * 100)
self.Y = self.startY - 10 if self.startY - 10 > 10 else self.startY + 10
# write label and confidence above the face rectangle
cv2.putText(self.frame, self.label, (self.startX, self.Y), cv2.FONT_HERSHEY_SIMPLEX,
0.7, (0,255,0), 2)
print("gender recognition working!")
# classes and webcam while loop
gender_detection = GFR()
# loop through frames
while webcam.isOpened():
VideoStream()
face_detection()
# display output
cv2.imshow("Gender Detection", gender_detection.frame)
# press "Q" to stop
if cv2.waitKey(1) & 0xFF == ord('q'):
break
webcam.release()
cv2.destroyAllWindows()
it give me no errors, but compared to my other code that is on the other question, the webcam open and on this one no, any idea?
Advertisement
Answer
Your VideoStream class’s init looks ok, but I think you might have better luck creating a cv2 VideoCapture object in the init as well:
self.stream = cv2.VideoCapture(0)
I’m not really as familiar with webcam.set() but if you want to incorporate that, I’m sure you can.
Here you have grabbed the initial frames:
self.status, self.frame = webcam.read()
(Or using the new self.stream variable):
self.status, self.frame = self.stream.read()
Yet this will only grab a frame when it’s initialized, not in a loop. To achieve a loop, you have to make a few more class methods. One will be for continuously getting frames (I added a self.stopped attribute, although it’s not in your code. It might be a good idea to have a True/False stop flag):
def read_stream(self):
while not self.stopped:
(self.grabbed, self.frame) = self.stream.read()
Then if you want to use multithreading, you can make a thread pointing to the read_stream method:
def start(self):
Thread(target=self.read_stream, args=()).start()
return self
You will have to call the start() method on the VideoStream before you start your CV2 imshow() loop.
video_stream = VideoStream().start(). #<------Here--------
while webcam.isOpened():
face_detection()
# display output
cv2.imshow("Gender Detection", gender_detection.frame)
# press "Q" to stop
if cv2.waitKey(1) & 0xFF == ord('q'):
break
Hopefully this helps getting the CV2 display to show. Whether your GFR class or face detection is grabbing the right frames from the VideoStream class… that’s something else, and I can’t debug all that code.