動画:【4桁 – 7セグメント編】文字検出機能付きの連続デジタル数字画像認識プログラミング入門(Python・OpenCV・Keras・CNN)
【Python機械学習入門】文字検出機能付き:高精度の自作OCRを作ろう
7セグメントデジタル連続数字画像認識AI:1桁〜4桁以上 – 物体検出・抽出編
7 Segment Digits OCR
視聴時間:18分26秒
訂正:17分6秒〜17分22秒までの音声説明は間違えです… 今回のプログラムでは「ROI_img〜.png」で保存した画像を使って予測はしていません。(作成中の日本語OCRプログラムと勘違いしていました・・・ご了承ください)
使い方がわからない方は、動画を参照ください。
【動画の内容】
0:00 ダイジェスト
0:22 はじめに – オリジナルOCR開発の設計概略
0:46 ステップ1 – 文字検出の概略:画像の前処理など(OpenCV)
6:33 ステップ2 – 文字検出の設定変更のチュートリアル
10:06 ステップ3 – 文字検出 + 連続文字認識(再学習について) ← ココ
17:24 おわりに – 日本語 横書き・縦書き対応のプログラミング学習用OCR開発中(ノイズ除去・直線除去・角度補正・ブロック検出機能付き)
機械学習モデルのディープラーニング(深層学習)でおなじみの「畳み込みニューラルネットワーク」(CNN:Convolutional Neural Network)で、7セグメントのデジタル数字画像のオリジナルデータセットで作成した学習済みモデルを使って、1〜4桁以上の連続した数字画像認識ができる文字検出(物体検出・輪郭検出)機能付きのOCRプログラムを開発してみました。
今回のOCRは、デジタル数字の静止画像から、数字の文字を自動で検出し、検出した数字を判定(画像分類)し、結果を出力します。(7セグメントのデジタル数字画像・デジタルメーターの数字を読み取り、画像判別)
既存のOCRプログラムで7セグメントのデジタル数字検出や画像認識をしてみても、思ったよりも上手く行かない経験をされる方もいるのではないかと思います。
一連のプログラムが、これから、計量器や時計、温度計をはじめとした測定器のデジタル数字認識に挑戦したい方の参考になることがありましたら幸いです。
7 Segment Edition(Seven Segment Edition)
:How to Create an Original OCR.
【Object Detection】Introduction to Continuous Digital Number Display Image Recognition Python Programming.
サンプル画像・学習済みモデル・サンプルコードリンク:文字検出機能付きの7セグメント連続デジタル数字画像認識プログラム用
事前に
【7セグメント編】オリジナル学習済みモデルの作成方法:連続デジタル数字画像認識プログラミング入門(Python・OpenCV・Keras・CNN)
の手順を実行し、学習済みモデルを作成した状態でサンプルコードを実行するか、7セグメントのデジタル数字画像の学習済みモデル作成プログラムで作成したサンプル学習済みモデル(「〜.h5」のファイル)をGoogle Colaboratoryにアップロードしてからサンプルコードを実行してください。
モノクロ・グレースケール版の学習済みモデル
ダウンロード:学習済みモデル - モノクロ・グレースケール版(7セグメントディスプレイのデジタル数字画像認識)
画像設定:モノクロ・グレースケール
大きさの設定:横の幅28 * 縦の高さ28ピクセル
python 3.6.9
tensoflow 2.4.1
keras 2.4.3
ランタイム:GPU
カラー版の学習済みモデル
画像設定:カラー
大きさの設定:横の幅28 * 縦の高さ28ピクセル
python 3.6.9
tensoflow 2.4.1
keras 2.4.3
ランタイム:GPU
文字検出・判定用のデジタル数字画像認サンプル画像
7セグメントのデジタル数字画像認識評価用サンプル画像です。
1桁〜4桁以上の画像などがあります。
すぐに使えるGoogle Colaboratoryサンプルコードリンク
CNN-7segment-digits-original-OCR.ipynb | Google Colaboratory
(ファイル – ドライブにコピーを保存後にコピー環境で実行)
【プログラムのライセンス】
The MIT License
Copyright 2021 child programmer
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
【7セグメントのデジタル数字の文字検出(物体検出)& 画像認識用:Pythonサンプルコード】
【7セグメント編 – 自動文字検出・抽出OCR】連続文字判定(デジタル数字:1〜4桁以上の連続数字)
400 × 100(横400 × 縦100ピクセル)の画像から、デジタル数字の文字検出を実施後に、検出画像を認識した結果をまとめて表示させることで1〜4桁以上の連続数字を認識できるOCRプログラムです。文字検出がない場合や、何も数字がない場合には、数値が出力されないようになっています。
学習データは、実際に使う7セグメントディスプレイ画像を撮影した物を使って学習を繰り返すと、デジタルの数字の認識精度が上がるのではないかと思います。
・機械学習モデル:CNN(Convolutional Neural Network:畳み込みニューラルネットワーク)
・データセット:オリジナルの7セグメントのデジタル数字画像で作成
こちらに公開しているプログラム
Keras_CNN_7segment_digits_originaldataset.ipynb | Google Colaboratory共有ファイル
(7セグメントのデジタル数字のオリジナル学習済みモデルを作成)
を使うと、オリジナルデータセットで学習済みモデルの作成や、モデルの再学習をすることができます。
実際に認識させていく中で、間違えた画像をデータセットに追加し、再学習することで実際の正解率が向上していくのではないかと思います。
一連のサンプルコードでは、学習済みモデルの学習回数は僅かで、基本的な画像の前処理しか行っていませんでしたが、自分が目的とするデジタル数字画像の判定結果はまずまずでした。
バージョン情報(Python・各種ライブラリ)
python 3.6.9 〜 3.7.10
tensoflow 2.4.1
keras 2.4.3
opencv(opencv-python)4.1.2
matplotlib 3.2.2
imutils 0.5.4
指定したバージョンのインストールが難しい場合、Python・TensorFlow・Keras以外は最新のバージョンを入れてみてください
また、Google Colaboratoryのサンプルコードではランタイム:GPUで実行しています。
① 学習済みモデルの準備。
以下のプログラムで作成できます。「〜.h5」という名前のファイルを作成できます。
Keras_CNN_7segment_digits_originaldataset.ipynb | Google Colaboratory共有ファイル
(7セグメントのデジタル数字のオリジナル学習済みモデルを作成)
文字検出・判定用のデジタル数字画像認サンプル画像
7セグメントのデジタル数字画像認識評価用サンプル画像です。
1桁〜4桁以上の画像などがあります。
② Google Colaboratoryの、このノートブックに学習済みモデルをアップロード。
サンプルの学習済みモデル「〜.h5」ファイルのダウンロードはこちら
カラー版の学習済みモデル
画像設定:カラー
大きさの設定:横の幅28 * 縦の高さ28ピクセル
python 3.6.9
tensoflow 2.4.1
keras 2.4.3
ランタイム:GPU
デジタル数字画像認サンプル画像
7セグメントのデジタル数字画像認識評価用サンプル画像です。
1桁〜4桁の画像があります。
* 区別がつきやすいように長い名前がついていますが、使う際は「model.h5」の名前に変更して使うと楽です。
デフォルトでは「model.h5」を読み込むプログラムを記述しています。
③ 画像認識させたい画像ファイルをこのノートブックにアップロード。
デフォルのプログラムでは、アップロードされた画像を「横の幅400ピクセル」・「縦の高さ100ピクセル」にサイズ変更しています。
また、1文字を「横の幅:各100ピクセル」・「縦の高さ:各100ピクセル」とした4桁を想定したプログラムになっています。
そのため、サイズ変更した際に、文字が小さすぎると、うまく認識できません。
今後実際に認識させたい画像に合わせて、輪郭をカットする設定
if not 40 < w < 130:
continue
if not 60 < h < 120:
continue
の数値を変更してみてください。
画像認識用のサンプル画像のダウンロードはこちら。ローカル環境で圧縮ファイルを解凍後に、画像ファイルだけをアップロードします。
文字検出・判定用のデジタル数字画像認サンプル画像
7セグメントのデジタル数字画像認識評価用サンプル画像です。
1桁〜4桁以上の画像などがあります。
④ 7セグメントデジタル数字の文字検出 & 画像判定に挑戦。
デフォルトでは、
・モノクロ・グレースケールのカラー設定
・横の幅28・縦の高さ28ピクセル
の学習済みモデル(Kerasで作成)を利用するプログラムになっています。
また、
・画像のカラーモード – モノクロ・グレースケール
・学習時の画像の大きさ – 横の幅28・縦の高さ28ピクセル
の「model.h5」という名前の学習済みモデルを利用するプログラムになっています。
カラー版の学習済みモデルを使う場合は、「2. 画像判定のためのプログラム」内の、「color_setting = 1」を「color_setting = 3」に変更します。
自作の学習済みモデルを使う場合などは、「model = load_model(‘model.h5‘)」の「model.h5」の名前を自作の学習済みモデルのファイル名に変更して使ってください。
上述のプログラム
Keras_CNN_7segment_digits_originaldataset.ipynb | Google Colaboratory共有ファイル
(7セグメントのデジタル数字のオリジナル学習済みモデルを作成)
を使うと、オリジナルデータセットで学習済みモデルの作成や、モデルの再学習をすることができます。
上記のノートブックに掲載してある無料公開中のサンプルのオリジナルデータセットの画像では、モノクロ・グレースケールで学習済みモデルを作成した際には、文字検出した「1」「5」の認識がしにくいようでした。
また、カラー版は、「0」と「2」と「4」が認識しにくいようでした。間違えた画像を各2枚ほど追加して再学習させるとうまくいくようでした。
サンプルの学習済みモデルも無料公開中ですので、以下のリンク先でダウンロード後に、「〜.h5」のファイルをアップロードして使ってください。
サンプルの学習済みモデル「〜.h5」ファイルのダウンロードはこちら
カラー版の学習済みモデル
画像設定:カラー
大きさの設定:横の幅28 * 縦の高さ28ピクセル
python 3.6.9
tensoflow 2.4.1
keras 2.4.3
ランタイム:GPU
デジタル数字画像認サンプル画像
7セグメントのデジタル数字画像認識評価用サンプル画像です。
1桁〜4桁の画像があります。
* 区別がつきやすいように長い名前がついていますが、使う際は「model.h5」の名前に変更して使うと楽です。
デフォルトでは「model.h5」を読み込むプログラムを記述しています。
サンプルコード
# OCRする画像
input_file = '1234.png' #ここを変更。OCRしたい画像のファイル名を入力します。
#### 1. デジタル数字検出のためのプログラム ####
# 輪郭検出・抽出のためのインポート
import cv2
import numpy as np
import matplotlib.pyplot as plt
from imutils import contours
# 画像から数字の領域を抽出する処理
def find_draw_contours (input_file):
# 画像の読み込み
img = cv2.imread(input_file)
# 画像のリサイズ。4桁の数字を想定。1桁ごとに縦横100ピクセル
img = cv2.resize(img, (400, 100)) # 縦の高さ400ピクセル・横の幅 100ピクセルにリサイズ。
# モノクロ・グレースケール画像へ変換(2値化前の画像処理)
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 2値化(Binarization):白(1)黒(0)のシンプルな2値画像に変換
retval, img_binary = cv2.threshold(img_gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
# 白部分の膨張処理(Dilation):モルフォロジー変換 - 2値画像を対象
kernel = np.ones((5,5),np.uint8) # カーネル(構造的要素):全要素の値が1の縦横5ピクセルのカーネル
img_dilation = cv2.dilate(img_binary,kernel,iterations = 1) #「iterations=」繰り返し膨張処理を行う回数を指定
# 解説用のコメント(2値化)
print('\n【2値化処理画像 - Binarization】')
print(' 画像の2値化と白部分の膨張をさせることで、途切れているデジタル数字を1文字として検出しやすいようにしています。')
print(' この段階で、数字が「白」として処理できていないと輪郭の検出がしにくいようでした。')
# 膨張処理後の2値化画像の表示
plt.imshow(cv2.cvtColor(img_dilation, cv2.COLOR_BGR2RGB))
plt.show()
# 輪郭の検出
#「findContours」の返り値「cnts(contours)」は輪郭毎の座標組・「hierarchy」は輪郭の階層構造
#「cv2.RETR_EXTERNAL」:最も外側の輪郭を返す
#「cv2.CHAIN_APPROX_SIMPLE」:輪郭上の全点の情報を保持しない。輪郭の情報を圧縮
cnts, hierarchy = cv2.findContours(img_dilation, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 輪郭の並べ替え(左から右へ並べる)
cnts, hierarchy = contours.sort_contours(cnts, method='left-to-right')
# ROI(Region of Interest:興味領域・対象領域)抽出用の初期設定
ROI_index = 0
# 抽出した輪郭を「x, y, w(横の幅), h(縦の高さ)」の単純なリストに変換
result = []
for contour in cnts:
x, y, w, h = cv2.boundingRect(contour) # 外接矩形の左上の位置は(x,y),横の幅と縦の高さは(w,h)
# 大きすぎる小さすぎる領域を除去。処理する画像サイズに合わせて微調整が必要
# 以下は縦の高さ400ピクセル・横の幅 100ピクセルの画像を想定。
# if not 40 < w < 130 ・ 60 < h < 120: # 横の幅の範囲40〜130ピクセル・縦の高さの範囲60〜120ピクセルの輪郭を残す
if not 40 < w < 130:
continue
if not 60 < h < 120: #輪郭の描画は画像サイズを超えることもあるようでした。
continue
# ROI抽出:画像の切り抜きと保存
ROI = img[y:y+h, x:x+w]
cv2.imwrite('ROI_img{}.png'.format(ROI_index), ROI)
ROI_index += 1
#resultに要素を追加
result.append([x, y, w, h])
# 画面に矩形の輪郭を描画 (描画機能:for〜cv2.rectangleまでの2行をコメントアウト、または削除すると輪郭の描画を無効にできます)
for x, y, w, h in result:
cv2.rectangle(img, (x, y), (x+w, y+h), (100, 255, 100), 1) # 色の指定はRGB(100, 255, 100)。「1」は 太さ。数字を大きくすると太い輪郭が描画される。
# 解説用のコメント(輪郭検出・抽出)
print('\n【輪郭検出・抽出結果 - Contours】')
print(' 枠が大きすぎる場合・小さすぎる場合には輪郭を除去しています。画像によって微調整する必要があります。')
print(' 輪郭検出は、ディスプレイ背景の光の加減による濃淡や、機器の色などが入ると検出しにくくなるようでした。')
print(' 輪郭検出を成功させるためには、「ディスプレイ表示画面」のみで「ディスプレイの縦横の範囲が最小限」の場合に検出しやすいようでした。')
# 輪郭検出・抽出結果の表示
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.savefig('digit-pick.png', dpi=300) # 抽出結果の画像ファイルも保存しています。「dpi」は何も指定しないと dpi=72
plt.show()
return result, img, ROI_index
#### 2. 画像判定のためのプログラム ####
# Kerasの学習済みモデルを読み込みむためのインポート
from keras.models import load_model
# 学習済みモデルの読み込み
model = load_model('model.h5') # ここを変更。ここに学習済みモデルを入れます
# 学習済みモデルの画像のカラー設定には「モノクロ・グレースケール」「カラー」があります
# 画像の各種設定
folder = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ''] # 空白の表示に対応させるため、blankのところを「' '」で空白に設定
image_width = 28 # 使用する学習済みモデルと同じwidth(横幅)を指定
image_height = 28 # 使用する学習済みモデルと同じheight(縦の高さ)を指定
color_setting = 1 # ここを変更。学習済みモデルと同じ画像のカラー設定にする。モノクロ・グレースケールの場合は「1」。カラーの場合は「3」
# 画像から領域を読み込む
cnts, img, ROI_index = find_draw_contours(input_file)
# 解説用コメント
print('\n【画像の判別結果 - Prediction】デフォルトではグレースケールの画像を判定できます。')
print(' 「color_setting = 3」に変更するとカラー版の学習済みモデルにも対応できます。 \n')
print(' 7セグメント連続数字画像の認識結果(予測結果): \n')
# 読み込んだ画像データを予測
for i, contour in enumerate(cnts):
x, y, w, h = contour
# 画像データを取り出す
img_extraction = img[y:y+h, x:x+w]
# データを学習済みモデルのデータに合わせる
if color_setting == 1:
gazou = cv2.cvtColor(img_extraction, cv2.COLOR_BGR2GRAY)
elif color_setting == 3:
gazou = cv2.cvtColor(img_extraction, cv2.COLOR_BGR2RGB)
gazou = cv2.resize(gazou, (image_width, image_height))
suuti = gazou.reshape(image_width, image_height, color_setting).astype('float32')/255
# 予測する
n = model.predict(np.array([suuti]))
# 画面に結果を表示
plt.subplot(1, ROI_index, i + 1)
plt.imshow(cv2.cvtColor(img_extraction, cv2.COLOR_BGR2RGB))
plt.axis('off')
plt.title(folder[n.argmax()] )
print(folder[n.argmax()] , end=' ') #横一列に表示させるため「, end=' '」を追加
plt.show()
# 解説用コメント
print('↑ 今回認識した元の画像から抽出された画像と「判定結果」:輪郭検出ができていない場合は、何も出力されません。')
print('\n * 間違えた画像がある場合は、ROI(Region of Interest)抽出した「ROI_img〜.png」という(枠線なしの)画像ファイルが保存されているので該当画像を探して、再学習してみてください。')
print(' * 輪郭検出の際に描画した枠の線が太いと、画像の認識精度が落ちるようでした。必要に応じて細くしたり、描画機能をコメントアウトして無効化してください。')
print(' * 画像によっては輪郭検出がうまくいかない場合もあるようでした。その際は、画像のサイズや撮影方法の再考、輪郭検出の設定の微調整が必要そうでした。')
print(' * ちょっとした撮影方法や画像の切り抜きの状態によって、輪郭検出の結果が変化するので奥深いですね。')
print(' * 何度もプログラムを実行すると「WARNING:tensorflow:〜」が出ることもあるようでしたが、結果は正常に出力されるようでした。')
#### 3.出力した画像ファイル削除のためのプログラム ####
# 「3」のプログラムをコメントアウト(または削除)すると間違えた画像ファイルを再学習用に使えます。
import glob
import os
file_list = glob.glob("ROI_img*png")
for file in file_list:
os.remove(file)
⑤ 再学習。
認識に失敗した画像(ROI_img〜.pngなど)を、オリジナルデータセットに追加して再学習。
色などを若干変えて2枚ほどデータセットに追加するだけで、結果が変わってくるようでした。
以下のプログラムで再学習できます。
Keras_CNN_7segment_digits_originaldataset.ipynb | Google Colaboratory 共有ファイル
(ファイル – ドライブにコピーを保存後にコピー環境で実行)
後は、画像サイズや撮影方法、輪郭をカットする基準などを試行錯誤し、実践活用。
【応用例】7セグメント自動文字検出OCRプログラム
嬉しいことに、今回のプログラムを活用して、自作のプログラムをラズパイで動かしている方がいらっしゃいましたので、リンクを掲載させていただきます。
・ラズパイ4B 64bitに Tensorflow 2.4.1とkeras2.4.3を入れ、7セグ画像から数値を取得する(その1) – @yoroyasu 2021年4月21日投稿 | Qiita
OCRプログラムを学習中の方の中には、ラズベリーパイ(ラズパイ)で実装してみたい方も多いのではないかと思います。まだまだ課題もあるようですが、今後の投稿も楽しみですね。
:【4桁 – 7セグメント編】連続デジタル数字画像認識プログラミング入門講座(Python・OpenCV・Keras・CNN)| 一覧ページ
:【日本語手書きOCR編】連続文字画像認識プログラミング入門(Python・OpenCV・Keras・CNN)
:【Python等】OCRプログラミング入門講座 | 一覧ページ
【音声認識】
:【Python入門】日本語の文字起こしのやり方(音声認識:音声ファイル編)サンプルコード
【音声合成】
1件のコメント
現在コメントは受け付けていません。