スポンサーリンク

【Python】OpenCVとNumpyで画像の文字間隔を広げる手順。

Python
スポンサーリンク

今回の記事はOpenCVとNumpyを用いた画像内の文字間隔を広げる手法について記載いたします。先に最終的なイメージとして下記のオリジナル画像と拡張画像をご確認ください。

オリジナル画像
拡張画像

上記のように拡張された画像を出力することができます。

全体的な流れとしては「画像読み込み」「画像のピーク値を検出」「余白部分を検出」「余白部分に白色の配列を挿入」「画像保存」です。

機械学習などでの画像の保存を行う際に使うことがあるかもしれんません。私の過去記事にある文字の領域検出と識別を行う際応用できる可能性もあるのできになる方はこちらから確認して見てください。

では今回の記事に進んでいきます。

スポンサーリンク

penCVとNumpyで画像の文字間隔を広げる環境紹介

今回の環境はdocker上に作成したpython環境です。imageはtensorflowベースのものを使用しております。

詳しくは下記で環境構築を行うことができます。

docker上でtensorflow(python)環境を構築する手順

pythonのバージョンは3.6.5です。

OpenCVとNumpyで画像の文字間隔を広げる手順

まずはOpenCVで画像を読み込みピーク値の検出を行います。

import cv2
import numpy as np
import matplotlib.pyplot as plt

#対象の画像読み込み
img = cv2.imread("./test_cv.png")
print(img.shape)

gray_img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
#print(img.shape)
ret, bw_img = cv2.threshold(gray_img, 0, 255, cv2.THRESH_OTSU)

height, width = bw_img.shape

#射影投射###########################################
array_V = np.zeros(width)
#画像を横から縦に回す
for i in range(width):
    total_count = 0
    for j in range(height):
        temp_pixVal = bw_img[j, i]
        if temp_pixVal == 0:
            total_count += 1
    array_V[i] = total_count
#図を写す
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
x_axis = np.arange(width)
ax.bar(x_axis, array_V)
###################################################

こちら詳しい解説はこちらの記事で解説しているのできになる方はご参照ください。

ピーク値を検出した後は下記のように余白挿入部を決定していきます。

#array_Vに入っているのが画像横に対応した各ピーク(要は画像の成分がどの程度充当しているか)
#ここで0のものが余白部分(何も入っていない部分になる)
#そこのindex番号を取得するともに配列代入箇所をさがす
add_index_list = []
num = 0
for i in array_V:
    #8充当までは余白とみなす
    if int(i) < 8:
        add_index_list.append(num)
        #if num - 1 not in add_index_list:
                
    num = num + 1
#print(add_index_list)
#余白部分に該当するindex番号

add_target_index = []
num = 0
for i in add_index_list:
    if num == 0:
        add_target_index.append(i)
    else:
        if i - add_index_list[num - 1] == 1:
            pass
        else:
            add_target_index.append(i)
    num = num + 1
    
#print(add_target_index)
#今回の余白挿入箇所のindex番号

余白は画像の縦方向に黒要素のピクセルが8個以下の部分というふうに設定を行います。(0にしない理由はノイズ等での要素が残っている場合があるためとか言いつつうまくいったのがこれだからです。)

挿入用の行列をnumpyによって作ります。余白幅は20ぴくする分にします。

add_lists = []


#余白用の配列を成型################
#20が余白の幅になる
for r in range(20):
    add_list = []
    #高さの分だけ回す
    for rr in range(height):
        add_list.append([255,255,255])
    add_lists.append(add_list)

#numpy_arrayに変換
add_lists = np.array(add_lists)
print(add_lists.shape)
#print(add_lists.shape)
#(20, 131, 3)###################

では最後に余白の挿入と画像保存を行います。

global add_magin_img
add_magin_img = img

add_target_index.reverse()
for i in add_target_index:
    #画像内に余白挿入
    
    add_magin_img = np.insert(add_magin_img, i, add_lists, axis=1)
    print(add_magin_img.shape)
#画像保存
cv2.imwrite('./test_bunkatu1.png',add_magin_img)

以上が一連の流れです。

おそらくエラーなどは発生しないものと思われますが発生した場合は経験談から、「画像の読み込み失敗」「配列の形が違う」などが考えられますがコード上特に問題になる箇所はないと思われます。

念のため全体を通してのコードを貼っておきます。

import cv2
import numpy as np
import matplotlib.pyplot as plt

#対象の画像読み込み
img = cv2.imread("./test_cv.png")
print(img.shape)

gray_img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
#print(img.shape)
ret, bw_img = cv2.threshold(gray_img, 0, 255, cv2.THRESH_OTSU)

height, width = bw_img.shape

#射影投射###########################################
array_V = np.zeros(width)
#画像を横から縦に回す
for i in range(width):
    total_count = 0
    for j in range(height):
        temp_pixVal = bw_img[j, i]
        if temp_pixVal == 0:
            total_count += 1
    array_V[i] = total_count
#図を写す
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
x_axis = np.arange(width)
ax.bar(x_axis, array_V)
###################################################

#array_Vに入っているのが画像横に対応した各ピーク(要は画像の成分がどの程度充当しているか)
#ここで0のものが余白部分(何も入っていない部分になる)
#そこのindex番号を取得するともに配列代入箇所をさがす
add_index_list = []
num = 0
for i in array_V:
    #8充当までは余白とみなす
    if int(i) < 8:
        add_index_list.append(num)
        #if num - 1 not in add_index_list:
                
    num = num + 1
#print(add_index_list)
#余白部分に該当するindex番号

add_target_index = []
num = 0
for i in add_index_list:
    if num == 0:
        add_target_index.append(i)
    else:
        if i - add_index_list[num - 1] == 1:
            pass
        else:
            add_target_index.append(i)
    num = num + 1
    
#print(add_target_index)
#今回の余白挿入箇所のindex番号
    
add_lists = []


#余白用の配列を成型################
#20が余白の幅になる
for r in range(20):
    add_list = []
    #高さの分だけ回す
    for rr in range(height):
        add_list.append([255,255,255])
    add_lists.append(add_list)

#numpy_arrayに変換
add_lists = np.array(add_lists)
print(add_lists.shape)
#print(add_lists.shape)
#(20, 131, 3)###################
global add_magin_img
add_magin_img = img

add_target_index.reverse()
for i in add_target_index:
    #画像内に余白挿入
    
    add_magin_img = np.insert(add_magin_img, i, add_lists, axis=1)
    print(add_magin_img.shape)
#画像保存
cv2.imwrite('./test_bunkatu1.png',add_magin_img)

Python
スポンサーリンク
tomoをフォローする
スポンサーリンク
SunnyDayTravel-Blog

コメント

タイトルとURLをコピーしました