見出し画像

【ゆるプロ!番外編】Webカメラでバーコードの番号を読み取る

ゆるいプログラミング講座、略して「ゆるプロ!」
これは気軽に気楽に試せるゆるーいプログラミング学習コンテンツである。今回のお題は「Webカメラでバーコードの番号を読み取る」

一言)

資産リストを作ろうと思い、前回は、GTINコードが分かれば商品名や金額を作成できないかと思い立ち、Yahoo Shopping APIよりPythonで商品名や金額の取得を試みた。今度は、GTINコードをWebカメラでバーコードから読み取ろうとした。きっかけは、ハードのバーコードリーダーを買わなくても、もしかしたらWebカメラとソフトウェア処理でどうにかなるのではないかと考えた

前提)

例)Webカメラでバーコードの番号を読み取る

import cv2
import pyautogui
import time
import pywinctl as gw

# Webカメラを立ち上げる
def read_barcode_from_webcam():

    # 対象のアプリのファイル名を取得して、アクティブにする
    text_editor_title = "対象のアプリのファイル名"
    set_text_editor_active(text_editor_title)

    # Webカメラを起動
    cap = cv2.VideoCapture(1) #0->1で強制的に変更、0がデフォルトでiPhoneのカメラに連携しだす

    # 解像度の設定
    cap.set(cv2.CAP_PROP_FRAME_WIDTH, 2560)
    cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 1600)
    # 明るさの設定
    cap.set(cv2.CAP_PROP_BRIGHTNESS, 0) 
    # コントラストの設定
    cap.set(cv2.CAP_PROP_CONTRAST, 32) 
    # サンプリングレートの設定
    cap.set(cv2.CAP_PROP_FPS, 30)

    # 待機
    time.sleep(2) 

    while True:
        # フレームを読み込む
        ret, frame = cap.read()

        resized_frame = cv2.resize(frame, (480, 272))

        # フレームを表示
        cv2.imshow('Webcam', resized_frame)

        # Qキーで終了
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break

        # バーコードの読み取り
        decoded_info = read_barcode(frame)

        # バーコードが読み取れたらキーボードに入力
        if decoded_info:
            set_text_editor_active(text_editor_title)
            write_text(decoded_info[0])

    # カメラリソースの解放
    cap.release()
    cv2.destroyAllWindows()

# バーコードの取得
def read_barcode(frame):

    # OpenCVによるバーコードリーダーを作成
    barcode_reader = cv2.barcode.BarcodeDetector("sr.prototxt", "sr.caffemodel")

    retval, decoded_info, decoded_type, points  = barcode_reader.detectAndDecodeWithType(frame)

    if retval:
        print(f'Decoded Data: {decoded_info}')
        return decoded_info
    
    return None

# テキストを書き込む関数
def write_text(text):
    print(text)

    # 待機
    time.sleep(2) 

    # テキストを入力
    pyautogui.write(text,interval=0.1)

    # 待機
    time.sleep(2) 

# 取得したWindowをアクティブにする
def set_text_editor_active(text_editor_title):
    text_editor_window = gw.getWindowsWithTitle(text_editor_title)
    if text_editor_window:
        text_editor_window[0].activate()

# メイン関数
if __name__ == "__main__":
    read_barcode_from_webcam()

結果)

思ったよりも、Webカメラで精度よくバーコードの値を読み取れてよかった

実行結果

感想

  • 最初は別なライブラリで試そうとしたが、更新されていなかったのでOpenCVなら出来るのではと思い切り替えた

  • Macでは、pygetwindowがサポートされていないので、pywinctlを使用した

  • テキストの値を書き込むのに、PyAutoGUIを使用した。timer.sleep()を加えてあげないと、高速で処理しようとするのか値が読み取りづらくなる現象が発生した

  • なお、PyAutoGUIをMacで使用するときには警告が表示されるので許可してあげること

  • iPhoneと連動しているからかWarningが出るのだが、iPhoneの電源を切り、VideoCapture(0)に指定すれば警告は出ない。しかし、流石に利便性が落ちるので1番を指定した

  • BarcodeDetector("sr.prototxt", "sr.caffemodel")のコードがあるが、sr.prototxtとsr.caffemodelをダウンロードしてくる必要があることを参考にしたブログから知った。Windowsでは必要だった

  • 画面のピクセルサイズは使用するパソコンのピクセルサイズに合わせる必要がある、MacBook Air M1は2560*1600をサポートしているので、そこから1つの画面でカメラとNumbersを表示できるようにリサイズした

  • 逆に、ピクセルサイズが低い状態からリサイズすると読み取り精度が落ちた。解像度が低かったためと思われる

  • OpenCVのバージョンは4.8なので関数は使えるか見直しは必要だった

  • なぜか、Macのカメラがちらつくのだが待っているとチラつきが収まる。facetimeは依然としてもやつく。LEDではないからか?

  • 個人のちょっとした使用で、わざわざハードのバーコードリーダーを買うのもなと思ったが、精度を気にするならばハードも検討に入れたが、結果的にある程度のクオリティで読み取るので良しとする

  • バーコードリーダーとは何だろうと興味を持つこと、もしかしたらカメラがあれば出来るのではという発想が今回の成功だったかもしれない。結果的に出費を減らせた。解決までの時間を優先したい場合は買うという選択肢はありかと思う

  • Qualityは低いかもしれないが、一旦は要件を満たせるので良しとする

課題

  • カメラが起動されない場合はあるので、何が原因かは別途調べる。基本的にはタイマーは使いたくないので原因を時間があるときに別途、探っていく

参考

参考にしたブログ

OpenCVでバーコードを読み取れるのではと思って検索したサイト

おわり!