Search code examples
pythonpathworking-directory

Problem while trying to save a frame after every 1 second using opencv


I tried running the code below, it runs successfully but the images are not saved anywhere on the system. Does anyone know where the problem is or the solution?

import cv2
import time

# open the default camera
cap = cv2.VideoCapture(0)

# set the width and height of the frame
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)

# set the start time
start_time = time.time()

# loop through the frames
print("looping through frames")
while True:
    # capture a frame
    ret, frame = cap.read()

    t = time.localtime()
    current_time = time.strftime("%H:%M:%S", t)

    # define the output file name and format
    output_file = f'/Frame_{current_time}.jpg'
    output_format = 'JPEG'

    # check if the frame is captured successfully
    if not ret:
        break

    # calculate the elapsed time
    elapsed_time = time.time() - start_time

    # check if 1 second has passed
    if elapsed_time >= 1:
        print("1 second passed")
        # save the frame as an image file
        cv2.imwrite(f'/TestFrames/{output_file}', frame)
        print(output_file)
        print("image saved")

        # reset the start time
        start_time = time.time()
        print("time reset")

    # display the frame
    cv2.imshow('frame', frame)

    # check for the 'q' key to quit
    if cv2.waitKey(1) == ord('q'):
        break

# release the camera and close all windows
cap.release()
cv2.destroyAllWindows()

I tried running the code below, it runs successfully but the images are not saved anywhere on the system.


Solution

  • The main issue is that the image file name contains colon (:) characters, and colon character is invalid character (at least for a Windows) file name.

    For testing, we may check the returned status of cv2.imwrite (status is True for success and False for failure):

    is_ok = cv2.imwrite(f'/TestFrames/{output_file}', frame)
    print(output_file)
    
    if is_ok:
        print("image saved")
    else:
        print("Failed saving the image")
    

    Assuming we are using Windows:

    We may replace the : characters with _ for example:

    output_file = f'Frame_{current_time}.jpg'
    output_file = output_file.replace(":", "_")
    

    The following answer recommends to replace the colon with a unicode character "" that looks like colon, but cv2.imwrite doesn't support unicode characters (at least not in Windows).

    In case we want to use the '\ua789' unicode character we may use cv2.imencode and binary file writing:

    with open(f'/TestFrames/{output_file}', 'wb') as f:  # Open image file as binary file for writing
        cv2.imencode('.'+output_format, frame)[1].tofile(f)  # encode the image as JPEG, and write the encoded image to the file (use [1] because cv2.imencode returns a tuple).
    

    Code sample that uses the unicode character instead of colon:

    import cv2
    import time
    
    # open the default camera
    cap = cv2.VideoCapture(0)
    
    # set the width and height of the frame
    cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
    cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
    
    # set the start time
    start_time = time.time()
    
    # loop through the frames
    print("looping through frames")
    while True:
        # capture a frame
        ret, frame = cap.read()
    
        t = time.localtime()
        current_time = time.strftime("%H:%M:%S", t)
    
        # define the output file name and format
        output_file = f'Frame_{current_time}.jpg'
        output_file = output_file.replace(":", "\ua789")  # Replace colon character with a character that looks like colon
        #output_file = output_file.replace(":", "_")  # Replace colon character with a underscore character
        output_format = 'JPEG'
    
        # check if the frame is captured successfully
        if not ret:
            break
    
        # calculate the elapsed time
        elapsed_time = time.time() - start_time
    
        # check if 1 second has passed
        if elapsed_time >= 1:
            print("1 second passed")
    
            # save the frame as an image file
            #is_ok = cv2.imwrite(f'/TestFrames/{output_file}', frame)
    
            with open(f'/TestFrames/{output_file}', 'wb') as f:  # Open image file as binary file for writing
                cv2.imencode('.'+output_format, frame)[1].tofile(f)  # encode the image as JPEG, and write the encoded image to the file (use [1] because cv2.imencode returns a tuple).
    
            print(output_file)
            print("image saved")
    
            # reset the start time
            start_time = time.time()
            print("time reset")
    
        # display the frame
        cv2.imshow('frame', frame)
    
        # check for the 'q' key to quit
        if cv2.waitKey(1) == ord('q'):
            break
    
    # release the camera and close all windows
    cap.release()
    
    cv2.destroyAllWindows()