OpenCVを使って紙に押した印鑑を電子化してみた


Motive

Excelのシートかwordで自分の印鑑を押印する箇所があったりします。少し大事な書類であれば市役所に登録されている印鑑証明と同一のものを使いたい時があるのですが、以前は一度コンビニで紙を印刷して押印し、再度スキャンでpdf化して提出をしていました。

結構なアナログな処理をしていた訳ですが、印鑑をイメージ化してシートに貼り付けることができればコンビニへ行く手間がなくなっていいかなと思い方法を考えてみました。

最初は印鑑を撮影して、PowerPointかフリーの画像編集ツールを使って背景色を透過しようとしたのですが紙質によって全てを変換することは出来ずに断念してしまいました。

それで、試行錯誤して結局OpenCVで画像処理を数行書いて問題を解決をしたので備忘録として残しておきます。

Dataset

アクセアにあった印鑑サンプルを使いました。

Method

  1. 二値化+画像反転
  2. 元画像と1の画像でマスキング
  3. 背景画像を透過(α値100%)

Development

import cv2
import sys
import numpy as np

if __name__ == '__main__':

    if len(sys.argv) != 2:
        sys.exit()

    window_name = "sample"
    img_path = sys.argv[1]

    mat = cv2.imread(img_path)
    gray = cv2.cvtColor(mat, cv2.COLOR_BGR2GRAY)
    cv2.imwrite("gray.png", gray)

    #二値化
    ret2, mono = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU + cv2.THRESH_BINARY_INV) 
    cv2.imwrite("mono.png", mono)

    #マスキング処理
    dst = cv2.bitwise_and(mat,mat,mask=mono)
    cv2.imwrite("dst.png", dst)

    #channelを3 -> 4に変更
    alpha = cv2.cvtColor(dst, cv2.COLOR_BGR2BGRA)

    #背景が黒い部分のみ透過
    for i,col in enumerate(dst):
        for j,row in enumerate(col):
            color = dst[i][j]
            if (color == np.array([0,0,0])).all():
                alpha[i][j][3] = 0

    cv2.imshow(window_name, alpha)
    cv2.imwrite("out.png", alpha)
    cv2.waitKey(0)
    cv2.destroyWindow(window_name)

今回は途中まで処理した画像データも出力しています。

Result

処理フロー output
元データ
白黒
二値化+反転
マスキング
背景色透過
(処理終了)

Future

cv2.bitwise_andを利用すれば背景透過は簡単に作成はできます。
ツールを使って時間がかかりそうだったらこっちの方が良さそうです。

Reference