この記事では、PythonとOpenCVを活用して、文字の入った画像から文字だけを消す方法を解説します。
OpenCVの導入方法は以下の記事をご参照ください。
目次
文字を消すための考え方
文字を消すための考え方は…
文字をノイズと捉えて修復する
という考え方です。
そのため、傷のついた画像などを修復する際に使用されるOpenCVのImage Inpaintingという機能を使用します。
手順としては以下の通りです。
- 画像を読み込む
- マスクを作成する
- マスクを重ねて修復する
画像を修復する関数:inpaint関数
関数について詳細を見ていきましょう。
関数名はinpaint()です。
引数は以下の通りです。
cv2.inpaint(元画像 , マスク , 修復半径 , 修復手法)
よくわからないのは”修復半径”と”修復手法”ですね。
修復半径
inpaintRadius(修復半径)という項目です。初期値は”3″です。
公式によると…
アルゴリズムによって考慮される、修復された各ポイントの円形近傍の半径。
とのこと。
よくわからないけど、修復するマスク周りの輪郭の範囲という認識です。
(違ってたら直します)
なので、値が大きい方が消したい物はちゃんと消えますが、周りがガビガビ・モヤモヤになるのかな~と思います。
とりあえず初期値の”3″にしておいて、必要に応じて値を変えてみればいいかと思います。
参考程度に値を”1″,”3″,”10″,”20″と変えた結果の画像を貼っておきます。
“1”だとまだ輪郭が少し残っていますね。
値が”3″以上になると違いが判りませんが、背景が写真などの精細な物であれば影響がはっきり出るかと思います。
修復手法
修復手法には以下の2つがあります。
- cv.INPAINT_NS
- cv.INPAINT_TELEA
詳細はよくわからないので省きますが、修復のアルゴリズムの違いのようです。
正直違いがよくわからないです。。。
とりあえずcv.INPAINT_TELEAを選んでおきます。
詳細を知りたい方はググってみてください。
(他力本願)
閾値の決め方
マスク作成の工程について
ここはマスクを作成する工程の話になります。
inpaint関数に直接かかわるところではないですが、修復のためにマスクの精度は重要になるので解説します。
まず、マスクを作成する工程は以下の通りです。
- 画像をグレースケールで読み込む
- グレースケール画像を二値化(白黒)にする
- 白と黒を反転する
マスクは除去したい箇所を白、残したい部分を黒とするため、「3.白黒の反転」が必要になります。
閾値とは?
本題の閾値は「2.グレースケール画像を二値化(白黒)にする」際の閾値です。
この値が大きいほど、ちゃんとした黒じゃないと黒として判断されません。
閾値の決め方
「じゃあこの閾値はどう決めればいいの?」という所ですが、方法は2つあります。
- 実際にマスクを作りながら良い値を探す
- OpenCVに良い感じの値を自動で決めてもらう
使用する関数はthreshold関数です。
cv2.threshold(元画像 , 閾値 , 最大値 , タイプ)
上記の”タイプ”の設定で手動/自動を設定します。
cv2.THRESH_BINARY:手動
cv2.THRESH_OTSU:自動
実際の処理で書くと以下のようになります。
ret , img_gray = cv2.threshold(img,200,255,cv2.THRESH_BINARY)
→手動の閾値200
ret , img_gray = cv2.threshold(img,200,255,cv2.THRESH_OTSU)
→自動
上記の処理で”ret”に設定された閾値、”img_gray”に画像の数値ファイルが格納されます。
ソース
色々とややこしい部分はありますが、実際にソースを見てみましょう。
ソースをコピペして、画像の読み込み部分を手持ちのファイルに変えていただければ使えます。
import cv2 #画像の読み込み original = cv2.imread("image/English_yellow.png") img = cv2.imread("image/English_yellow.png",0) #画像の加工 ret , img_gray = cv2.threshold(img,200,255,cv2.THRESH_BINARY) #ret , img_gray = cv2.threshold(img,0,255,cv2.THRESH_OTSU) mask = cv2.bitwise_not(img_gray) repaire = cv2.inpaint(original,mask,3,cv2.INPAINT_TELEA) #出力 print(ret) cv2.imshow("original",original) cv2.imshow("mask",mask) cv2.imshow("repaire",repaire) cv2.waitKey(0)
↓解説付き↓
実行結果
実行結果は以下の通りです。
左から元画像、マスク、修復後となります。
少しモヤモヤが残っている感じがしますが、文字の削除ができました。
ということでこの記事はここまでとなります。
ご覧いただきありがとうございました。
他にもOCRなどの手順も記載しているので、他の記事も見ていただけると幸いです。