I am currently working on a DIY book scanner project using a Raspberry Pi Camera V3 with 12 megapixels. I have tried using both libcamera and picamera2 to capture images, but I am facing performance issues. The capture process takes more than 6 seconds for each image, which is not ideal for my application.
has ever anybody use a camera on raspberry that capture images but not from the frame of the video? i need 12 mp because i need the most possible detail from the image of the book page.
i think that camera open and close in raspberry while i use the code but i did not find something that keep it open. ok probabply is of topic but the same sensors on smarphone can capture on the same resolution in much less than a sec .
import subprocess
import os
import re
import time
import RPi.GPIO as GPIO
output_folder = "your_output_folder" # Replace with your desired output folder
base_filename = "image"
file_extension = "jpg"
gpio_pin = 18 # GPIO pin to use
if not os.path.exists(output_folder):
os.makedirs(output_folder)
# Find the last image file in the folder
existing_files = [f for f in os.listdir(output_folder) if f.endswith(f".{file_extension}")]
if existing_files:
last_file = max(existing_files, key=lambda x: int(re.search(r'\d+', x).group()))
last_number = int(re.search(r'\d+', last_file).group())
else:
last_number = 0
GPIO.setmode(GPIO.BCM)
GPIO.setup(gpio_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
while True:
GPIO.wait_for_edge(gpio_pin, GPIO.FALLING)
# Record the start time
start_time = time.time()
# Increment the counter
last_number += 1
# Generate the output filename
output_filename = f"{base_filename}{last_number:04d}.{file_extension}"
output_path = os.path.join(output_folder, output_filename)
# Run the libcamera-jpeg command
command = ["libcamera-jpeg", "-n", "-o", output_path]
subprocess.run(command)
# Calculate and print the elapsed time with 1 decimal place
end_time = time.time()
elapsed_time = round(end_time - start_time, 1)
print(f"Image captured: {output_filename}, Elapsed Time: {elapsed_time} seconds")
result
User
[0:24:08.427953396] [2517] INFO Camera camera_manager.cpp:284 libcamera v0.1.0+118-563cd78e
[0:24:08.581691708] [2523] WARN RPiSdn sdn.cpp:39 Using legacy SDN tuning - please consider moving SDN inside rpi.denoise
[0:24:08.588225484] [2523] INFO RPI vc4.cpp:444 Registered camera /base/soc/i2c0mux/i2c@1/imx708@1a to Unicam device /dev/media3 and ISP device /dev/media0
[0:24:08.588380899] [2523] INFO RPI pipeline_base.cpp:1142 Using configuration file '/usr/share/libcamera/pipeline/rpi/vc4/rpi_apps.yaml'
Mode selection for 2304:1296:12:P
SRGGB10_CSI2P,1536x864/0 - Score: 3400
SRGGB10_CSI2P,2304x1296/0 - Score: 1000
SRGGB10_CSI2P,4608x2592/0 - Score: 1900
Stream configuration adjusted
[0:24:08.591796900] [2517] INFO Camera camera.cpp:1183 configuring streams: (0) 2304x1296-YUV420 (1) 2304x1296-SBGGR10_CSI2P
[0:24:08.592701680] [2523] INFO RPI vc4.cpp:608 Sensor: /base/soc/i2c0mux/i2c@1/imx708@1a - Selected sensor format: 2304x1296-SBGGR10_1X10 - Selected unicam format: 2304x1296-pBAA
Mode selection for 4608:2592:12:P
SRGGB10_CSI2P,1536x864/0 - Score: 10600
SRGGB10_CSI2P,2304x1296/0 - Score: 8200
SRGGB10_CSI2P,4608x2592/0 - Score: 1000
[0:24:13.816165872] [2517] INFO Camera camera.cpp:1183 configuring streams: (0) 4608x2592-YUV420 (1) 4608x2592-SBGGR10_CSI2P
[0:24:13.824487022] [2523] INFO RPI vc4.cpp:608 Sensor: /base/soc/i2c0mux/i2c@1/imx708@1a - Selected sensor format: 4608x2592-SBGGR10_1X10 - Selected unicam format: 4608x2592-pBAA
Still capture image received
Image captured: image0040.jpg, Elapsed Time: 9.4 seconds
this is for raspberry pi5 to use one camera v3
import keyboard
from picamera2 import Picamera2, Preview
import time
from datetime import datetime
from datetime import datetime
from libcamera import controls
import os
picam2 = Picamera2() # if u have one camera it will try to check it
#if u have alrerd two connected and wanna use only one use Picamera2(1) or Picamera2(1)
config = picam2.create_still_configuration(buffer_count=3)
picam2.configure(config)
picam2.start_preview(Preview.QTGL)
preview_config = picam2.create_preview_configuration({"size": (4096, 2592)})
picam2.configure(preview_config)
picam2.start()
picam2.set_controls({"AfMode": controls.AfModeEnum.Continuous })
try:
while True:
# Wait for the space key to be pressed
keyboard.wait("space")
# Record the start time
start_time = time.time()
# Capture an image
timeStamp = datetime.now().strftime("%Y%m%d-%H%M%S.%f")[:-4]
filename = f"z_img_{timeStamp}.jpg"
request = picam2.capture_request(flush=False )
request.save('main', filename)
request.release()
# Get the size of the captured image in bytes
file_size_bytes = os.path.getsize(filename)
# Convert the file size to megabytes
file_size_mb = file_size_bytes / (1024 ** 2)
# Record the end time
end_time = time.time()
# Calculate and print the time taken and the size of the image in megabytes
capture_time = end_time - start_time
print(f"Image captured: {filename}, Time taken: {capture_time:.2f} seconds, Size: {file_size_mb:.2f} MB")
except KeyboardInterrupt:
pass
finally:
# Clean up
picam2.stop_preview()
picam2.stop()
for two camera v3
import keyboard
from picamera2 import Picamera2, Preview
import time
from datetime import datetime
from libcamera import controls
import os
def capture_image(picam2, filename_prefix):
# Record the start time
start_time = time.time()
# Capture an image
timeStamp = datetime.now().strftime("%Y%m%d-%H%M%S.%f")[:-4]
filename = f"{filename_prefix}_img_{timeStamp}.jpg"
request = picam2.capture_request(flush=False)
request.save('main', filename)
request.release()
# Get the size of the captured image in bytes
file_size_bytes = os.path.getsize(filename)
# Convert the file size to megabytes
file_size_mb = file_size_bytes / (1024 ** 2)
# Record the end time
end_time = time.time()
# Calculate and print the time taken and the size of the image in megabytes
capture_time = end_time - start_time
print(f"Image captured: {filename}, Time taken: {capture_time:.2f} seconds, Size: {file_size_mb:.2f} MB")
# Set up the first camera
picam1 = Picamera2(1)
config1 = picam1.create_still_configuration(buffer_count=3)
picam1.configure(config1)
picam1.start_preview(Preview.QTGL)
preview_config1 = picam1.create_preview_configuration({"size": (4096, 2592)})
picam1.configure(preview_config1)
picam1.start()
picam1.set_controls({"AfMode": controls.AfModeEnum.Continuous})
# Set up the second camera
picam2 = Picamera2(0)
config2 = picam2.create_still_configuration(buffer_count=3)
picam2.configure(config2)
picam2.start_preview(Preview.QTGL)
preview_config2 = picam2.create_preview_configuration({"size": (4096, 2592)})
picam2.configure(preview_config2)
picam2.start()
picam2.set_controls({"AfMode": controls.AfModeEnum.Continuous})
try:
while True:
# Wait for the space key to be pressed
keyboard.wait("space")
# Capture images from both cameras
capture_image(picam1, "y")
capture_image(picam2, "x")
except KeyboardInterrupt:
pass
finally:
# Close QtGL preview windows
picam1.stop_preview()
picam2.stop_preview()
# Clean up both cameras
picam1.stop()
picam2.stop()
to calibrate camera i use app_capture_overlay.py before i use what script we made
if u wanna have lens opposite from a glass u have to see in the middle the lens on a mirror