nicknochnack / TFODCourse

944 stars 920 forks source link

Optimize Image Collection Script to Avoid `time.sleep()` #159

Open kust1011 opened 5 months ago

kust1011 commented 5 months ago

Description:

The current script for collecting images for machine learning dataset creation relies on time.sleep() to enforce a delay of 5 seconds between each image capture. This method of introducing delay not only causes the application to pause, creating a noticeable "stutter" or "freeze" in the video feed, but also makes the process of capturing screenshots less convenient and less responsive to real-time changes in the video stream. This issue of delay and unresponsiveness is evident in the instructional video, where the script's inability to capture images smoothly and promptly can lead to missed opportunities for capturing the desired frames.

Proposed Changes:

Replace the usage of time.sleep() with a non-blocking approach that utilizes cv2.VideoCapture.get(cv2.CAP_PROP_POS_MSEC) to monitor elapsed time since the video capture started. This method should allow the script to continue processing video frames while still ensuring images are captured at 5-second intervals.

Current Implementation:

for label in labels:
    cap = cv2.VideoCapture(0)
    print('Collecting images for {}'.format(label))
    time.sleep(5)
    for imgnum in range(number_imgs):
        print('Collecting image {}'.format(imgnum))
        ret, frame = cap.read()
        imgname = os.path.join(IMAGES_PATH,label,label+'.'+'{}.jpg'.format(str(uuid.uuid1())))
        cv2.imwrite(imgname, frame)
        cv2.imshow('frame', frame)
        time.sleep(2)

        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
cap.release()
cv2.destroyAllWindows()

Suggested Improvement:

cap = cv2.VideoCapture(0)

for label in labels:
    print('Collecting images for {}'.format(label))
    initial_time = None  # Initialize the start time
    imgnum = 0  # Initialize the image counter

    while imgnum < number_imgs:
        ret, frame = cap.read()

        if not ret:
            print("Failed to grab frame")
            break

        current_time = cap.get(cv2.CAP_PROP_POS_MSEC)  # Get the current timestamp of the video capture

        # Initialize initial_time
        if initial_time is None:
            initial_time = current_time

        # Save an image every 5 seconds
        if current_time - initial_time >= 5000:
            imgname = os.path.join(IMAGES_PATH, label, label + '.' + '{}.jpg'.format(str(uuid.uuid1())))
            cv2.imwrite(imgname, frame)
            print('Collecting image {}'.format(imgnum))
            imgnum += 1
            initial_time = current_time  # Reset the start time

        cv2.imshow('frame', frame)

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

cap.release()
cv2.destroyAllWindows()