「Streamlitを使用してナンバープレート認識アプリを作成する」
「美容とファッションの専門家がおすすめする鮮やかなアイテム」(A recommendation from a beauty and fashion expert Vibrant items)
要約
この記事では、事前学習済みモデルを使用して可変行数のナンバープレートからテキストを抽出する解決策を簡単に説明し、この解決策をユーザーに提供するためにStreamlitを使用してWebアプリを構築する手順を詳しく説明します。
Streamlitは、機械学習やデータサイエンスのプロジェクトに特化したオープンソースのアプリフレームワークです。
対象読者
- HTML、CSS、JSを学ぶには人生が短すぎると思っているが、Web開発を学びたいデータサイエンティスト。
- Pythonのコードを共有可能なWebアプリに変えたいと考えている機械学習エンジニア志望者。
アウトライン
- カメラに最も近いナンバープレートを検出する。
easyocr
またはtesseract
を使用してテキストを抽出する。- 画像を入力として受け取り、文字列を出力するアプリを構築する。
問題の設定
カメラから撮影された変角度、距離、照明条件の異なる1つまたは複数の車両の2D画像が与えられた場合、カメラに最も近い車両のナンバープレート番号を抽出したいとします。すべてのナンバープレートはシンガポールのものであり、英字と数字で構成されており、可変長の1行または2行です。

- カメラに最も近いナンバープレートを検出する
データがないため、微調整なしで事前学習済みの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
とすると、最も自信のある予測を得ることができますが、それが常にカメラに最も近いナンバープレートであるとは限りません。

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

2. easyocr
またはtesseract
を使用してテキストを抽出する。
もしもあなたのナンバープレートが固定長で単一行の場合、tesseract
はほぼ十分です。ただし、私の経験からは、数字の9
と文字のZ
、そして時折D
に対して性能が低いです。
以下に私のコードを貼り付けました。もしもあなたのナンバープレートに英語以外の文字が含まれている場合は、tessedit_char_whitelist
とlang
を適切に変更してください。
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
は抽出できません。

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

困難な部分もありますが、easyocr
は5
を除いてほとんどの文字を正常に認識しました! 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
というコマンドを実行しました。

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

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

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

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

Djangoを使用した後、私は本当にStreamlitを高く評価しています。後者はデータサイエンティストが一日でマスターできるものではありません。Streamlitは、フロントエンドのウェブ開発の最小限の知識で、データサイエンティストが作業に集中することができるまま、解決策をユーザーに展開することができます。
コードリポジトリを表示するには、このリンクをクリックしてください。
LinkedInで私をフォローする | 👏🏽 for my story | VoAGIで私をフォローする
We will continue to update VoAGI; if you have any questions or suggestions, please contact us!
Was this article helpful?
93 out of 132 found this helpful
Related articles