「Streamlitを使用してナンバープレート認識アプリを作成する」

「美容とファッションの専門家がおすすめする鮮やかなアイテム」(A recommendation from a beauty and fashion expert Vibrant items)

要約

この記事では、事前学習済みモデルを使用して可変行数のナンバープレートからテキストを抽出する解決策を簡単に説明し、この解決策をユーザーに提供するためにStreamlitを使用してWebアプリを構築する手順を詳しく説明します。

Streamlitは、機械学習やデータサイエンスのプロジェクトに特化したオープンソースのアプリフレームワークです。

対象読者

  • HTML、CSS、JSを学ぶには人生が短すぎると思っているが、Web開発を学びたいデータサイエンティスト。
  • Pythonのコードを共有可能なWebアプリに変えたいと考えている機械学習エンジニア志望者。

アウトライン

  1. カメラに最も近いナンバープレートを検出する。
  2. easyocrまたはtesseractを使用してテキストを抽出する。
  3. 画像を入力として受け取り、文字列を出力するアプリを構築する。

問題の設定

カメラから撮影された変角度、距離、照明条件の異なる1つまたは複数の車両の2D画像が与えられた場合、カメラに最も近い車両のナンバープレート番号を抽出したいとします。すべてのナンバープレートはシンガポールのものであり、英字と数字で構成されており、可変長の1行または2行です。

出典:Executive Travellerで公開された「シンガポールでタクシーに乗るための便利なガイド」
  1. カメラに最も近いナンバープレートを検出する

データがないため、微調整なしで事前学習済みのyolov5モデルを使用します。以下がコードです:

import yolov5import torchdef inference(    path2img: str,    show_img: bool = False,    size_img: int = 640,    nms_conf_thresh: float = 0.7,    max_detect: int = 10,) -> torch.Tensor:    model = yolov5.load("keremberke/yolov5m-license-plate")    model.conf = nms_conf_thresh    model.iou = 0.45    model.agnostic = False    model.multi_label = False    model.max_det = max_detect    results = model(path2img, size=size_img)    results = model(path2img, augment=True)    if show_img:        results.show()    return results.pred[0]

1つのバウンディングボックスだけでなく、複数のバウンディングボックスを直接取得するためにmax_detectを1に設定しないのはなぜか疑問に思うかもしれません。その理由は、予測されたすべてのバウンディングボックスには信頼スコアがあるためです。max_detect = 1とすると、最も自信のある予測を得ることができますが、それが常にカメラに最も近いナンバープレートであるとは限りません。

事前学習済みyolov5モデルを使用してすべてのナンバープレートを検出します。

そのため、予測されたすべてのバウンディングボックスの面積を計算し、最も面積が大きいものを保持する必要があります。これにより、信頼度が低い場合でも、カメラに最も近いナンバープレートが常に得られます。

カメラに最も近いナンバープレートを取得します。

2. easyocrまたはtesseractを使用してテキストを抽出する。

もしもあなたのナンバープレートが固定長で単一行の場合、tesseractはほぼ十分です。ただし、私の経験からは、数字の9と文字のZ、そして時折Dに対して性能が低いです。

以下に私のコードを貼り付けました。もしもあなたのナンバープレートに英語以外の文字が含まれている場合は、tessedit_char_whitelistlangを適切に変更してください。

import pytesseractdef ocr_tesseract(path2img):    text = pytesseract.image_to_string(        path2img,        lang="eng",        config="--oem 3 --psm 6 -c tessedit_char_whitelist=ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",    )    return text

この一行のナンバープレートは正常に認識できますが、下の画像の2行目をtesseractは抽出できません。

Source: Toyota Wish Taxi in Singapore 23.9.2017 2926 taken by Elmar

この赤いタクシーのナンバープレートはD9Zを含んでいるためtesseractにとってかなり困難です。代わりにeasyocrを試してみましょう!

easyocr detection output

困難な部分もありますが、easyocr5を除いてほとんどの文字を正常に認識しました! tesseractよりもeasyocrをお勧めします。以下に私のコードを示します。

def ocr_easyocr(path2img):    image = cv2.imread(path2img)    reader = easyocr.Reader(["en"], gpu=False)    detections = reader.readtext(image)    plate_no = []    [plate_no.append(line[1]) for line in detections]    return "".join(plate_no)

3. 画像を入力として受け取り、文字列を出力するアプリを作成する

最もエキサイティングな部分がやってきました!

私たちが作成したものを使って利用者が利用できるようにするには、画像をアップロードしてデコードされたナンバープレートの文字列を読み取るためのウェブアプリケーションが必要です。

より詳細に分解してみましょう:

  • 3.1 タイトルとサブタイトルを表示する
  • 3.2 利用者が画像をアップロードするためのファイルアップローダーを表示する
  • 3.3 認識されたナンバープレートの数字をテキストとして出力する
  • 3.4 アップロードされた画像を予測されたバウンディングボックスとともに表示する

3.1 タイトルとサブタイトルを表示する

まず、streamlitをインストールします。ターミナルでpip install streamlitを実行します。

次に、ターミナルでstreamlit helloを実行してStreamlit UIを開きます。

UIがデフォルトのブラウザに表示されます。デモを楽しんでください!

3.2 利用者が画像をアップロードするためのファイルアップローダーを表示する

次に、私はsrc/にPythonスクリプトを作成し、その名前をapp.pyとしました。

import streamlit as stdef app():    st.header("License Plate Recognition Web App")    st.subheader("Powered by YOLOv5")    st.write("Welcome!")if __name__ == "__main__":    app()

その後、ターミナルでstreamlit run src/app.pyというコマンドを実行しました。

`streamlit run <path>’を実行してWebアプリの変更を確認します。

ウェブページを更新すると、タイトルとサブタイトルが表示されます!HTMLの文法は全く必要ありません!

streamlitウェブアプリにタイトルが表示されました。

さらにウィジェットを追加しましょう!ユーザーがクリックするためのボタンを持つファイルアップローダーが欲しいです。新しいapp関数は以下の通りです。

def app():    st.header("ナンバープレート認識ウェブアプリ")    st.subheader("YOLOv5によるパワード")    st.write("ようこそ!")    # ファイルアップローダーを追加    with st.form("my_uploader"):        uploaded_file = st.file_uploader(            "画像をアップロード", type=["png", "jpg", "jpeg"], accept_multiple_files=False        )        submit = st.form_submit_button(label="アップロード")

再びstreamlit runコマンドを実行すると、ファイルアップローダーが表示されます。CSSのスタイリングは必要ありません。

ファイルアップローダーが追加されました。

3.3 テキスト出力として認識されたナンバープレート番号を表示する

ユーザーが画像をアップロードすると(トリガー:アップロードボタンをクリックする)、関連するPython関数を使用して推論を行えます。ナンバープレート番号はテキストとして表示されます。

def app():    st.header("ナンバープレート認識ウェブアプリ")    st.subheader("YOLOv5によるパワード")    st.write("ようこそ!")    with st.form("my_uploader"):        uploaded_file = st.file_uploader(            "画像をアップロード", type=["png", "jpg", "jpeg"], accept_multiple_files=False        )        submit = st.form_submit_button(label="アップロード")    if uploaded_file is not None:        # アップロードされた画像を保存        save_path = os.path.join("temp", uploaded_file.name)        with open(save_path, "wb") as f:            f.write(uploaded_file.getbuffer())    if submit:        # ナンバープレートをテキストとして表示        text = run_license_plate_recognition(save_path).recognize_text()        st.write(f"検出されたナンバープレート番号:{text}")if __name__ == "__main__":    app()
抽出されたナンバープレート番号をテキストとして表示します。

3.4 アップロードされた画像と予測されたバウンディングボックスを表示する

ウェブアプリに入力と出力があるとはいえ、それだけでは不十分です。ユーザーがアップロードした画像をバウンディングボックスとともに表示できればさらに良いでしょう。小さなウィジェットを追加することで、ユーザーに予測が正しい車両に対してなされていることを保証できます。特に予測が完璧でない場合、ユーザーは矛盾をより簡単に理解できるでしょう。

出典: Dinesh Dayaniによる『Complete Guide To Singapore Taxi Flag Down Rates And Fares』

よりインタラクティブにするために、リクエスト処理中にスピナーを追加します。

スピナーが追加されました。

検出が完了すると、画像が以下に表示されます。

ナンバープレート認識ウェブアプリはいい感じです!

Djangoを使用した後、私は本当にStreamlitを高く評価しています。後者はデータサイエンティストが一日でマスターできるものではありません。Streamlitは、フロントエンドのウェブ開発の最小限の知識で、データサイエンティストが作業に集中することができるまま、解決策をユーザーに展開することができます。

コードリポジトリを表示するには、このリンクをクリックしてください。

LinkedInで私をフォローする | 👏🏽 for my story | VoAGIで私をフォローする

We will continue to update VoAGI; if you have any questions or suggestions, please contact us!

Share:

Was this article helpful?

93 out of 132 found this helpful

Discover more