PythonでパソコンのスクリーンショットからQRコードを読み込む。(バーコードも読めます)

Python

パソコンのスクリーンショットからQRコードを読み込むには?

ブラウザに表示されたQRコードやバーコードを読み込みしたいときはありませんか?

業務プログラムを作成していると、コードを埋め込んだ帳票のプレビューを行い動作確認を行う場合があり、コードリーダーやスマートフォンでコードを読み込みしてコードが正しいか確認する必要がありますが、わざわざ用意することが面倒という場合があります。

    本記事ではスクリーンショットした画像からQRコードやバーコードを読み込みするアプリを紹介します。

    プログラムは苦手だからexeファイルが欲しいという方は本ページの「最後に」を参照ください。

    パソコンのスクリーンショットからQRコードを読み込みするサンプルコード

    サンプルコードを紹介します。

    # tkinter: GUIアプリケーション作成用の標準ライブラリ。
    import tkinter as tk
    # tkinter.messagebox: ポップアップメッセージボックスを表示するためのモジュール。
    from tkinter import messagebox
    
    # pip install pyzbar
    # pyzbar: バーコードおよびQRコードを読み取るためのライブラリ。
    import pyzbar.pyzbar as pyzbar
    
    # pip install Pillow
    # PIL: Python Imaging Library、画像処理を行うためのライブラリ。
    from PIL import Image, ImageGrab, ImageTk
    
    # pip install clipboard
    # clipboard: クリップボード操作を行うためのライブラリ。
    import clipboard
    
    # threading: マルチスレッド処理を可能にするモジュール。
    from threading import Thread
    
    # time: 時間に関連する関数を提供するモジュール。
    import time
    
    # pip install pyautogui
    # pyautogui: GUI操作を自動化するためのライブラリ。
    import pyautogui
    
    
    
    def launch_screenshot_tool():
        """
        スクリーンショット取得ツールを起動する関数。
        キーボードショートカット[shift]+[windows]+[s]をシミュレートして、スクリーンショットツールを起動します。
        """
        
        # [shift]+[windows]+[s]キーを送りSnipping Toolを起動
        pyautogui.hotkey('shift', 'win', 's')
    
    
    def read_codes_from_clipboard(image):
        """
        与えられた画像からバーコードまたはQRコードを読み取り、デコードする関数。
        引数:
            image (Image): PIL Image オブジェクト。
        戻り値:
            list: 読み取ったコードのデータを含むリスト。コードがなければ空のリストを返します。
        """
        try:
            codes = pyzbar.decode(image)
            return [code.data.decode('utf-8') for code in codes]
        except Exception as e:
            messagebox.showerror("エラー", f"エラーが発生しました: {e}")
            return []
    
    
    def update_codes_display():
        """
        クリップボードを定期的に監視し、新しい画像がある場合はその画像からコードを読み取り、
        テキストボックスに表示する関数。また、画像をGUIのキャンバスに表示します。
        """
        while not exit_flag:
            try:
                img = ImageGrab.grabclipboard()
                if img and isinstance(img, Image.Image):  # imgがPIL Imageオブジェクトであることを確認
                    # キャンバスサイズに応じて画像を縮小して表示
                    canvas_width, canvas_height = canvas.winfo_width(), canvas.winfo_height()
                    img_width, img_height = img.size
                    scale = min(canvas_width / img_width, canvas_height / img_height)
                    if scale < 1:
                        img = img.resize((int(img_width * scale), int(img_height * scale)))
    
                    # キャンバスに画像配置
                    photo = ImageTk.PhotoImage(img)
                    canvas.create_image(10, 10, image=photo, anchor=tk.NW) # 左上から10ピクセル右、10ピクセル下の位置に画像配置
                    canvas.image = photo  # イメージオブジェクトを保持
    
                    # 画像からバーコードやQRコードを読み込み
                    codes = read_codes_from_clipboard(img)
                    if codes:
                        codes_text = '\n'.join(reversed(codes))
                        txt_codes.delete('1.0', tk.END)
                        txt_codes.insert(tk.END, codes_text)
    
                time.sleep(2)  # 2秒間隔でクリップボードを監視
            except Exception as e:
                messagebox.showerror("エラー", f"エラーが発生しました: {e}")
    
    
    
    def copy_clipboard(text):
        """
        指定されたテキストをクリップボードにコピーする関数。
        引数:
            text (str): クリップボードにコピーするテキスト。
        """
        clipboard.copy(text)
    
    
    def copy_button_on_click():
        """
        「クリップボードにコピー」ボタンがクリックされた際の処理
        テキストボックスの内容をクリップボードにコピーし、成功メッセージを表示します。
        """
        text = txt_codes.get('1.0', tk.END).strip()
        if text:
            copy_clipboard(text)
            messagebox.showinfo("成功", "コードがクリップボードにコピーされました。")
    
    
    def exit_button_on_click():
        """
        「終了」ボタンがクリックされた際の処理
        アプリケーションを終了させるため、フラグを立ててGUIを破棄します。
        """
        global exit_flag
        exit_flag = True
        root.destroy()
    
    
    
    
    
    
    # TKinter GUIの初期設定
    root = tk.Tk()
    root.title("コードリーダー")
    
    clipboard.copy('')  # 起動時にクリップボードをクリア
    
    # GUI要素の設定
    canvas = tk.Canvas(root, width=600, height=400)
    canvas.pack()
    
    # 読み取ったコードの表示
    txt_codes = tk.Text(root, height=10, width=80)
    txt_codes.pack(pady=10)
    
    frame_buttons = tk.Frame(root)
    frame_buttons.pack(anchor='e')
    
    # Snipping Toolを起動ボタン
    btn_screen_shot = tk.Button(frame_buttons, text="Snipping Toolを起動", command=launch_screenshot_tool)
    btn_screen_shot.pack(side='left', padx=5)
    
    # テキストをクリップボードにコピーボタン
    btn_copy = tk.Button(frame_buttons, text="テキストをクリップボードにコピー", command=copy_button_on_click)
    btn_copy.pack(side='left', padx=5)
    
    # コードリーダーを終了ボタン
    btn_exit = tk.Button(frame_buttons, text="コードリーダーを終了", command=exit_button_on_click)
    btn_exit.pack(side='left')
    
    # スレッドと終了フラグの設定
    exit_flag = False
    thread = Thread(target=update_codes_display)
    thread.start()
    
    # メインループを開始
    root.mainloop()
    
    

    事前準備として
    ・バーコードやQRコードを読み取りするpyzbar
    ・画像処理を行うためのPillow
    ・クリップボードを操作するclipboard
    ・GUI操作を自動化するpyautogui
    を使用していますので事前に以下を参照してインストールしてください。

    pip install pyzbar 
    pip install Pillow
    pip install clipboard
    pip install pyautogui

    実行結果

    実行すると次のような画面が表示されます。
    ※説明用で一度画像をスクリーンショットした後の画面となっています。

    Snipping Toolを起動ボタンを押下して以下画像をスクリーンショットでとってみるとコード読み込みができると思います。

    2つのコードを読み取りした例

    スクリーンショットした結果コードとして認識できた分を読み込みします。
    ※画像が小さいとコードとして判定ができず読み込みできないので、複数一気に読み込みする場合には限界があるようです。

    最後に

    以上がPythonを利用してパソコンのカメラでQRコードやバーコードを読み込みする方法です。

    読み込みすることで省力化となる業務がかなりあると思いますので、興味のある方は試してみてはいかがでしょうか。

    また本プログラムのexeファイルもダウンロードできますので動作確認してみたい方は活用ください。
    ※zipファイルで圧縮されています。

    libiconv.dllとlibzbar-64.dllをプログラム(screenshot_code_reader.exe)と同じフォルダにおいてください。

    実行時に「WindowsによってPCが保護されました」と表示される場合にはこちらを参照ください。

    コメント

    タイトルとURLをコピーしました