INNO-MAKER / U20CAM-9281M

3 stars 1 forks source link

External Trigger Duplicale Images #1

Open rohan1198 opened 3 months ago

rohan1198 commented 3 months ago

Hi there, I am trying to use the U20CAM-9281M camera with the external trigger. I generate the trigger using an Arduino with this code:

#define TRIGGER_PIN 5 // The pin used to send the trigger signal

void setup() {
  pinMode(TRIGGER_PIN, OUTPUT); // Initialize the trigger pin as an output
  digitalWrite(TRIGGER_PIN, LOW); // Ensure the trigger pin starts in a LOW state
  Serial.begin(115200); // Start serial communication at 115200 baud rate
}

void loop() {
  digitalWrite(TRIGGER_PIN, HIGH); // Trigger signal HIGH
  delayMicroseconds(1000); // Pulse duration of HIGH signal is 200 microseconds
  digitalWrite(TRIGGER_PIN, LOW); // Trigger signal LOW

  Serial.println("C"); // Send trigger command

  delay(1000); // Full one second delay to maintain 1 Hz frequency
}

Then I use this python script to capture the images triggered by the camera:

import cv2
import threading
import queue
import datetime
import os

# Global flag for stopping threads
stop_threads = False

# Queue for storing frames for display and save
frame_queue = queue.Queue(maxsize=10)

# Directory to save images
save_dir = "images"
os.makedirs(save_dir, exist_ok=True)

# Number of images to capture and save
image_count = 20

# Global counter for image filenames
image_counter = 1

def camera_capture_thread(camera_device):
    global stop_threads
    cap = cv2.VideoCapture(camera_device)
    if not cap.isOpened():
        print("Cannot open camera")
        return

    while not stop_threads and image_count > 0:
        ret, frame = cap.read()
        if not ret:
            print("Can't receive frame. Exiting ...")
            break
        try:
            frame_queue.put_nowait(frame)
        except queue.Full:
            pass

    cap.release()

def display_and_save_thread():
    global stop_threads, image_count, image_counter

    while not stop_threads and image_count > 0:
        if not frame_queue.empty():
            frame = frame_queue.get()
            timestamp = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S-%f")
            filename = os.path.join(save_dir, f"img_{image_counter}_{timestamp}.jpg")
            cv2.imwrite(filename, frame)
            print(f"Saved {filename}")
            image_count -= 1
            image_counter += 1  # Increment the counter after saving an image

            cv2.putText(frame, timestamp, (10, 50), cv2.FONT_HERSHEY_SIMPLEX, 
                        1, (255, 255, 255), 2, cv2.LINE_AA)
            cv2.imshow('Captured Image', frame)
            if cv2.waitKey(1) & 0xFF == ord('q'):
                stop_threads = True

if __name__ == "__main__":
    capture_thread = threading.Thread(target=camera_capture_thread, args=("/dev/video0",))
    display_thread = threading.Thread(target=display_and_save_thread)

    capture_thread.start()
    display_thread.start()

    capture_thread.join()
    display_thread.join()

    cv2.destroyAllWindows()

I get this output from my v4l2:

❯ v4l2-ctl -l                     
                     brightness 0x00980900 (int)    : min=-64 max=64 step=1 default=0 value=20
                       contrast 0x00980901 (int)    : min=0 max=64 step=1 default=32 value=32
                     saturation 0x00980902 (int)    : min=0 max=128 step=1 default=0 value=0
                            hue 0x00980903 (int)    : min=-40 max=40 step=1 default=0 value=0
 white_balance_temperature_auto 0x0098090c (bool)   : default=1 value=1
                          gamma 0x00980910 (int)    : min=72 max=500 step=1 default=100 value=100
                           gain 0x00980913 (int)    : min=0 max=64 step=1 default=15 value=45
           power_line_frequency 0x00980918 (menu)   : min=0 max=2 default=1 value=2
      white_balance_temperature 0x0098091a (int)    : min=2800 max=6500 step=1 default=4600 value=4600 flags=inactive
                      sharpness 0x0098091b (int)    : min=0 max=6 step=1 default=3 value=3
         backlight_compensation 0x0098091c (int)    : min=0 max=3 step=1 default=1 value=1
                  exposure_auto 0x009a0901 (menu)   : min=0 max=3 default=3 value=1
              exposure_absolute 0x009a0902 (int)    : min=1 max=5000 step=1 default=157 value=200
         exposure_auto_priority 0x009a0903 (bool)   : default=0 value=0
                 focus_absolute 0x009a090a (int)    : min=1 max=100 step=1 default=1 value=1 flags=inactive
                     focus_auto 0x009a090c (bool)   : default=0 value=1

With this setup, I have noticed that I get two images after each trigger:

Saved images/img_1_2024-03-22_16-47-13-252488.jpg
Saved images/img_2_2024-03-22_16-47-14-214541.jpg
Saved images/img_3_2024-03-22_16-47-14-250490.jpg
Saved images/img_4_2024-03-22_16-47-15-218713.jpg
Saved images/img_5_2024-03-22_16-47-15-249771.jpg
Saved images/img_6_2024-03-22_16-47-16-217733.jpg
Saved images/img_7_2024-03-22_16-47-16-249886.jpg
Saved images/img_8_2024-03-22_16-47-17-218003.jpg
Saved images/img_9_2024-03-22_16-47-17-249905.jpg
Saved images/img_10_2024-03-22_16-47-18-217891.jpg

Here, I can see roughly 300ms delay between two images when they are triggered sometimes, and about 1 second other times. How can I prevent the duplicate capturing by a single trigger signal? Any help would be helpful.

Taoran2023 commented 3 days ago

same issue, did you solve it,I tried with my laptop and JetsonNano, same problem?

Taoran2023 commented 3 days ago

Also, I noticed that, the time gap between first and second frame depends on your video fps setting. I am thinking it is bug...