kitchen800
kitchen800

Reputation: 227

pythons opencv running out of frames when using webcam

I am trying to set my opencv to make a heat map. I have it working for a set .mp4 file. However when i try to make it work using my webcam on a live feed it doesn't seem to like it. the problem it has is it says that the "index is out of range" fr the following lines of code:

make_video('./frames/', './output.avi')
frame = cv2.imread(os.path.join(image_folder, images[0]))

The .py file is as follows:

import numpy as np
import cv2
import copy
from make_video import make_video
from progress.bar import Bar



def main():
    capture = cv2.VideoCapture(0)
    background_subtractor = cv2.bgsegm.createBackgroundSubtractorMOG()
    length = int(capture.get(cv2.CAP_PROP_FRAME_COUNT))

    bar = Bar('Processing Frames', max=length)

    print(length)
    short = length
    first_iteration_indicator = 1
    for i in range(0, short):

        print(i)

        ret, frame = capture.read()

        # If first frame
        if first_iteration_indicator == 1:

            first_frame = copy.deepcopy(frame)
            height, width = frame.shape[:2]
            accum_image = np.zeros((height, width), np.uint8)
            first_iteration_indicator = 0
        else:

            filter = background_subtractor.apply(frame)  # remove the background
            cv2.imwrite('./frame.jpg', frame)
            cv2.imwrite('./diff-bkgnd-frame.jpg', filter)

            threshold = 2
            maxValue = 2
            ret, th1 = cv2.threshold(filter, threshold, maxValue, cv2.THRESH_BINARY)

            # add to the accumulated image
            accum_image = cv2.add(accum_image, th1)
            cv2.imwrite('./mask.jpg', accum_image)

            color_image_video = cv2.applyColorMap(accum_image, cv2.COLORMAP_HOT)

            video_frame = cv2.addWeighted(frame, 0.7, color_image_video, 0.7, 0)

            name = "./frames/frame%d.jpg" % i
            cv2.imwrite(name, video_frame)

            if cv2.waitKey(1) & 0xFF == ord('q'):
                break
        bar.next()

    bar.finish()

    make_video('./frames/', './output.avi')

    color_image = cv2.applyColorMap(accum_image, cv2.COLORMAP_HOT)
    result_overlay = cv2.addWeighted(first_frame, 0.7, color_image, 0.7, 0)

    # save the final heatmap
    cv2.imwrite('diff-overlay.jpg', result_overlay)

    # cleanup
    capture.release()
    cv2.destroyAllWindows()

if __name__ == '__main__':
    main()

in order to set it to the webcam i use capture = cv2.VideoCapture(0) which causes the error above, however if i use a pre-saved .mp4 file like so capture = cv2.VideoCapture('vid.mp4') it works fine.Any ideas?

Upvotes: 0

Views: 105

Answers (1)

Jeru Luke
Jeru Luke

Reputation: 21233

Problem:

When using your webcam with capture = cv2.VideoCapture(0); the line length = int(capture.get(cv2.CAP_PROP_FRAME_COUNT)) is not helpful. Because, when using a webcam capture.get(cv2.CAP_PROP_FRAME_COUNT) returns -1.0. And that means to say the number of frames does not apply when using webcam. It makes sense when using to read video, since it can find out the number of frames present in the video.

Solution:

I modified the existing code to use the webcam and removed the for loop. I tested this code without make_video. The results were as expected on analyzing them using cv2.imshow (uncomment them to see it for yourself).

import cv2

capture = cv2.VideoCapture(0)

background_subtractor = cv2.bgsegm.createBackgroundSubtractorMOG()

threshold = 100
maxValue = 255

# for counting frames
i = 0
while True:
    i = i + 1
    ret, frame = capture.read()

    if frame is None:
        break
    
    fgMask = background_subtractor.apply(frame)
    ret, th1 = cv2.threshold(fgMask, threshold, maxValue, cv2.THRESH_BINARY)
    blur = cv2.GaussianBlur(th1,(11,11), 9)
    heat_map = cv2.applyColorMap(blur, cv2.COLORMAP_HOT)
    video_hm = cv2.addWeighted(frame, 0.7, heat_map, 0.7, 0)

    name = "./frames/frame%d.jpg" % i
    cv2.imwrite(name, video_hm)
    
    #cv2.imshow('Frame', frame)
    #cv2.imshow('FG Mask', fgMask)
    #cv2.imshow('Video OP', video_hm)
    #cv2.imshow('Blur', blur)
    
    keyboard = cv2.waitKey(30)
    if keyboard == 'q' or keyboard == 27:
        break

capture.release()
make_video('./frames/', './output.avi')
cv2.destroyAllWindows()

Upvotes: 2

Related Questions