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.