Pythonを使用した指紋認識方法と実装

今学期には、「コンピューター情報を保護する方法と手段」という主題がスケジュールに登場しました。その一部は、生体認証、より具体的には指紋認識に関する実験室作業です。 また、最近、Habréでスキャン対象のデバイスに関する記事がありました。 ここで、認識アルゴリズムについて書くことにしました。


私の前に、学生として、かなり標準的なタスクがあります:指紋の検証(標準との比較)。 この研究室のものは今年だけ登場したので、方法論的なマニュアルはまだありません。 しかし、タスクの面白さを考慮して、Googleに行きました。

奇妙なことに、スキャナに関するトピックで示された記事の2番目の部分が最も有益であることが判明しました。 非常に理解しやすいように、いくつかのアルゴリズムについて説明しています。

1.相関の比較
このアプローチは、得られた結果に基づいて、異なるシフトと回転角度の2つの画像をピクセルごとに比較することで構成され、一致が判断されます。 (高度な複雑さのため、現代の条件では使用されません)

2.パターン比較
必要な精度に応じて、印刷の画像は領域に分割されます。 さらに、各領域のパターンは、パラメーターを使用して正弦波で記述されます。

このクラスのアルゴリズムは、スキャン時に高解像度を必要としません。

3.人のポイントによる比較
特徴点は、エンドポイントと分岐点です。 これらのポイントは両方の画像で強調表示され、その後、相関比較の方法によって、印刷物の一致に関する判定が発行されます。
比較的単純な実装と速度のため、これらのアルゴリズムはより一般的です。
私は、このタイプのアルゴリズムを実験室での実装に選択しました。 したがって、より詳細に説明します。

この記事では一般的なアイデアしか示していないため、引き続きGoogleを使用しました。 配信の3行目はこのプレゼンテーションでした。
選択したアプローチを実装するための手順をかなり詳細に説明しています。

だから、アクションプラン:

実装はPythonで行うことが決定されました。 したがって、 Python自体(バージョン2.7.1があります)に加えて、 PIL(Python Imaging Library)で画像をピクセルに解析する必要があります。

ステップ1.二値化
それから私は発明しなかったし、額で非常に簡単にすべてをした。
defバイナリ img
bImg = [ ]
範囲内の i img。size [ 0 ]
tmp = [ ]
範囲内の j img。size [ 1 ]
t = img。 getpixel i、j
p = t [ 0 ] * 0.3 + t [ 1 ] * 0.59 + t [ 2 ] * 0.11
p > 128の 場合
p = 1
その他
p = 0
tmp。 追加 p
bImg。 追加 tmp
戻り

別の結果が必要な場合は、 「画像処理」ブログのトピックを参照してください。ここでは、2値化が頻繁に影響を受けます。

ステップ2.スケルトン化
グーグルのアルゴリズムが最も難しかったので、このステップは最大の困難を引き起こしました。 その結果、4つのアルゴリズムが見つかりました。

テンプレートの方法が選択されました。最初のセットは、テンプレートの2番目のセットとは異なり、画像のクロールが1回だけ必要なためです。 確かに、不正確さのレベルを下げるために、2番目のセットのテンプレートの一部が使用されます。

パターンは3 * 3マトリックスに対応します。ここで、中心要素はイメージトラバーサルの現在のピクセルです。
画像
ここで、グレーは色が重要でないピクセルです

最初の8つのテンプレートが主要部分です。 「ノイズ」を除去するために下から4つ、これら4つは90、180、270度回転させることもでき、画像の2番目のバイパスで検索されます。

テンプレートに遭遇した場合、中央のピクセルは白く塗られます(スケルトンに属していません)。 削除オプションが残っている間、トラバーサルは続行します。

このアクションのコードは、いくつかの機能に分かれています。
def tmpDelete img #スケルトン化プロシージャの呼び出し、入力時にリストのリスト(2値化後)
w = len img
h = len img [ 0 ]
カウント= 1
カウントしながら = 0#少なくとも1つのピクセルが削除されたpokを繰り返します
カウント=削除 img、w、h
カウントする場合
delete2 img、w、h


def delete img、w、h #メインセットからピクセルを削除し、削除された数を返します
カウント= 0
範囲内の iの場合 1 、h- 1
j 範囲 1 、w- 1 )の場合
if img [ j ] [ i ] == 0
削除可能な場合 img、j、i
img [ j ] [ i ] = 1
カウント+ = 1
戻り回数

def delete2 img、w、h #ノイズセットからピクセルを削除
範囲内の iの場合 1 、h- 1
j 範囲 1 、w- 1 )の場合
if img [ j ] [ i ] == 0
deletable2 img、j、i )の場合
img [ j ] [ i ] = 1


def fringe a #3 * 3ノイズの定義
t = [ [ 1、1、1、1、0、1、1、1、1 ]

[ 1、1、1、1、0、1、1、0、0 ]
[1、1、1、0、0、1、0、1、1 ]
[ 0、0、1、1、0、1、1、1、1 ]
[1、1、0、1、0、0、1、1、1 ]

[1、1、1、1、0、1、0、0、1 ]
[ 0、1、1、0、0、1、1、1、1 ]
[1、0、0、1、0、1、1、1、1 ]
[ 1、1、1、1、0、0、1、1、0 ]

[ 1、1、1、1、0、1、0、0、0 ]
[ 0、1、1、0、0、1、0、1、1 ]
[ 0、0、0、1、0、1、1、1、1 ]
[ 1、1、0、1、0、0、1、1、0 ] ]
tのiの場合:
a == iの場合
真を 返す

def check a #3 * 3がメインテンプレートに属するかどうかを判断する
t123457 = [ 1、1、0、0、1、0 ]
t013457 = [ 1、1、1、0、0、0 ]
t134567 = [ 0、1、0、0、1、1 ]
t134578 = [ 0、0、0、1、1、1 ]
t0123457 = [ 1、1、1、0、0、0、0 ]
t0134567 = [ 1、0、1、0、0、1、0 ]
t1345678 = [ 0、0、0、0、1、1、1 ]
t1234578 = [ 0、1、0、0、1、0、1 ]

t = [ a [ 1 ] 、a [ 2 ] 、a [ 3 ] 、a [ 4 ] 、a [ 5 ] 、a [ 7 ] ]
t == t123457の場合
真を 返す
t = [ a [ 0 ] 、a [ 1 ] 、a [ 3 ] 、a [ 4 ] 、a [ 5 ] 、a [ 7 ] ]
t == t013457の場合
真を 返す
t = [ a [ 1 ] 、a [ 3 ] 、a [ 4 ] 、a [ 5 ] 、a [ 6 ] 、a [ 7 ] ]
t == t134567の場合
真を 返す
t = [ a [ 1 ] 、a [ 3 ] 、a [ 4 ] 、a [ 5 ] 、a [ 7 ] 、a [ 8 ] ]
t == t134578の場合
真を 返す
t = [ a [ 0 ] 、a [ 1 ] 、a [ 2 ] 、a [ 3 ] 、a [ 4 ] 、a [ 5 ] 、a [ 7 ] ]
t == t0123457の場合
真を 返す
t = [ a [ 1 ] 、a [ 3 ] 、a [ 4 ] 、a [ 5 ] 、a [ 6 ] 、a [ 7 ] 、a [ 8 ] ]
t == t1345678の場合
真を 返す
t = [ a [ 0 ] 、a [ 1 ] 、a [ 3 ] 、a [ 4 ] 、a [ 5 ] 、a [ 6 ] 、a [ 7 ] ]
t == t0134567の場合
真を 返す
t = [ a [ 1 ] 、a [ 2 ] 、a [ 3 ] 、a [ 4 ] 、a [ 5 ] 、a [ 7 ] 、a [ 8 ] ]
t == t1234578の場合
真を 返す

def deletable img、x、y #受信3 * 3、メインの検証のために送信
a = [ ]
範囲内の iの場合 y- 1 、y + 2
j 範囲 x- 1 、x + 2 )の場合
a。 追加 img [ j ] [ i ]
返却チェック a

def deletable2 img、x、y #3 * 3を受信し、ノイズのチェックのために送信します
a = [ ]
範囲内の iの場合 y- 1 、y + 2
j 範囲 x- 1 、x + 2 )の場合
a。 追加 img [ j ] [ i ]
戻りフリンジ a


ステップ3.特異点を強調表示する
ここではすべてが簡単です。 8ポイントの近傍に黒が1つしかない場合、これが終点です。 それらが2つある場合、これは単なる行のポイントです。 3つは分岐点です。
def checkThisPoint img、x、y #近所の黒人を数える
c = 0
範囲 x- 1 、x + 2 )の iの場合:
j 範囲 y- 1 、y + 2 )の場合
if img [ i ] [ j ] == 0
c + = 1
return c- 1

def findCheckPoint img #分岐点のリストと終了
x = len img
y = len img [ 0 ]
branchPoint = [ ]
endPoint = [ ]
範囲 x )の iの場合:
範囲 y )の jの場合:
if img [ i ] [ j ] == 0
t = checkThisPoint img、i、j
t == 1の 場合
エンドポイント。 追加 i、j
t == 3の 場合
branchPoint。 追加 i、j
return branchPoint、endPoint

唯一の問題は、ノイズの完全な除去ではなく、特異点として認識されたプロセスの出現につながりました。 それらを考慮に入れないために、密接な(10 * 10)分岐点と終点の削除が行われました。
def __removeDouble x、y #別のリストに同じものがない要素のリストを返します
z = [ ]
xのiの場合:
c = true
yのjの場合:
i == jの場合
c = False
cの場合
z。 追加 i
yのiの場合:
c = true
xのjの場合:
i == jの場合
c = False
cの場合
z。 追加 i
zを返す

def delNoisePoint r #入力タプル(分岐、末尾)
tmp = [ ]
tmp2 = [ ]
for i in r [ 1 ]
x = 範囲 i [ 0 ] -5 、i [ 0 ] + 5
y = 範囲 i [ 1 ] -5 、i [ 1 ] + 5
r [ 0 ]の jの場合:
xのj [ 0 ] および yのj [ 1 ]の場合
tmp。 追加 i
tmp2。 追加 j
return __removeDouble r [ 0 ] 、tmp2 、__ removeDouble r [ 1 ] 、tmp


ステップ4.ポイントを比較する
30 * 30の近傍に入り、同じタイプのポイントであるポイントの簡単な検索。
def matchingPoint r、v #input:参照点のタプルとチェックされたもののタプル。 出力(一致、合計)
すべて = 0
一致= 0
v [ 0 ]の iの場合:
x = range i [ 0 ] -15 、i [ 0 ] + 15
y = 範囲 i [ 1 ] -15 、i [ 1 ] + 15
すべて + = 1
r [ 0 ]の jの場合:
xのj [ 0 ] および yのj [ 1 ]の場合
マッチ+ = 1
破る
v [ 1 ]の iの場合:
x = range i [ 0 ] -15 、i [ 0 ] + 15
y = 範囲 i [ 1 ] -15 、i [ 1 ] + 15
すべて + = 1
r [ 1 ]の jの場合:
xのj [ 0 ] および yのj [ 1 ]の場合
マッチ+ = 1
破る

リターン 一致、 すべて


オプション:
すべてのコードは、同じサイズの画像に対して有効です(ただし、異なる画像でも機能します)。

結論:
1.この実装は単純で不器用です。 たとえば、特定のポイントで線の角度を調べるなど、いくつかのチェックを追加することができます。 チェック時に、同じタイプの多くのポイントが近傍に落ちた場合に、すでに見つかったペアを破棄します。
2. Pythonでの実装はかなり遅いです。私のマシンでの実行速度は、人の往来が多いアイテムにはまったく適していません。 NumPyを使用するとパフォーマンスが向上する可能性があり、私も最高の実装者ではありません。
3. ここで完全なコードを取得します 。 このキットでテスト済み。

PS pythonの方がやや弱いので、コードについてコメントしたいと思います。 まあ、指紋採取に真剣に取り組んでいる人の意見。

Source: https://habr.com/ru/post/J116603/


All Articles