proof of concept
This commit is contained in:
51
550d_config.py
Normal file
51
550d_config.py
Normal file
@@ -0,0 +1,51 @@
|
||||
import gphoto2 as gp
|
||||
|
||||
# def list_config(widget, indent=0):
|
||||
# name = widget.get_name()
|
||||
# label = widget.get_label()
|
||||
# type_name = widget.get_type()
|
||||
# choices = widget.get_choices()
|
||||
# if choices:
|
||||
# choices_str = ", ".join(choices)
|
||||
# print(" " * indent + f"{name} ({label}) type={type_name} choices=[{choices_str}]")
|
||||
# else:
|
||||
|
||||
# print(" " * indent + f"{name} ({label}) type={type_name}")
|
||||
|
||||
# for i in range(widget.count_children()):
|
||||
# child = widget.get_child(i)
|
||||
# list_config(child, indent + 1)
|
||||
|
||||
|
||||
def list_config(widget, indent=0):
|
||||
name = widget.get_name()
|
||||
label = widget.get_label()
|
||||
type_name = widget.get_type()
|
||||
|
||||
line = " " * indent + f"{name} ({label}) type={type_name}"
|
||||
|
||||
# tylko jeśli widget obsługuje choices
|
||||
try:
|
||||
choices = widget.get_choices()
|
||||
if choices:
|
||||
choices_str = ", ".join(str(c) for c in choices)
|
||||
line += f" choices=[{choices_str}]"
|
||||
except gp.GPhoto2Error:
|
||||
# brak choices -> ignorujemy
|
||||
pass
|
||||
|
||||
print(line)
|
||||
|
||||
# rekurencja dla dzieci
|
||||
for i in range(widget.count_children()):
|
||||
child = widget.get_child(i)
|
||||
list_config(child, indent + 1)
|
||||
|
||||
|
||||
camera = gp.Camera()
|
||||
camera.init()
|
||||
|
||||
config = camera.get_config()
|
||||
list_config(config)
|
||||
|
||||
camera.exit()
|
||||
82
config.txt
Normal file
82
config.txt
Normal file
@@ -0,0 +1,82 @@
|
||||
(.venv) bartool@BARTOOL-PC:~/local_projects/canon_550d$ python 550d_config.py
|
||||
main (Camera and Driver Configuration) type=0
|
||||
actions (Camera Actions) type=1
|
||||
syncdatetime (Synchronize camera date and time with PC) type=4
|
||||
uilock (UI Lock) type=4
|
||||
popupflash (Popup Flash) type=4
|
||||
autofocusdrive (Drive Canon DSLR Autofocus) type=4
|
||||
manualfocusdrive (Drive Canon DSLR Manual focus) type=5 choices=[Near 1, Near 2, Near 3, None, Far 1, Far 2, Far 3]
|
||||
cancelautofocus (Cancel Canon DSLR Autofocus) type=4
|
||||
eoszoom (Canon EOS Zoom) type=2
|
||||
eoszoomposition (Canon EOS Zoom Position) type=2
|
||||
viewfinder (Canon EOS Viewfinder) type=4
|
||||
eosremoterelease (Canon EOS Remote Release) type=5 choices=[None, Press Half, Press Full, Release Half, Release Full, Immediate, Press 1, Press 2, Press 3, Release 1, Release 2, Release 3]
|
||||
eosmoviemode (Movie Mode) type=4
|
||||
opcode (PTP Opcode) type=2
|
||||
settings (Camera Settings) type=1
|
||||
datetime (Camera Date and Time) type=8
|
||||
reviewtime (Quick Review Time) type=5 choices=[None, 2 seconds, 4 seconds, 8 seconds, Hold]
|
||||
output (Camera Output) type=5 choices=[TFT, PC, MOBILE, Off]
|
||||
movierecordtarget (Recording Destination) type=5 choices=[None]
|
||||
evfmode (EVF Mode) type=5 choices=[0, 1]
|
||||
ownername (Owner Name) type=2
|
||||
artist (Artist) type=2
|
||||
copyright (Copyright) type=2
|
||||
customfuncex (Custom Functions Ex) type=2
|
||||
focusinfo (Focus Info) type=2
|
||||
strobofiring (Strobo Firing) type=5 choices=[0, 1, 2]
|
||||
flashcharged (Flash Charging State) type=2
|
||||
autopoweroff (Auto Power Off) type=2
|
||||
depthoffield (Depth of Field) type=2
|
||||
capturetarget (Capture Target) type=5 choices=[Internal RAM, Memory card]
|
||||
capture (Capture) type=4
|
||||
remotemode (Remote Mode) type=2
|
||||
eventmode (Event Mode) type=2
|
||||
status (Camera Status Information) type=1
|
||||
serialnumber (Serial Number) type=2
|
||||
manufacturer (Camera Manufacturer) type=2
|
||||
cameramodel (Camera Model) type=2
|
||||
deviceversion (Device Version) type=2
|
||||
vendorextension (Vendor Extension) type=2
|
||||
model (Camera Model) type=2
|
||||
ptpversion (PTP Version) type=2
|
||||
batterylevel (Battery Level) type=2
|
||||
batterylevel (Battery Level) type=2
|
||||
mirrorlockstatus (Mirror Lock Status) type=2
|
||||
mirrordownstatus (Mirror Down Status) type=2
|
||||
lensname (Lens Name) type=2
|
||||
eosserialnumber (Serial Number) type=2
|
||||
shuttercounter (Shutter Counter) type=2
|
||||
availableshots (Available Shots) type=2
|
||||
eosmovieswitch (Movie Switch) type=2
|
||||
imgsettings (Image Settings) type=1
|
||||
imageformat (Image Format) type=5 choices=[L, cL, M, cM, S, cS, RAW + L, RAW]
|
||||
imageformatsd (Image Format SD) type=5 choices=[L, cL, M, cM, S, cS, RAW + L, RAW]
|
||||
iso (ISO Speed) type=5 choices=[Auto, 100, 200, 400, 800, 1600, 3200, 6400]
|
||||
whitebalance (WhiteBalance) type=5 choices=[Auto, Daylight, Shadow, Cloudy, Tungsten, Fluorescent, Flash, Manual]
|
||||
whitebalanceadjusta (WhiteBalance Adjust A) type=5 choices=[-9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
whitebalanceadjustb (WhiteBalance Adjust B) type=5 choices=[-9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
whitebalancexa (WhiteBalance X A) type=5 choices=[0, 1, 2, 3]
|
||||
whitebalancexb (WhiteBalance X B) type=5 choices=[0, 1, 2, 3]
|
||||
colorspace (Color Space) type=5 choices=[sRGB, AdobeRGB]
|
||||
capturesettings (Capture Settings) type=1
|
||||
exposurecompensation (Exposure Compensation) type=5 choices=[-5, -4.6, -4.3, -4, -3.6, -3.3, -3, -2.6, -2.3, -2, -1.6, -1.3, -1, -0.6, -0.3, 0, 0.3, 0.6, 1, 1.3, 1.6, 2, 2.3, 2.6, 3, 3.3, 3.6, 4, 4.3, 4.6, 5]
|
||||
focusmode (Focus Mode) type=5 choices=[One Shot, AI Focus, AI Servo, Manual]
|
||||
afmethod (AF Method) type=5 choices=[Live, LiveFace, Quick]
|
||||
storageid (Storage Device) type=2
|
||||
autoexposuremode (Canon Auto Exposure Mode) type=5 choices=[P, TV, AV, Manual, Bulb, A_DEP, DEP, Custom, Lock, Green, Night Portrait, Sports, Portrait, Landscape, Closeup, Flash Off, C2, C3, Creative Auto, Movie, Auto, Handheld Night Scene, HDR Backlight Control, SCN, Food, Grainy B/W, Soft focus, Toy camera effect, Fish-eye effect, Water painting effect, Miniature effect, HDR art standard, HDR art vivid, HDR art bold, HDR art embossed, Panning, HDR, Self Portrait, Hybrid Auto, Smooth skin, Fv]
|
||||
drivemode (Drive Mode) type=5 choices=[Single, Continuous, Timer 10 sec, Timer 2 sec, Continuous timer]
|
||||
picturestyle (Picture Style) type=5 choices=[Standard, Portrait, Landscape, Neutral, Faithful, Monochrome, User defined 1, User defined 2, User defined 3]
|
||||
aperture (Aperture) type=5 choices=[implicit auto]
|
||||
shutterspeed (Shutter Speed) type=5 choices=[30, 25, 20, 15, 13, 10.3, 8, 6.3, 5, 4, 3.2, 2.5, 2, 1.6, 1.3, 1, 0.8, 0.6, 0.5, 0.4, 0.3, 1/4, 1/5, 1/6, 1/8, 1/10, 1/13, 1/15, 1/20, 1/25, 1/30, 1/40, 1/50, 1/60, 1/80, 1/100, 1/125, 1/160, 1/200, 1/250, 1/320, 1/400, 1/500, 1/640, 1/800, 1/1000, 1/1250, 1/1600, 1/2000, 1/2500, 1/3200, 1/4000]
|
||||
meteringmode (Metering Mode) type=5 choices=[Evaluative, Partial, Spot, Center-weighted average]
|
||||
liveviewsize (Live View Size) type=5 choices=[Large, Medium]
|
||||
bracketmode (Bracket Mode) type=5 choices=[Unknown value 0000]
|
||||
aeb (Auto Exposure Bracketing) type=5 choices=[off, +/- 1/3, +/- 2/3, +/- 1, +/- 1 1/3, +/- 1 2/3, +/- 2]
|
||||
alomode (Auto Lighting Optimization) type=5 choices=[Standard (disabled in manual exposure), x1, x2, x3]
|
||||
other (Other PTP Device Properties) type=1
|
||||
d402 (Friendly Device Name) type=2
|
||||
d407 (Perceived Device Type) type=2
|
||||
d406 (Session Initiator Info) type=2
|
||||
d303 (PTP Property 0xd303) type=2
|
||||
5001 (Battery Level) type=6 choices=[100, 0, 75, 50]
|
||||
29
live_flask.py
Normal file
29
live_flask.py
Normal file
@@ -0,0 +1,29 @@
|
||||
import cv2
|
||||
import numpy as np
|
||||
import gphoto2 as gp
|
||||
from flask import Flask, Response
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
camera = gp.Camera()
|
||||
camera.init()
|
||||
|
||||
def generate():
|
||||
while True:
|
||||
file = camera.capture_preview()
|
||||
data = file.get_data_and_size()
|
||||
frame = np.frombuffer(data, dtype=np.uint8)
|
||||
frame = cv2.imdecode(frame, cv2.IMREAD_COLOR)
|
||||
|
||||
if frame is not None:
|
||||
_, buffer = cv2.imencode('.jpg', frame)
|
||||
yield (b'--frame\r\n'
|
||||
b'Content-Type: image/jpeg\r\n\r\n' + buffer.tobytes() + b'\r\n')
|
||||
|
||||
@app.route('/liveview')
|
||||
def liveview():
|
||||
return Response(generate(),
|
||||
mimetype='multipart/x-mixed-replace; boundary=frame')
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run(host="0.0.0.0", port=5000)
|
||||
125
live_pyside.py
Normal file
125
live_pyside.py
Normal file
@@ -0,0 +1,125 @@
|
||||
import sys
|
||||
import cv2
|
||||
import numpy as np
|
||||
from PySide6.QtWidgets import QApplication, QWidget, QLabel, QPushButton, QVBoxLayout, QHBoxLayout
|
||||
from PySide6.QtGui import QImage, QPixmap
|
||||
from PySide6.QtCore import QTimer
|
||||
import gphoto2 as gp
|
||||
|
||||
class LiveViewApp(QWidget):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.setWindowTitle("Canon LiveView")
|
||||
|
||||
# Widget do obrazu
|
||||
self.image_label = QLabel("Brak obrazu")
|
||||
self.image_label.setFixedSize(640, 480)
|
||||
|
||||
# Przyciski start/stop
|
||||
self.start_button = QPushButton("Start LiveView")
|
||||
self.stop_button = QPushButton("Stop LiveView")
|
||||
self.stop_button.setEnabled(False)
|
||||
|
||||
self.start_button.clicked.connect(self.start_liveview)
|
||||
self.stop_button.clicked.connect(self.stop_liveview)
|
||||
|
||||
# Layout
|
||||
button_layout = QHBoxLayout()
|
||||
button_layout.addWidget(self.start_button)
|
||||
button_layout.addWidget(self.stop_button)
|
||||
|
||||
layout = QVBoxLayout()
|
||||
layout.addWidget(self.image_label)
|
||||
layout.addLayout(button_layout)
|
||||
|
||||
self.setLayout(layout)
|
||||
|
||||
# Timer do odświeżania obrazu
|
||||
self.timer = QTimer()
|
||||
self.timer.timeout.connect(self.update_frame)
|
||||
|
||||
# kamera (na razie None – podepniesz gphoto2)
|
||||
self.camera = None
|
||||
self.set_dummy_frame()
|
||||
|
||||
|
||||
|
||||
def set_dummy_frame(self):
|
||||
self.dummy_frame = np.zeros((480, 640, 3), dtype=np.uint8)
|
||||
cv2.putText(self.dummy_frame, "LiveView OFF", (200, 240),
|
||||
cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
|
||||
|
||||
rgb_image = cv2.cvtColor(self.dummy_frame, cv2.COLOR_BGR2RGB)
|
||||
h, w, ch = rgb_image.shape
|
||||
qimg = QImage(rgb_image.data, w, h, ch * w, QImage.Format_RGB888)
|
||||
pixmap = QPixmap.fromImage(qimg)
|
||||
|
||||
self.image_label.setPixmap(pixmap)
|
||||
|
||||
def start_liveview(self):
|
||||
print("Start LiveView")
|
||||
self.start_button.setEnabled(False)
|
||||
self.stop_button.setEnabled(True)
|
||||
# TODO: tu zainicjalizujesz kamerę gphoto2
|
||||
# Przykład inicjalizacji kamery przez gphoto2 (wymaga zainstalowanego python-gphoto2)
|
||||
try:
|
||||
self.camera = gp.Camera()
|
||||
self.camera.init()
|
||||
except Exception as e:
|
||||
print(f"Błąd inicjalizacji kamery: {e}")
|
||||
self.camera = None
|
||||
self.timer.start(100) # odświeżanie co 100ms
|
||||
|
||||
def stop_liveview(self):
|
||||
print("Stop LiveView")
|
||||
self.timer.stop()
|
||||
self.start_button.setEnabled(True)
|
||||
self.stop_button.setEnabled(False)
|
||||
self.image_label.setText("Brak obrazu")
|
||||
self.image_label.setPixmap(QPixmap()) # czyści obraz
|
||||
|
||||
self.set_dummy_frame()
|
||||
# TODO: tu zamkniesz kamerę gphoto2
|
||||
if self.camera:
|
||||
self.camera.exit()
|
||||
self.camera = None
|
||||
self.start_button.setEnabled(True)
|
||||
self.stop_button.setEnabled(False)
|
||||
|
||||
def update_frame(self):
|
||||
# Na razie sztuczna klatka testowa z OpenCV (czarne tło + napis)
|
||||
# frame = np.zeros((480, 640, 3), dtype=np.uint8)
|
||||
# cv2.putText(frame, "Canon LiveView", (50, 240),
|
||||
# cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
|
||||
|
||||
if self.camera:
|
||||
try:
|
||||
file = self.camera.capture_preview()
|
||||
data = file.get_data_and_size()
|
||||
frame = np.frombuffer(data, dtype=np.uint8)
|
||||
frame = cv2.imdecode(frame, cv2.IMREAD_COLOR)
|
||||
|
||||
if frame is None:
|
||||
return
|
||||
|
||||
except gp.GPhoto2Error as e:
|
||||
print(f"Błąd odczytu LiveView: {e}")
|
||||
return
|
||||
except Exception as e:
|
||||
print(f"Nieoczekiwany błąd: {e}")
|
||||
return
|
||||
else:
|
||||
return
|
||||
# Konwersja OpenCV -> QImage
|
||||
rgb_image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
||||
h, w, ch = rgb_image.shape
|
||||
qimg = QImage(rgb_image.data, w, h, ch * w, QImage.Format_RGB888)
|
||||
pixmap = QPixmap.fromImage(qimg)
|
||||
|
||||
self.image_label.setPixmap(pixmap)
|
||||
|
||||
if __name__ == "__main__":
|
||||
app = QApplication(sys.argv)
|
||||
window = LiveViewApp()
|
||||
window.show()
|
||||
sys.exit(app.exec())
|
||||
26
live_view.py
Normal file
26
live_view.py
Normal file
@@ -0,0 +1,26 @@
|
||||
import gphoto2 as gp
|
||||
import cv2
|
||||
import numpy as np
|
||||
|
||||
camera = gp.Camera()
|
||||
camera.init()
|
||||
|
||||
def liveview():
|
||||
while True:
|
||||
# Pobierz klatkę z LiveView
|
||||
file = camera.capture_preview()
|
||||
data = file.get_data_and_size()
|
||||
frame = np.frombuffer(data, dtype=np.uint8)
|
||||
frame = cv2.imdecode(frame, cv2.IMREAD_COLOR)
|
||||
|
||||
if frame is not None:
|
||||
cv2.imshow("LiveView", frame)
|
||||
|
||||
if cv2.waitKey(1) == 27: # ESC
|
||||
break
|
||||
|
||||
cv2.destroyAllWindows()
|
||||
camera.exit()
|
||||
|
||||
if __name__ == "__main__":
|
||||
liveview()
|
||||
27
test_pyside.py
Normal file
27
test_pyside.py
Normal file
@@ -0,0 +1,27 @@
|
||||
import sys
|
||||
from PySide6.QtWidgets import QApplication, QWidget, QLabel, QPushButton, QVBoxLayout
|
||||
|
||||
class TestWindow(QWidget):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.setWindowTitle("PySide6 Test")
|
||||
|
||||
# Tworzymy label
|
||||
self.label = QLabel("Hello from PySide6!", self)
|
||||
|
||||
# Tworzymy przycisk do zamykania
|
||||
self.close_button = QPushButton("Zamknij")
|
||||
self.close_button.clicked.connect(self.close)
|
||||
|
||||
# Układ pionowy
|
||||
layout = QVBoxLayout()
|
||||
layout.addWidget(self.label)
|
||||
layout.addWidget(self.close_button)
|
||||
|
||||
self.setLayout(layout)
|
||||
|
||||
if __name__ == "__main__":
|
||||
app = QApplication(sys.argv)
|
||||
window = TestWindow()
|
||||
window.show()
|
||||
sys.exit(app.exec())
|
||||
Reference in New Issue
Block a user