2

I have a simple python code using OpenCV and Keras that performs some detections on frames (follow-up from my previous question here). But when I want to record and save the frames as a video using video_writer, the generated video is empty.

What is wrong in the video_writer?

#........some code    
# start the webcam feed
cap = cv2.VideoCapture(1)

canvasImageOriginal = cv2.imread("fg2.png")
canvasImage = cv2.imread("fg2.png")
canvasHappy = cv2.imread("fg2happy.png")
canvasSad = cv2.imread("fg2sad.png")
x0, x1 = 330, 1290
y0, y1 = 155, 700

#=========
w=960#int(cap.get(cv2.CV_CAP_PROP_FRAME_WIDTH ))
h=540#int(cap.get(cv2.CV_CAP_PROP_FRAME_HEIGHT ))
# video recorder
fourcc = cv2.VideoWriter_fourcc(*'XVID')
video_writer = cv2.VideoWriter('output.avi', fourcc, 25.0, (w, h))
#=========


prediction_history = []
LOOKBACK = 5 # how far you want to look back

counter = 0
while True:
    # Find haar cascade to draw bounding box around face
    ret, frame = cap.read()
    frame=cv2.flip(frame,3)
    if not ret:
        break
    facecasc = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    faces = facecasc.detectMultiScale(gray,scaleFactor=1.3, minNeighbors=5)

    for (x, y, w, h) in faces:
        cv2.rectangle(frame, (x, y-50), (x+w, y+h+10), (255, 0, 0), 2)
        roi_gray = gray[y:y + h, x:x + w]
        cropped_img = np.expand_dims(np.expand_dims(cv2.resize(roi_gray, (48, 48)), -1), 0)
        prediction = model.predict(cropped_img)
        
        maxindex = int(np.argmax(prediction))
        text = emotion_dict[maxindex]
        print(prediction[0][3])
        
        prediction_history.append(maxindex)
        most_common_index = max(set(prediction_history[-LOOKBACK:][::-1]), key = prediction_history.count)
        text = emotion_dict[most_common_index]
        
        #if ("Sad" in text) or ("Angry" in text) or ("Disgusted" in text):
        #    text = "Sad"
        if ("Happy" in text) or ("Sad" in text) :
            cv2.putText(frame, text, (x+20, y-60), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2, cv2.LINE_AA)
            if ("Happy" in text):
                counter= counter+1
                if counter == 10:
                    #print("Happy!")
                    
                    canvasImage = canvasHappy
        else:
            counter = 0
            canvasImage = canvasImageOriginal
            
                
            
            

    dim = (800,480)
    frame_shrunk = cv2.resize(frame, (x1 - x0, y1 - y0))
    canvasImage[y0:y1, x0:x1] = frame_shrunk
    #cv2.imshow('Video', cv2.resize(frame,dim,interpolation = cv2.INTER_CUBIC))
    cv2.imshow('Demo', canvasImage)
    video_writer.write(frame)
    
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
video_writer.release()
cv2.destroyAllWindows()
4
  • 2
    check frame.shape. make sure to pass the isColor parameter to VideoWriter and that it matches frame (gray? color?) Commented Oct 12, 2021 at 21:24
  • 1
    Yes that fixed the problem. So the dims must match? I thought it will automatically resize the frame to what writer wants.
    – angel_30
    Commented Oct 13, 2021 at 4:02
  • 1
    no, it will not do anything automatically. the dimensions must match. this is one of the common pitfalls. I'll check the docs and add some notes if they don't warn about this already. Commented Oct 13, 2021 at 11:30
  • OK. Feel free to share your prior answer for best answer credit.
    – angel_30
    Commented Oct 13, 2021 at 16:22

1 Answer 1

1

As it is mentioned above, please check print(frame.shape).

When I did it, I saw (300,450,3), and I changed the resolution of videowriter as (450,300) and it worked for me. As a result, I can say that frame.shape=(y, x, maybe color) but the resolution of videowriter=(x,y).

Not the answer you're looking for? Browse other questions tagged or ask your own question.