セキュリティは常に人類の主要な関心事でした。今日、私たちは学校、病院、その他すべての公共の場所にビデオ監視カメラを設置して、安心感を与えています。HISの調査によると、2014年には約2億4500万台の防犯カメラが設置され、機能していたと推定されています。これは、この地球上の30人に1台の防犯カメラがあるようなものです。特に画像処理と機械学習の技術の進歩により、ビデオフィードからの情報を処理するようにトレーニングすることで、これらのカメラをよりスマートにすることができます。
これらのカメラからのビデオフィードを使用して、顔認識、パターン分析、感情分析などを実行できます。これにより、FF7ムービーに示されている「神の目」のようなものに実際に近づくことができます。実際、Hikvisionや他の多くの監視会社は、すでにこれらの機能を自社製品に実装し始めています。以前はMATLAB画像処理を使用してナンバープレートを読み取りましたが、本日この記事では、RaspberryPiとOpenCVを使用して自動車からナンバープレート番号を認識して読み取る方法を学習します。Googleのランダムな車両画像を使用し、OpenCV輪郭検出を使用してナンバープレートを認識するプログラムを作成し、TesseractOCRを使用してナンバープレートから番号を読み取ります。面白そうですね!だから始めましょう。
前提条件
前に述べたように、OpenCVライブラリを使用して顔を検出および認識します。したがって、このチュートリアルに進む前に、必ずRaspberryPiにOpenCVライブラリをインストールしてください。また、2AアダプターでPiに電力を供給し、デバッグを容易にするためにディスプレイモニターに接続します。
このチュートリアルでは、OpenCVがどのように機能するかについては説明しません。画像処理の学習に興味がある場合は、このOpenCVの基本と高度な画像処理チュートリアルを確認してください。OpenCVを使用したこの画像セグメンテーションチュートリアルでは、輪郭、ブロブ検出などについても学ぶことができます。これと同様のことをして、画像から車のナンバープレートを検出します。
RaspberryPiを使用したナンバープレート認識に関連する手順
ナンバープレート認識または略してLPRには、3つの主要なステップが含まれます。手順は次のとおりです
1.ナンバープレートの検出:最初のステップは、車からナンバープレートを検出することです。OpenCVの輪郭オプションを使用して長方形のオブジェクトを検出し、ナンバープレートを見つけます。ナンバープレートの正確なサイズ、色、おおよその位置がわかれば、精度を向上させることができます。通常、検出アルゴリズムは、その特定の国で使用されているカメラの位置とナンバープレートのタイプに基づいてトレーニングされます。画像に車がない場合、これはさらに複雑になります。この場合、車を検出してからナンバープレートを検出するための追加の手順を実行します。
2.文字のセグメンテーション:ナンバープレートを検出したら、それを切り取って新しい画像として保存する必要があります。繰り返しますが、これはOpenCVを使用して簡単に行うことができます。
3. 文字認識:これで、前の手順で取得した新しい画像には、必ずいくつかの文字(数字/アルファベット)が書き込まれています。そのため、OCR(光学式文字認識)を実行して番号を検出できます。Raspberry Piを使用した光学式文字認識(OCR)についてはすでに説明しました。
1.ナンバープレートの検出
このRaspberryPiナンバープレートリーダーの最初のステップは、ナンバープレートを検出することです。車のサンプル画像を撮り、その車のナンバープレートを検出することから始めましょう。次に、同じ画像を文字セグメンテーションと文字認識にも使用します。説明なしでコードに直接ジャンプしたい場合は、このページの一番下までスクロールして、完全なコードが提供されています。このチュートリアルで使用しているテストイメージを以下に示します。
手順1: 画像のサイズを必要なサイズに変更してから、グレースケールします。同じためのコードを以下に示します
img = cv2.resize(img、(620,480)) gray = cv2.cvtColor(img、cv2.COLOR_BGR2GRAY)#グレースケールに変換
サイズ変更は、より大きな解像度の画像での問題を回避するのに役立ちます。サイズ変更後もナンバープレートがフレーム内に残っていることを確認してください。グレースケーリングは、すべての画像処理ステップで共通です。これにより、画像を処理するときに色の詳細を処理する必要がなくなる、他の後続のプロセスサインが高速化されます。この手順を実行すると、画像は次のように変換されます。
ステップ2:すべての画像には有用で役に立たない情報が含まれます。この場合、ナンバープレートだけが有用な情報であり、残りはプログラムにとってほとんど役に立たないものです。この役に立たない情報はノイズと呼ばれます。通常、バイラテラルフィルター(ぼかし)を使用すると、画像から不要な詳細が削除されます。同じためのコードは
灰色= cv2.bilateralFilter(灰色、11、17、17)
構文は destination_image = cv2.bilateralFilter(source_image、ピクセルの直径、sigmaColor、sigmaSpace)です。 シグマカラーとシグマスペースを17からより高い値に増やして、より多くの背景情報をぼかすことができますが、有用な部分がぼやけないように注意してください。この画像では背景の詳細(木と建物)がぼやけていることがわかるため、出力画像を以下に示します。このようにして、プログラムが後でこれらの地域に集中するのを防ぐことができます。
ステップ3:次のステップは、エッジ検出を実行する興味深いものです。それを行うには多くの方法がありますが、最も簡単で一般的な方法は、OpenCVのキャニーエッジ方式を使用することです。同じことをするための行を以下に示します
edged = cv2.Canny(gray、30、200)#エッジ検出を実行します
構文は destination_image = cv2.Canny(source_image、thresholdValue 1、thresholdValue 2)になります。 しきい値値1としきい値2は、最小しきい値と最大しきい値です。最小しきい値より大きく、最大しきい値より小さい強度勾配を持つエッジのみが表示されます。結果の画像を以下に示します
ステップ4:これで、画像の輪郭を探し始めることができます。前のチュートリアルでOpenCVを使用して輪郭を見つける方法についてはすでに学習しているので、同じように進めます。
nts = cv2.findContours(edged.copy()、cv2.RETR_TREE、cv2.CHAIN_APPROX_SIMPLE) cnts = imutils.grab_contours(cnts) cnts = sorted(cnts、key = cv2.contourArea、reverse = True) screenCnt = None
カウンターが検出されたら、それらを大きいものから小さいものに並べ替え、最初の10個の結果のみを考慮して他の結果を無視します。私たちの画像では、カウンターは閉じた表面を持つものであれば何でもかまいませんが、得られたすべての結果の中で、ナンバープレート番号も閉じた表面であるためそこにあります。
得られた結果の中からナンバープレートの画像をフィルタリングするために、すべての結果をループして、4辺が閉じた長方形の輪郭を持っているかどうかを確認します。ナンバープレートは間違いなく長方形の4面図になるので。
#cnts内のcの 等高線をループします:#等高線を近似します peri = cv2.arcLength(c、True) 概算= cv2.approxPolyDP(c、0.018 *ペリ、True) #近似した等高線に4つの点がある場合、 # len(approx)== 4の場合 、画面が見つかったと見なすことができます。screenCnt=約 break
値0.018は実験値です。あなたはそれをいじって、どれがあなたにとって最もうまくいくかをチェックすることができます。または、機械学習を使用して車の画像に基づいてトレーニングし、そこで適切な値を使用して、次のレベルに引き上げます。正しいカウンターが見つかったら、それを screenCnt という変数に保存し、その周りに長方形のボックスを描画して、ナンバープレートが正しく検出されたことを確認します。
ステップ5:ナンバープレートがどこにあるかがわかったので、残りの情報はほとんど役に立ちません。したがって、ナンバープレートがある場所を除いて、画像全体をマスキングすることができます。同じことを行うためのコードを以下に示します
#ナンバープレート以外の部分のマスキング mask = np.zeros(gray.shape、np.uint8) new_image = cv2.drawContours(mask,, 0,255、-1) new_image = cv2.bitwise_and(img、img、mask =マスク)
マスクされた新しい画像は次のように表示されます
2.文字セグメンテーション
Raspberry Piナンバープレート認識の次のステップは、ナンバープレートをトリミングして新しい画像として保存することにより、画像からナンバープレートをセグメント化することです。次に、この画像を使用して、その中の文字を検出できます。メイン画像からroi(関心領域)画像を切り抜くためのコードを以下に示します。
#ここで、crop (x、y)= np.where(mask == 255) (topx、topy)=(np.min(x)、np.min(y)) (bottomx、bottomy)=(np.max( x)、np.max(y))トリミング =グレー
結果の画像を以下に示します。通常、画像のトリミングに追加されますが、必要に応じて画像をグレー表示してエッジすることもできます。これは、次のステップで文字認識を改善するために行われます。しかし、元の画像でも問題なく動作することがわかりました。
3.文字認識
このラズベリーパイナンバープレート認識の最後のステップは、セグメント化された画像からナンバープレート情報を実際に読み取ることです。前のチュートリアルで行ったように、 pytesseract パッケージを使用して画像から文字を読み取ります。同じためのコードを以下に示します
#ナンバープレートの テキストを読む= pytesseract.image_to_string(Cropped、config = '-psm 11') print( "Detected Number is:"、text)
Tesseractエンジンの構成方法についてはすでに説明したので、ここでも必要に応じてTesseract OCRを構成して、必要に応じてより良い結果を得ることができます。検出された文字は、コンソールに出力されます。コンパイルすると、結果は次のように表示されます
ご覧のとおり、元の画像には「HR 25 BR9044」という番号が付いており、プログラムは同じ値を画面に印刷したことを検出しました。
ナンバープレート認識の失敗事例
このRaspberryPiナンバープレート認識の完全なプロジェクトファイルは、ここからダウンロードできます。このファイルには、プログラムと、プログラムのチェックに使用したテスト画像が含まれています。言うまでもなく、この方法の結果は正確ではないことに注意してください。精度は、画像の鮮明さ、向き、露出などに依存します。より良い結果を得るには、これと一緒に機械学習アルゴリズムを実装してみてください。
アイデアを得るために、車がカメラに直接向いていない別の例を見てみましょう。
ご覧のとおり、私たちのプログラムはナンバープレートを正しく検出してトリミングすることができました。しかし、 Tesseract ライブラリは文字を正しく認識できませんでした。実際の「TS08UE 3396」の代わりに、OCRはそれを「1508ye3396」として認識しました。このような問題は、より適切な方向の画像を使用するか、 Tesseract エンジンを構成することで修正できます。
もう1つの最悪のシナリオは、輪郭がナンバープレートを正しく検出できない場合です。下の画像には、背景情報が多すぎて照明が悪いため、プログラムは番号からナンバープレートを識別できませんでした。この場合、機械学習を再度中継するか、画像の品質を向上させる必要があります。
その他の成功例
ほとんどの場合、画質と向きは正しいので、プログラムはナンバープレートを識別し、そこから番号を読み取ることができました。以下のスナップショットは、得られた成功した結果のいくつかを示しています。ここでも、ここで使用されているすべてのテストイメージとコードは、ここで提供されているZIPファイルで入手できます。
Raspberry Piを使用した自動ナンバープレート認識を理解し、自分でクールなものを作成することを楽しんだことを願っています。OpenCVとTesseractで他に何ができると思いますか?コメントセクションであなたの考えを教えてください。この記事に関して質問がある場合は、下のコメントセクションに残しておくか、フォーラムを使用して他の技術的な質問をしてください。