pizda bochku
This commit is contained in:
@@ -0,0 +1,42 @@
|
|||||||
|
# QR/Barcode Scanner
|
||||||
|
|
||||||
|
Считыватель QR-кодов и штрихкодов на базе **pyzbar** + **OpenCV** для **Raspberry Pi Camera Module v3**.
|
||||||
|
|
||||||
|
## Зависимости
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt install libzbar0 libgstreamer1.0-dev
|
||||||
|
pip install opencv-python pyzbar
|
||||||
|
```
|
||||||
|
|
||||||
|
## Запуск
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python scanner.py
|
||||||
|
```
|
||||||
|
|
||||||
|
## Поддерживаемые форматы
|
||||||
|
|
||||||
|
- QR-код
|
||||||
|
- Code 128, Code 39, EAN-13, EAN-8
|
||||||
|
- UPC-A, UPC-E
|
||||||
|
- Interleaved 2 of 5
|
||||||
|
- И другие форматы, поддерживаемые `pyzbar`
|
||||||
|
|
||||||
|
## Управление
|
||||||
|
|
||||||
|
| Клавиша | Действие |
|
||||||
|
|---------|-----------------------------------|
|
||||||
|
| `q` | Выход |
|
||||||
|
| `r` | Сброс списка отсканированных кодов|
|
||||||
|
|
||||||
|
## Как работает
|
||||||
|
|
||||||
|
1. Подключение камеры через GStreamer (`libcamerasrc`) — родной путь для Camera Module v3
|
||||||
|
2. Каждый кадр конвертируется в градации серого и передаётся в `pyzbar.decode()`
|
||||||
|
3. Найденные коды обводятся зелёной рамкой, данные выводятся в консоль и на экран
|
||||||
|
4. Дубликаты фильтруются — каждый уникальный код выводится один раз (до сброса)
|
||||||
|
|
||||||
|
## Fallback
|
||||||
|
|
||||||
|
Если GStreamer-пайплайн недоступен, скрипт автоматически пробует открыть камеру через `/dev/video0` (V4L2).
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""QR/Barcode scanner using pyzbar + OpenCV for Raspberry Pi Camera Module v3."""
|
||||||
|
|
||||||
|
import cv2
|
||||||
|
from pyzbar import pyzbar
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
# Camera Module v3 uses libcamera (not V4L2 by default)
|
||||||
|
# GStreamer pipeline for libcamera
|
||||||
|
gst_pipeline = (
|
||||||
|
"libcamerasrc ! "
|
||||||
|
"video/x-raw, format=NV12, width=1280, height=960 ! "
|
||||||
|
"videoconvert ! "
|
||||||
|
"video/x-raw, format=BGR ! "
|
||||||
|
"appsink"
|
||||||
|
)
|
||||||
|
|
||||||
|
cap = cv2.VideoCapture(gst_pipeline, cv2.CAP_GSTREAMER)
|
||||||
|
|
||||||
|
if not cap.isOpened():
|
||||||
|
# Fallback: try V4L2 if libcamera pipeline fails
|
||||||
|
print("GStreamer pipeline failed, trying /dev/video0...")
|
||||||
|
cap = cv2.VideoCapture(0)
|
||||||
|
if not cap.isOpened():
|
||||||
|
print("Error: Cannot open camera")
|
||||||
|
return
|
||||||
|
|
||||||
|
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
|
||||||
|
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 960)
|
||||||
|
|
||||||
|
scanned_codes = set()
|
||||||
|
|
||||||
|
print("Scanner running. Press 'q' to quit, 'r' to reset scanned codes.")
|
||||||
|
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
ret, frame = cap.read()
|
||||||
|
if not ret:
|
||||||
|
print("Failed to grab frame")
|
||||||
|
break
|
||||||
|
|
||||||
|
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
|
||||||
|
codes = pyzbar.decode(gray)
|
||||||
|
|
||||||
|
for code in codes:
|
||||||
|
data = code.data.decode("utf-8")
|
||||||
|
code_type = code.type
|
||||||
|
|
||||||
|
if data not in scanned_codes:
|
||||||
|
scanned_codes.add(data)
|
||||||
|
print(f"[{code_type}] {data} (total unique: {len(scanned_codes)})")
|
||||||
|
|
||||||
|
# Draw bounding box
|
||||||
|
points = code.polygon
|
||||||
|
if len(points) == 4:
|
||||||
|
pts = [(p.x, p.y) for p in points]
|
||||||
|
for i in range(4):
|
||||||
|
cv2.line(frame, pts[i], pts[(i + 1) % 4], (0, 255, 0), 3)
|
||||||
|
|
||||||
|
# Draw data label
|
||||||
|
cv2.putText(
|
||||||
|
frame,
|
||||||
|
data[:40],
|
||||||
|
(points[0].x, points[0].y - 10),
|
||||||
|
cv2.FONT_HERSHEY_SIMPLEX,
|
||||||
|
0.5,
|
||||||
|
(0, 255, 0),
|
||||||
|
2,
|
||||||
|
)
|
||||||
|
|
||||||
|
cv2.imshow("Scanner", frame)
|
||||||
|
|
||||||
|
key = cv2.waitKey(1) & 0xFF
|
||||||
|
if key == ord("q"):
|
||||||
|
break
|
||||||
|
elif key == ord("r"):
|
||||||
|
scanned_codes.clear()
|
||||||
|
print("Scanned codes reset.")
|
||||||
|
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
pass
|
||||||
|
finally:
|
||||||
|
cap.release()
|
||||||
|
cv2.destroyAllWindows()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user