« あずきが音を立てるだけのアプリ「あずきザザー」 | トップページ | 大阪出張ついでに大阪城 & 個室ワーキングスペースへ行ってみた »

2022年6月28日 (火)

ラベル(四角形で囲まれた部分)を自動で抜き出して台形補正してくれるやーつを作ってみた

社内で、ラベル部分を撮影してその部分を補正しつつ自動的に抜き出すプログラムコードを作ってみました。
何を言っているのかというと、

Image3

例えばこういう写真を撮ると

Output

ラベルの部分だけを抜き出して、補正した状態で保存してくれるものを作った、ということです。
いろんなところを参考にしたのと、社内の有志(勇士)にも頼んで作った結果、できました。
参考にしたサイトは、以下。

OpenCVの使い方9 ~ 台形補正2 - つれづれなる備忘録

【label_daikei.py】

import cv2
import numpy as np
import math
import itertools

# 比率調整
import pandas as pd
# 入力画像のパス
input_file_path = "./data/image3.jpg"
# 出力画像のパス
output_file_path = "./output.jpg"
# 入力画像の読み込み
img = cv2.imread(input_file_path,0)
# 二値化
# 閾値の設定
threshold_min = 160
threshold_max = 230
# 二値化
ret, img_thresh = cv2.threshold(img, threshold_min, threshold_max , cv2.THRESH_BINARY)

#四角抽出
tmp= cv2.findContours(img_thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
contours = tmp[0] if len(tmp) == 2 else tmp[1]
#一定以上の面積の図形のみを抽出
areas = []
for cnt in contours:
    area = cv2.contourArea(cnt)
    if area > 70000:
        epsilon = 0.1*cv2.arcLength(cnt,True)
        approx = cv2.approxPolyDP(cnt,epsilon,True)
        areas.append(approx)
pt=[]
# arrayをdataframeに変換して整形
df_a = pd.DataFrame(areas[0].reshape(-1,2))
# 全4pointについてy座標でsort
df_a.sort_values([df_a.columns[0], df_a.columns[1]], inplace=True)
# 上下の2pointずつを分ける
df_upper = df_a.iloc[:2, :]
df_lower = df_a.iloc[2:, :]
# 下部2pointについてx座標でsort
df_lower.sort_values([df_lower.columns[1], df_lower.columns[0]], inplace=True)
# 上下を合体
df_a = pd.concat([df_upper, df_lower])
for j in range(df_a.shape[0]):
    # arrayにしてリスト化
    p = np.array([df_a.iloc[j, :].tolist()])
    pt.append(p)
# 全体をarray化
pt = np.array(pt)
#頂点の座標を得る
pt1=pt[0] #左上
pt2=pt[1] #左下
pt3=pt[2] #右下
pt4=pt[3] #右上
print(pt[0]) #左上
print(pt[1]) #右上
print(pt[2]) #右下
print(pt[3]) #左下
pts = np.float32(np.array([pt1,pt2,pt3,pt4]))
o_width = np.linalg.norm(pt2 - pt1)
o_width=int(np.floor(o_width))
o_height = np.linalg.norm(pt3 - pt1)
o_height=int(np.floor(o_height))
dst_cor=np.float32([[0,0],[o_width,0],[0, o_height],[o_width, o_height]])
# 変換行列
M = cv2.getPerspectiveTransform(pts, dst_cor)
# 射影変換・透視変換する
output = cv2.warpPerspective(img_thresh, M,(o_width, o_height)).T
cv2.imshow("cut", output)
cv2.waitKey()
# 射影変換・透視変換した画像の保存
cv2.imwrite(output_file_path, output)

参考にしたサイトの通りにすると、うまく抜き出せなかったのですが、これでようやく正常な画像として抜き出せました。
最後の方の「output = ~」のところに転置(.T)がついてて奇妙なコードですが、なんかもうこれで動いちゃったので、勘弁してください。

で、「data」というフォルダに入っているimage3.jpgという画像ファイルを読み込み、四角形で囲まれた部分を抜き出して補正するというものですが、18、19行目にある「100」、「230」という数値は、その画像抜出時に二値化するための閾値です。適宜、いじってください。

また、画像ファイルの横幅は1000程度にしておいた方がいいです。あまり大きいと、うまく読み込みません。
もし大きな画像サイズでじっしするときは、31行目あたりの

if area > 70000:

という行の「70000」という数値を大きくした方がいいでしょう。

この程度の台形補正ならば、Microsoft Pixあたりでも可能です。その方が楽ですね。
が、台形補正 → OCR処理 という連続処理をさせたかったがために、アプリではなくPythonのコード化をする必要に迫られた次第です。
もし、前処理として画像の歪みを補正する必要に迫られたら、ぜひご参考に。


OpenCVではじめよう ディープラーニングによる画像認識

« あずきが音を立てるだけのアプリ「あずきザザー」 | トップページ | 大阪出張ついでに大阪城 & 個室ワーキングスペースへ行ってみた »

数値解析系」カテゴリの記事

コメント

こんにちは。
変換行列を決める二つの変数、ptsは左上から反時計回りなのにdst_corは左上から時計回りになっているのがおかしいです。

dst_cor=np.float32([[0,0],[o_width,0],[0, o_height],[o_width, o_height]])

dst_cor=np.float32([[0,0],[0, o_height],[o_width,0],[o_width, o_height]])
としてやれば最後に転置する必要がなくなります。

> mo256manさん
すいません、仕上げが雑で。この部分が社内で作ってもらったやつなのですが、結果見て対処療法的にやりました。はい。

コメントを書く

(ウェブ上には掲載しません)

« あずきが音を立てるだけのアプリ「あずきザザー」 | トップページ | 大阪出張ついでに大阪城 & 個室ワーキングスペースへ行ってみた »

当ブログ内検索

スポンサード リンク

ブログ村

無料ブログはココログ