パスポート画像の機械可読ゾーンの検出
今日のブログ記事は、PyImageSearchの達人のメンバー、ハンス-ブーンなしでは不可能でしょう。 Hansは、上の画像で検出された領域と同じように、passport画像の機械可読ゾーン(Mrz)を自動的に検出するコンピュータビジョンプロジェクトに取り組んでいます。
パスポートまたは旅行カードのMRZ地域は、タイプ1とタイプ3の二つのクラスに分類されます。 タイプ1Mrzは3行で、各行には30文字が含まれています。 タイプ3MRZには2行しかありませんが、各行には44文字が含まれています。 いずれの場合も、MRZは、パスポートの種類、パスポートID、発行国、名前、国籍、有効期限などを含む、特定の市民の識別情報をエンコードします。
PyImageSearch Gurusコースの中で、Hansは私にプロジェクトの進捗状況を示し、私はすぐに興味を持ちました。 私はいつもパスポート画像にコンピュータビジョンアルゴリズムを適用したいと思っていました(主に楽しみのためだけに)が、そうす パスポートに含まれている個人識別情報を考えると、私は明らかにテーマに関するブログ記事を書いて、アルゴリズムを開発するために使用した画像を共有することができませんでした。
幸いにも、ハンスは彼がアクセスできるサンプル/標本パスポート画像のいくつかを共有することに同意しました—そして、私はこれらの画像で遊ぶ機会
さて、遠くに行く前に、これらのパスポートは実際の人間とリンクできるという意味で”本物”ではないことに注意することが重要です。 しかし、彼らは偽の名前、住所などを使用して生成された本物のパスポートです。 開発者が一緒に作業するためのものです。
パスポートのMRZ領域を検出するには、線形SVM+HOGフレームワークを使用して”MRZ検出器”を構築する必要があると思うかもしれませんが、それはやり過ぎです。
代わりに、しきい値、モルフォロジー演算、輪郭プロパティなどの基本的な画像処理技術のみを使用してMRZ検出を実行できます。 このブログ記事の残りの部分では、パスポートのMRZ領域を検出するためにこれらの方法を適用する方法について、私自身のテイクを詳しく説明します。
この記事のソースコードをお探しですか?
ダウンロードセクションに右にジャンプします
パスポート画像内の機械可読ゾーンの検出
このプロジェクトを開始しましょう。 新しいファイルを開き、detect_mrz.py
という名前を付け、次のコードを挿入します:
# import the necessary packagesfrom imutils import pathsimport numpy as npimport argparseimport imutilsimport cv2# construct the argument parse and parse the argumentsap = argparse.ArgumentParser()ap.add_argument("-i", "--images", required=True, help="path to images directory")args = vars(ap.parse_args())# initialize a rectangular and square structuring kernelrectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (13, 5))sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (21, 21))
2-6行目必要なパッケージをインポートします。 私はあなたがすでにOpenCVをインストールしていると仮定します。 また、opencvでの基本的な画像処理操作を簡単にするために、私の便利な関数のコレクションであるimutilsも必要になります。 imutils
をインストールするにはpip
を使用します :
$ pip install --upgrade imutils
そこから、9-11行目がコマンドライン引数の解析を処理します。 ここで必要なのは、処理しようとしているパスポート画像を含むディレクトリへのパスである--images
という単一のスイッチだけです。
最後に、14行目と15行目は、後でモルフォロジー演算、特に終了演算を適用するときに使用する二つのカーネルを初期化します。 当分の間、最初のカーネルは高さの約3倍の幅を持つ長方形であることに注意してください。 第二のカーネルは正方形です。 これらのカーネルは、MRZ文字の間のギャップとMRZ行の間の開口部を閉じることを可能にします。
コマンドライン引数が解析されたので、データセット内の各画像をループして処理することができます:
# loop over the input image pathsfor imagePath in paths.list_images(args):# load the image, resize it, and convert it to grayscaleimage = cv2.imread(imagePath)image = imutils.resize(image, height=600)gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# smooth the image using a 3x3 Gaussian, then apply the blackhat# morphological operator to find dark regions on a light backgroundgray = cv2.GaussianBlur(gray, (3, 3), 0)blackhat = cv2.morphologyEx(gray, cv2.MORPH_BLACKHAT, rectKernel)
20行目と21行目は、元のイメージをディスクから読み込み、最大高さが600ピクセルになるようにサイズを変更します。 下の元の画像の例を見ることができます:
高周波ノイズを低減するために、26行目にガウスぼかしを適用します。 次に、27行目のぼやけたグレースケール画像にblackhatモルフォロジー演算を適用します。
blackhat演算子は、暗い領域(すなわち、MRZテキスト)を明るい背景(すなわち、パスポート自体の背景)に対して明らかにするために使用されます。 パスポートのテキストは明るい背景では常に黒であるため(少なくともこのデータセットに関しては)、blackhat操作が適切です。 以下では、blackhat演算子を適用した出力を確認できます:
MRZ検出の次のステップは、Scharr演算子を使用してblackhat画像の勾配振幅表現を計算することです:
# compute the Scharr gradient of the blackhat image and scale the# result into the range gradX = cv2.Sobel(blackhat, ddepth=cv2.CV_32F, dx=1, dy=0, ksize=-1)gradX = np.absolute(gradX)(minVal, maxVal) = (np.min(gradX), np.max(gradX))gradX = (255 * ((gradX - minVal) / (maxVal - minVal))).astype("uint8")
ここでは、blackhat画像のx軸に沿ったScharr勾配を計算し、明るい背景に対して暗いだけでなく、MRZテキスト領域などの勾配の垂直変化を含む画像の領域を明 次に、このグラデーション画像を取得し、min/max scalingを使用して範囲に戻します:
なぜこのステップを適用するのかは完全には明らかではありませんが、偽陽性のMRZ検出を減らすのに非常に役立つと言います。 それがなければ、我々は誤ってMRZとしてパスポートの装飾や設計された領域をマークすることができます。 Blackhat画像の勾配を計算することでMRZ検出精度が向上することを確認するための練習としてこれを残します。
次のステップは、MRZの実際のラインを検出しようとすることです:
# apply a closing operation using the rectangular kernel to close# gaps in between letters -- then apply Otsu's thresholding methodgradX = cv2.morphologyEx(gradX, cv2.MORPH_CLOSE, rectKernel)thresh = cv2.threshold(gradX, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
まず、矩形カーネルを使用して閉じる操作を適用します。 この終了操作は、MRZ文字間のギャップを閉じるためのものです。 次に、大津の方法を使用してしきい値処理を適用して、画像を自動的にしきい値にします:
間のギャップを閉じるために長方形のカーネル(高さよりも広い)を使用して閉じる操作を適用する上の図からわかるように、各MRZ行はしきい値マッ
次のステップは、実際の線の間のギャップを閉じて、MRZに対応する大きな長方形の領域を1つ与えることです:
# perform another closing operation, this time using the square# kernel to close gaps between lines of the MRZ, then perform a# series of erosions to break apart connected componentsthresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, sqKernel)thresh = cv2.erode(thresh, None, iterations=4)
ここでは、squareカーネルを使用して、別の閉じ操作を実行します。 このカーネルは、MRZの個々のライン間のギャップを閉じるために使用され、MRZに対応する1つの大きな領域が与えられます。 一連の腐食はそれから閉鎖操作の間に結合されたかもしれない離れて接続された部品を壊すために行われる。 これらの侵食は、MRZとは無関係の小さな塊を除去するのにも役立ちます。
一部のパスポートスキャンでは、閉鎖操作中にパスポートの境界線がMRZ領域に接続されている可能性があります。 これを解決するために、画像の左右の境界線の5%をゼロ(つまり黒)に設定します):
# during thresholding, it's possible that border pixels were# included in the thresholding, so let's set 5% of the left and# right borders to zerop = int(image.shape * 0.05)thresh = 0thresh - p:] = 0
あなたは以下の私たちの境界線の除去の出力を見ることができます。
上の図5と比較すると、境界線が削除されていることがわかります。
最後のステップは、しきい値画像で輪郭を見つけ、輪郭プロパティを使用してMRZを識別することです:
# find contours in the thresholded image and sort them by their# sizecnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)cnts = imutils.grab_contours(cnts)cnts = sorted(cnts, key=cv2.contourArea, reverse=True)# loop over the contoursfor c in cnts:# compute the bounding box of the contour and use the contour to# compute the aspect ratio and coverage ratio of the bounding box# width to the width of the image(x, y, w, h) = cv2.boundingRect(c)ar = w / float(h)crWidth = w / float(gray.shape)# check to see if the aspect ratio and coverage width are within# acceptable criteriaif ar > 5 and crWidth > 0.75:# pad the bounding box since we applied erosions and now need# to re-grow itpX = int((x + w) * 0.03)pY = int((y + h) * 0.03)(x, y) = (x - pX, y - pY)(w, h) = (w + (pX * 2), h + (pY * 2))# extract the ROI from the image and draw a bounding box# surrounding the MRZroi = image.copy()cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)break# show the output imagescv2.imshow("Image", image)cv2.imshow("ROI", roi)cv2.waitKey(0)
ライン56-58では、しきい値画像の輪郭(すなわち輪郭)を計算します。 次に、これらの輪郭を取得し、59行目の降順でサイズに基づいて並べ替えます(最大の輪郭がリストの最初にあることを意味します)。
62行目で、ソートされた輪郭のリストをループし始めます。 これらの各等高線について、境界ボックス(66行目)を計算し、それを使用してアスペクト比とカバレッジ比の2つのプロパティを計算します。 縦横比は、単に境界ボックスの幅を高さで割ったものです。 カバレッジ率は、境界ボックスの幅を実際の画像の幅で割ったものです。
これらの2つのプロパティを使用して、72行目でMRZ領域を調べているかどうかを確認できます。 MRZは長方形で、幅は高さよりもはるかに大きいです。 MRZは、入力イメージの少なくとも75%にも及ぶ必要があります。
これらの2つのケースが成り立つ場合、75-84行目は境界ボックスの(x,y)座標を使用してMRZを抽出し、入力画像に境界ボックスを描画します。
最後に、87-89行目に結果が表示されます。
結果
MRZ検出器が動作していることを確認するには、次のコマンドを実行します:
$ python detect_mrz.py --images examples
以下では、mrzが緑色で概説されているMRZ検出に成功した例を見ることができます:
PythonとOpenCVを使用してpassportイメージ内の機械可読ゾーンを検出する別の例を次に示します:
MRZ領域が画像の上部または下部にあるかどうかは関係ありません。 形態学的演算を適用し,等高線を抽出し,等高線特性を計算することにより,問題なくMRZを抽出することができる。
同じことが次の画像にも当てはまります:
別の画像を試してみましょう:
これまでは、3行を含むタイプ1Mrzしか見ていませんでした。 ただし、この方法は、2行のみを含むタイプ3Mrzでも同様に機能します:
タイプ3MRZを検出する別の例は次のとおりです:
次は何ですか? 私はPyImageSearch大学をお勧めします。
30+合計クラス•39h44mビデオ•最終更新: 12/2021
★★★★★ 4.84 (128 評価)•3,000+学生が在籍
私は強くあなたが右の先生を持っていた場合、あなたはコンピュータビジョンと深い学習を習得することができると信じています。
コンピュータビジョンとディープラーニングの学習は、時間がかかり、圧倒的で、複雑でなければならないと思いますか? または複雑な数学や方程式を関与させる必要がありますか? またはコンピュータサイエンスの学位が必要ですか?
そうではありません。
コンピュータビジョンとディープラーニングを習得するために必要なのは、誰かが簡単で直感的な言葉であなたに物事を説明することだけです。 そして、それはまさに私が何をすべきかです。 私の使命は、教育と複雑な人工知能のトピックが教えられている方法を変更することです。
コンピュータビジョンの学習を真剣に考えているなら、あなたの次の停留所はPyImageSearch University、最も包括的なコンピュータビジョン、ディープラーニング、OpenCVコースです。 ここでは、あなたの仕事、研究、およびプロジェクトにコンピュータビジョンを成功させ、自信を持って適用する方法を学びます。 コンピュータビジョンマスタリーに参加してください。
:
- &チェック; Essential computer vision、deep learning、OpenCVトピックに関する30以上のコース
- ✓30以上の修了証明書
- ✓39h44m on-demand video
- ✓毎月リリースされる新しいコースで、最先端の技術についていくことができます
- ✓毎月リリースされる新しいコースで、最先端のテクニックに追いつくことができます
- ✓毎月リリースされる新しいコースで、最先端のテクニックに追いつくことができます
- ✓毎月リリースされる新しいコースで、最新のテクニックに追いつくことができます
- &1499>check;google Colabで事前設定されたjupyterノートブック
- &Check;Webブラウザですべてのコード例を実行する-Windows、macOS、Linuxで動作します(開発環境の設定は必要ありません!)
- &チェック; PyImageSearch
- &チェック上のすべての500+チュートリアルのための集中コードreposへのアクセス;コード、データセット、事前に訓練されたモデルなどのための簡単なワンクリッ
- &チェック;モバイル、ラップトップ、デスクトップなどでアクセスします。
PyImageSearch Universityに参加するにはここをクリック
概要
このブログ記事では、基本的な画像処理技術のみを使用してパスポートスキャンで機械可読ゾーン(Mrz)を検出す:
- しきい値処理。
- グラデーション。
- 等高線プロパティ。
これらの操作により、より高度な特徴抽出や線形SVM+HOGなどの機械学習方法に依存することなく、画像内のMRZ領域を検出することができました。
困難なコンピュータビジョンの問題に直面したとき、覚えておいてください—常に問題とあなたの仮定を考慮してください! このブログ記事が示すように、タンデムで使用される基本的な画像処理機能が何を達成できるか驚くかもしれません。
もう一度、PyImageSearchの達人のメンバー、Hans Booneに大きな感謝します。 ありがとうハンス!