3

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()
Jeru Luke
  • 20,118
  • 13
  • 80
  • 87
Tina J
  • 4,983
  • 13
  • 59
  • 125
  • 2
    check `frame.shape`. make sure to pass the `isColor` parameter to VideoWriter and that it matches `frame` (gray? color?) – Christoph Rackwitz Oct 12 '21 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. – Tina J Oct 13 '21 at 04: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. – Christoph Rackwitz Oct 13 '21 at 11:30
  • OK. Feel free to share your prior answer for best answer credit. – Tina J Oct 13 '21 at 16:22

1 Answers1

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).