Skip to content

Commit 1a0e79d

Browse files
Enable gtk on opencv builds
1 parent ab80c83 commit 1a0e79d

3 files changed

Lines changed: 53 additions & 11 deletions

File tree

flake.lock

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

flake.nix

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,16 @@
1616
system:
1717
let
1818
pkgs = import nixpkgs { inherit system; };
19-
python = pkgs.python313;
19+
python = pkgs.python313.override {
20+
packageOverrides = pyFinal: _pyPrev: {
21+
opencv4 = pkgs.opencv4.override {
22+
enablePython = true;
23+
pythonPackages = pyFinal;
24+
enableGtk3 = true;
25+
gtk3 = pkgs.gtk3;
26+
};
27+
};
28+
};
2029
pythonEnv = python.withPackages (ps: [
2130
ps.click
2231
ps.imageio

xfer.py

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from math import log2, floor
1111
import json
1212
import logging
13+
import time
1314

1415
## tweakable params
1516
CHUNK_SIZE = 256
@@ -48,20 +49,51 @@ def open_video(idx: int):
4849
vcap.release()
4950

5051

51-
def capture(idx: int = 0, show_frame: bool = True) -> bytes:
52+
def capture(idx: int = 0, show_frame: bool = True) -> dict[int, str]:
5253
"""Capture a QR code from the default video feed."""
5354
with open_video(idx) as vcap:
55+
if not vcap.isOpened():
56+
raise click.ClickException(
57+
f"Could not open video capture device index {idx}."
58+
)
59+
60+
if not show_frame:
61+
click.echo(
62+
"Capturing QR frames from camera; press Ctrl-C to abort.", err=True
63+
)
64+
5465
## set this implausibly high, until we read the keyframe (which may not be the first frame we see).
5566
n_frames = 99999999999999
5667
frames = {}
68+
display_enabled = show_frame
69+
max_consecutive_read_failures = 100
70+
consecutive_read_failures = 0
5771
while True:
5872
ret, frame = vcap.read()
73+
if not ret:
74+
consecutive_read_failures += 1
75+
if consecutive_read_failures >= max_consecutive_read_failures:
76+
raise click.ClickException(
77+
"Camera opened but no frames were received. "
78+
"Try a different --idx value and check camera permissions."
79+
)
80+
time.sleep(0.05)
81+
continue
82+
83+
consecutive_read_failures = 0
5984
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
6085
image = Image.fromarray(gray)
6186

62-
cv2.imshow("Live Capture Feed", gray)
63-
if cv2.waitKey(1) == 27: # esc to quit
64-
break
87+
if display_enabled:
88+
try:
89+
cv2.imshow("Live Capture Feed", gray)
90+
if cv2.waitKey(1) == 27: # esc to quit
91+
break
92+
except cv2.error:
93+
logging.warning(
94+
"OpenCV display backend unavailable; disabling live preview."
95+
)
96+
display_enabled = False
6597

6698
for decoded in pyzbar.decode(image):
6799
try:
@@ -149,11 +181,12 @@ def write(outfile: str, duration: int):
149181
@main.command()
150182
@click.option("--outfile", "-o", is_flag=False, required=False)
151183
@click.option("--idx", "-i", is_flag=False, type=int, default=0, required=False)
152-
def read(outfile: str, idx: int):
184+
@click.option("--show-frame/--no-show-frame", default=True)
185+
def read(outfile: str, idx: int, show_frame: bool):
153186
"""
154187
Capture QR-code encoded data from webcam. Output defaults to stdout.
155188
"""
156-
data = capture(idx)
189+
data = capture(idx, show_frame=show_frame)
157190
output = b""
158191
for idx, val in sorted(data.items()):
159192
output += bytes.fromhex(val)

0 commit comments

Comments
 (0)