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