Ich möchte eine simple Software für meine Fotobox schreiben.
Die Software soll einfach einen Live-Stream anzeigen, bei Klick aufs Bild nen Countdown starten, Foto machen, für X Sekunden anzeigen und wieder zurück zum Livestream.
Mir ist bewusst, dass beides gleichzeitig nicht funktioniert, daher soll der Stream ja vor dem capture Befehl stoppen um das Interface der Kamera wieder freizugeben.
Das funktioniert nur leider nicht. Ich bekomme nen Live-Stream, der Countdown zählt runter nach Klick, aber es wird einfach kein Foto gemacht.
Das ist der Output der Konsole:
Code: Alles auswählen
python3 ./pb5.py
[ WARN:0@3.678] global ./modules/videoio/src/cap_gstreamer.cpp (2401) handleMessage OpenCV | GStreamer warning: Embedded video playback halted; module typefind reported: Could not determine type of stream.
[ WARN:0@3.678] global ./modules/videoio/src/cap_gstreamer.cpp (1356) open OpenCV | GStreamer warning: unable to start pipeline
[ WARN:0@3.678] global ./modules/videoio/src/cap_gstreamer.cpp (862) isPipelinePlaying OpenCV | GStreamer warning: GStreamer: pipeline have not been created
*** Error ***
An error occurred in the io-library ('Could not claim the USB device'): Could not claim interface 0 (Device or resource busy). Make sure no other program (gvfs-gphoto2-volume-monitor) or kernel module (such as sdc2xx, stv680, spca50x) is using the device and you have read/write access to the device.
ERROR: Could not capture image.
ERROR: Could not capture.
*** Error (-53: 'Could not claim the USB device') ***
For debugging messages, please use the --debug option.
Debugging messages may help finding a solution to your problem.
If you intend to send any error or debug messages to the gphoto
developer mailing list <gphoto-devel@lists.sourceforge.net>, please run
gphoto2 as follows:
env LANG=C gphoto2 --debug --debug-logfile=my-logfile.txt --capture-image-and-download --filename photo.jpg --force-overwrite
Please make sure there is sufficient quoting around the arguments.
[ WARN:0@12.437] global ./modules/videoio/src/cap_gstreamer.cpp (2401) handleMessage OpenCV | GStreamer warning: Embedded video playback halted; module typefind reported: Could not determine type of stream.
[ WARN:0@12.437] global ./modules/videoio/src/cap_gstreamer.cpp (1356) open OpenCV | GStreamer warning: unable to start pipeline
[ WARN:0@12.437] global ./modules/videoio/src/cap_gstreamer.cpp (862) isPipelinePlaying OpenCV | GStreamer warning: GStreamer: pipeline have not been created
^CTraceback (most recent call last):
File "/home/bpw/diypb/./pb5.py", line 43, in <module>
ret, frame = cap.read()
^^^^^^^^^^
KeyboardInterrupt
Und das ist mein Code:
Code: Alles auswählen
import cv2
import subprocess
import time
import os
VIRTUAL_DEVICE = "/dev/video10"
WINDOW_NAME = "Fotobox Test"
PHOTO_PATH = "photo.jpg"
COUNTDOWN = 3
USB_WAIT = 2 #delay falls die kamera bissel länger braucht
def start_stream():
cmd = [
"bash", "-c",
f"gphoto2 --stdout --capture-movie | ffmpeg -f mjpeg -i - "
f"-vcodec rawvideo -pix_fmt bgr24 -f v4l2 {VIRTUAL_DEVICE}"
]
return subprocess.Popen(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
def capture_photo():
subprocess.run(["gphoto2", "--capture-image-and-download",
"--filename", PHOTO_PATH, "--force-overwrite"])
clicked = False
countdown_start = None
def mouse_callback(event, x, y, flags, param):
global clicked, countdown_start
if event == cv2.EVENT_LBUTTONDOWN and countdown_start is None:
clicked = True
countdown_start = time.time()
cv2.namedWindow(WINDOW_NAME, cv2.WINDOW_NORMAL)
cv2.setWindowProperty(WINDOW_NAME, cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)
cv2.setMouseCallback(WINDOW_NAME, mouse_callback)
while True:
stream_proc = start_stream()
time.sleep(2) # kurz warten, bis Stream verfügbar
cap = cv2.VideoCapture(VIRTUAL_DEVICE)
while True:
ret, frame = cap.read()
if not ret:
continue
# Countdown Overlay
if countdown_start is not None:
elapsed = time.time() - countdown_start
remaining = COUNTDOWN - int(elapsed)
h, w = frame.shape[:2]
if remaining > 0:
overlay = frame.copy()
cv2.putText(overlay, str(remaining),
(w//2 - 50, h//2),
cv2.FONT_HERSHEY_SIMPLEX,
4, (0,0,255), 8)
cv2.imshow(WINDOW_NAME, overlay)
else:
# Countdown fertig -> Livestream stoppen
stream_proc.terminate()
cap.release()
time.sleep(USB_WAIT) # USB-Port freigeben
# Foto aufnehmen
capture_photo()
# Foto anzeigen
if os.path.exists(PHOTO_PATH):
photo = cv2.imread(PHOTO_PATH)
cv2.imshow(WINDOW_NAME, photo)
cv2.waitKey(5000)
countdown_start = None
clicked = False
break # verlässt inneren Loop → Livestream neu starten
else:
cv2.imshow(WINDOW_NAME, frame)
key = cv2.waitKey(1) & 0xFF
if key == ord('q'):
stream_proc.terminate()
cap.release()
cv2.destroyAllWindows()
exit()
Ich habe die EOS500D. Funktioniert mit diversen anderen Fotobox-Software's auch einwandfrei.
Ergänzung / Was ich bisher probiert hab: "pkill -f gvfs-gphoto2 und pkill -f gvfs-gphoto2-volume-monitor" bevor ich den Script gestartet hab. Leider ohne Erfolg. Er startet ja auch den LiveStream. Das Problem muss irgendwo zwischen Livestream beenden und Foto machen sein.