.. _py_vision: 5. 计算机视觉 ======================= 本项目将正式进入计算机视觉领域! **运行代码** .. raw:: html .. code-block:: cd ~/picrawler/examples sudo python3 5_display.py **查看画面** 代码运行后,终端会显示如下提示: .. code-block:: No desktop ! * Serving Flask app "vilib.vilib" (lazy loading) * Environment: production WARNING: Do not use the development server in a production environment. Use a production WSGI server instead. * Debug mode: off * Running on http://0.0.0.0:9000/ (Press CTRL+C to quit) 随后,在浏览器中输入 ``http://:9000/mjpg`` 即可查看视频画面,例如: ``http://192.168.18.113:9000/mjpg`` .. image:: img/display.png 程序运行后,最后你会在终端看到以下提示信息: * 输入按键以调用对应功能! * ``q``: 拍照 * ``1``: 颜色识别:红色 * ``2``: 颜色识别:橙色 * ``3``: 颜色识别:黄色 * ``4``: 颜色识别:绿色 * ``5``: 颜色识别:蓝色 * ``6``: 颜色识别:紫色 * ``0``: 关闭颜色识别 * ``r``: 扫描二维码 * ``f``: 开/关人脸识别 * ``s``: 显示检测到的对象信息 请根据提示操作以启用对应功能。 * **拍照** 在终端输入 ``q`` 并按回车,摄像头当前画面将被保存(若颜色识别已开启,保存的照片中也会显示标记框)。照片会保存在树莓派的 ``~/Pictures/PiCrawler/`` 目录下。 你可以使用 :ref:`filezilla` 等工具将照片传输到电脑。 * **颜色识别** 输入 ``1~6`` 中的任意数字,即可识别“红、橙、黄、绿、蓝、紫”中的一种颜色;输入 ``0`` 可关闭颜色识别。 .. image:: img/DTC2.png .. note:: 你可以下载并打印 :download:`PDF 色卡 ` 以进行颜色识别。 * **人脸识别** 输入 ``f`` 开启人脸检测。 .. image:: img/DTC5.png * **二维码识别** 输入 ``r`` 开启二维码识别。在二维码识别完成前,无法执行其他操作。二维码的解码信息会打印在终端中。 .. image:: img/DTC4.png * **显示信息** 输入 ``s`` 将在终端打印人脸检测(以及颜色检测)的目标信息,包括目标的中心坐标 (X, Y) 以及大小 (宽度、高度)。 **代码** .. code-block:: python from vilib import Vilib from time import sleep, time, strftime, localtime import threading import readchar from os import getlogin USERNAME = getlogin() PICTURE_PATH = f"/home/{USERNAME}/Pictures/" flag_face = False flag_color = False qr_code_flag = False MANUAL = ''' Press a key to call the function: q: Take photo 1: Color detect : red 2: Color detect : orange 3: Color detect : yellow 4: Color detect : green 5: Color detect : blue 6: Color detect : purple 0: Switch off Color detect r: Scan the QR code (toggle) f: Switch ON/OFF face detect s: Display detected object information Ctrl+C: Quit ''' color_list = ['close', 'red', 'orange', 'yellow', 'green', 'blue', 'purple'] def face_detect(flag): print("Face Detect:", flag) Vilib.face_detect_switch(flag) def qrcode_detect(): global qr_code_flag Vilib.qrcode_detect_switch(True) print("Waiting for QR code...") text = None while qr_code_flag: temp = Vilib.detect_obj_parameter.get('qr_data', "None") if temp != "None" and temp != text: text = temp print("QR code:", text) sleep(0.2) Vilib.qrcode_detect_switch(False) def take_photo(): _time = strftime('%Y-%m-%d-%H-%M-%S', localtime(time())) name = f'photo_{_time}' Vilib.take_photo(name, PICTURE_PATH) print(f'Photo saved as {PICTURE_PATH}{name}.jpg') def object_show(): global flag_color, flag_face if flag_color: if Vilib.detect_obj_parameter.get('color_n', 0) == 0: print('Color Detect: None') else: x = Vilib.detect_obj_parameter.get('color_x') y = Vilib.detect_obj_parameter.get('color_y') w = Vilib.detect_obj_parameter.get('color_w') h = Vilib.detect_obj_parameter.get('color_h') print("[Color Detect] Coordinate:", (x, y), "Size:", (w, h)) if flag_face: if Vilib.detect_obj_parameter.get('human_n', 0) == 0: print('Face Detect: None') else: x = Vilib.detect_obj_parameter.get('human_x') y = Vilib.detect_obj_parameter.get('human_y') w = Vilib.detect_obj_parameter.get('human_w') h = Vilib.detect_obj_parameter.get('human_h') print("[Face Detect] Coordinate:", (x, y), "Size:", (w, h)) def main(): global flag_face, flag_color, qr_code_flag qrcode_thread = None Vilib.camera_start(vflip=False, hflip=False) Vilib.display(local=True, web=True) print(MANUAL) try: while True: key = readchar.readkey().lower() if key == 'q': take_photo() elif key in '0123456': index = int(key) if index == 0: flag_color = False Vilib.color_detect('close') else: flag_color = True Vilib.color_detect(color_list[index]) print('Color detect:', color_list[index]) elif key == 'f': flag_face = not flag_face face_detect(flag_face) elif key == 'r': qr_code_flag = not qr_code_flag if qr_code_flag: if qrcode_thread is None or not qrcode_thread.is_alive(): qrcode_thread = threading.Thread(target=qrcode_detect, daemon=True) qrcode_thread.start() else: print('QRcode Detect: close') elif key == 's': object_show() sleep(0.05) except KeyboardInterrupt: print("\nQuit.") finally: # Stop QR thread and switches qr_code_flag = False try: Vilib.qrcode_detect_switch(False) except Exception: pass try: Vilib.color_detect('close') except Exception: pass try: Vilib.face_detect_switch(False) except Exception: pass # Close camera try: Vilib.camera_close() except Exception: pass if __name__ == "__main__": main() **工作原理** 首先需要注意以下函数,这两个函数可以启动摄像头: .. code-block:: python Vilib.camera_start() Vilib.display() 与“目标检测”相关的函数有: * ``Vilib.face_detect_switch(True)`` : 开/关人脸检测 * ``Vilib.color_detect(color)`` : 进行颜色检测,同一时间只能检测一种颜色。可输入的参数有: ``"red"`` 、 ``"orange"`` 、 ``"yellow"`` 、 ``"green"`` 、 ``"blue"`` 、 ``"purple"`` * ``Vilib.color_detect_switch(False)`` : 关闭颜色检测 * ``Vilib.qrcode_detect_switch(False)`` : 开/关二维码检测,并返回二维码的解码数据 * ``Vilib.gesture_detect_switch(False)`` : 开/关手势检测 * ``Vilib.traffic_sign_detect_switch(False)`` : 开/关交通标志检测 目标检测到的信息会存储在 ``detect_obj_parameter = Manager().dict()`` 字典中。 在主程序中,可以这样调用: .. code-block:: python Vilib.detect_obj_parameter['color_x'] 字典中的键及其含义如下: * ``color_x``: 检测到的颜色块中心点 x 坐标,范围 0~320 * ``color_y``: 检测到的颜色块中心点 y 坐标,范围 0~240 * ``color_w``: 检测到的颜色块宽度,范围 0~320 * ``color_h``: 检测到的颜色块高度,范围 0~240 * ``color_n``: 检测到的颜色块数量 * ``human_x``: 检测到的人脸中心点 x 坐标,范围 0~320 * ``human_y``: 检测到的人脸中心点 y 坐标,范围 0~240 * ``human_w``: 检测到的人脸宽度,范围 0~320 * ``human_h``: 检测到的人脸高度,范围 0~240 * ``human_n``: 检测到的人脸数量 * ``traffic_sign_x``: 检测到的交通标志中心点 x 坐标,范围 0~320 * ``traffic_sign_y``: 检测到的交通标志中心点 y 坐标,范围 0~240 * ``traffic_sign_w``: 检测到的交通标志宽度,范围 0~320 * ``traffic_sign_h``: 检测到的交通标志高度,范围 0~320 * ``traffic_sign_t``: 检测到的交通标志内容,可选值为 `['stop','right','left','forward']` * ``gesture_x``: 检测到的手势中心点 x 坐标,范围 0~320 * ``gesture_y``: 检测到的手势中心点 y 坐标,范围 0~240 * ``gesture_w``: 检测到的手势宽度,范围 0~320 * ``gesture_h``: 检测到的手势高度,范围 0~320 * ``gesture_t``: 检测到的手势内容,可选值为 `["paper","scissor","rock"]` * ``qr_date``: 检测到的二维码内容 * ``qr_x``: 检测到的二维码中心点 x 坐标,范围 0~320 * ``qr_y``: 检测到的二维码中心点 y 坐标,范围 0~240 * ``qr_w``: 检测到的二维码宽度,范围 0~320 * ``qr_h``: 检测到的二维码高度,范围 0~240