動画:【4桁 – 7セグメント編】連続デジタル数字画像認識プログラミング入門(Python・OpenCV・Keras・CNN)
【Python機械学習入門】高精度の自作OCRを作ろう
7セグメントデジタル連続数字画像認識AI:1桁〜4桁 – 静止画トリミング編(7 Segment Digits Training)
視聴時間:30分36秒
使い方がわからない方は動画の該当箇所をご視聴いただけますと幸いです。
【動画の内容】
0:00 はじめに – 7セグメントデジタル数字OCRについて
3:14 ステップ1 – 学習済みモデルの作成
9:58 ステップ2 – 1文字判定 7セグメントデジタル数字
16:24 ステップ3 – 1桁〜4桁の連続文字認識+再学習 ← ここ
29:14 おわりに – AIを賢く
機械学習モデルのディープラーニング(深層学習)でおなじみの「畳み込みニューラルネットワーク」(CNN:Convolutional Neural Network)で、7セグメントのデジタル数字画像のオリジナルデータセットで作成した学習済みモデルを使って、1〜4桁の連続した数字画像認識ができる簡単なプログラムを作成してみました。静止画像をトリミングして、4枚の各画像を判定した結果を、まとめて1桁〜4桁の数字として出力させます。
既存のOCRプログラムで7セグメントのデジタル数字認識をしてみても、思ったよりも上手く行かない経験をされる方もいるのではないかと思います。
一連のプログラムが、これから、計量器や時計、温度計をはじめとしたデジタル数字認識に挑戦したい方の参考になることがありましたら幸いです。
7 Segment Edition(Seven Segment Edition)
:How to Create an Original OCR.
Introduction to Continuous Digital Number Display Image Recognition Python Programming.
今回のプログラムは、以前投稿させていただいた
:【4桁】連続数字画像認識プログラミング入門(Python・OpenCV・SVM)
の手書き連続数字画像認識プログラムを改変して作っています。
基本的な構造は似ていますが、やはりディープラーニングの方が精度は良さそうです。
【追記:2022年1月16日】
CSV形式のファイルに、出力結果を保存できるサンプルコードも公開しておきました。
CSV形式ファイルに結果を保存版【1〜4桁:7セグメントのデジタル数字認識用:Pythonサンプルコード】
のコードを参照ください。
学習済みモデル・サンプル画像・サンプルコードリンク: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_4digits-recognition.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.
【1〜4桁:7セグメントのデジタル数字認識用:Pythonサンプルコード】
KerasでCNN機械学習。自作・自前画像のオリジナルデータセットで画像認識入門
【7セグメントのデジタル数字画像認識 – 4桁の連続数字認識(連続文字認識)】
400 × 100(横400 × 縦100ピクセル)の画像を4等分し、個別に認識した結果をまとめて表示させることで1〜4桁の連続数字を認識できるプログラムです。何も数字がない場合には、数値が出力されないようになっています。
学習データは、実際に使う7セグメントディスプレイ画像(デジタルメーターの画像)を撮影した物を使って学習を繰り返すと、デジタルの数字の認識精度が上がるのではないかと思います。
・機械学習モデル:CNN(Convolutional Neural Network:畳み込みニューラルネットワーク)
・データセット:オリジナルの7セグメントのデジタル数字画像で作成
こちらに公開しているプログラム
Keras_CNN_7segment_digits_originaldataset.ipynb | Google Colaboratory共有ファイル
(7セグメントのデジタル数字のオリジナル学習済みモデルを作成)
を使うと、オリジナルデータセットでモデルを再学習することができます。
実際に認識させていく中で、間違えた画像をデータセットに追加し、再学習することで実際の正解率が向上していくのではないかと思います。
一連のサンプルコードでは、学習済みモデルの学習回数は僅かで、基本的な画像の前処理しか行っていませんでしたが、自分が目的とするデジタル数字画像の判定結果はまずまずでした。
バージョン情報(Python・各種ライブラリ)
python 3.6.9
tensoflow 2.4.1
keras 2.4.3
opencv(opencv-python)4.1.2
matplotlib 3.2.2
ローカル環境で、指定したバージョンのインストールが難しい場合、Python・TensorFlow・Keras以外は最新のバージョンを入れてみてください。
① 学習済みモデルの準備。
以下のプログラムで作成できます。「〜.h5」という名前のファイルを作成できます。
Keras_CNN_7segment_digits_originaldataset.ipynb | Google Colaboratory共有ファイル
② 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ピクセル」にサイズ変更し横の幅を4等分(100ピクセルごとに分ける)しています。
そのため、横の幅を4等分した際に、認識させたい7セグメントの数字の画像が入っていないと、うまく認識できません。
今後実際に認識させたい画像サイズに合わせて画像のサイズやトリミング範囲を変更してみてください。
サンプル画像のダウンロードはこちら
:ダウンロード:判定用1桁〜4桁の7セグメントのデジタル数字画像
④ 7セグメントデジタル数字の画像判定に挑戦
デフォルトでは、
・モノクロ・グレースケールのカラー設定
・横の幅28・縦の高さ28ピクセル
の学習済みモデル(Kerasで作成)を利用するプログラムになっています。
【OpenCVの座標系とトリミングの関係】
import cv2
import matplotlib.pyplot as plt
import numpy as np
from keras.models import load_model
#画像の読み込みとリサイズ(画像を横の幅400・高さ100ピクセルにリサイズ)
img = cv2.imread('869.png') # ここに数字画像認識をしたい画像を入れます。事前に4等分を考慮して撮影した画像を利用
img = cv2.resize(img, (400, 100)) # サイズが調整されていない画像を入れた場合のエラー予防
#img = cv2.resize(img, (800, 200)) # 画像を横の幅800・高さ200ピクセルにリサイズするプログラム例
# 画像のトリミング [y1:y2, x1:x2] (img = cv2.resize(img, (400, 100)) を使った場合のプログラム例
data1 = img[0:100, 0:100] #yの範囲(縦)が0〜100・xの範囲(横)が0〜100までをトリミング
data2 = img[0:100, 100:200] #yの範囲(縦)が0〜100・xの範囲(横)が100〜200までをトリミング
data3 = img[0:100, 200:300] #yの範囲(縦)が0〜100・xの範囲(横)が200〜300までをトリミング
data4 = img[0:100, 300:400] #yの範囲(縦)が0〜100・xの範囲(横)が300〜400までをトリミング
#(img = cv2.resize(img, (800, 200)) を使った場合のプログラム例
#data1 = img[0:200, 0:200] #yの範囲(縦)が0〜200・xの範囲(横)が0〜200までをトリミング
#data2 = img[0:200, 200:400] #yの範囲(縦)が0〜200・xの範囲(横)が200〜400までをトリミング
#data3 = img[0:200, 400:600] #yの範囲(縦)が0〜200・xの範囲(横)が400〜600までをトリミング
#data4 = img[0:200, 600:800] #yの範囲(縦)が0〜200・xの範囲(横)が600〜800までをトリミング
# トリミングした画像を保存
cv2.imwrite('data1.png', data1)
cv2.imwrite('data2.png', data2)
cv2.imwrite('data3.png', data3)
cv2.imwrite('data4.png', data4)
# 学習済みモデルの読み込み
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」 。
cv2_color_setting = 0 # 学習済みモデルと同じ画像のカラー設定にする。cv2.imreadではモノクロ・グレースケールの場合は「0」。カラーの場合は「1」 。
# 4桁目の画像の数値リスト化(データ化)と予測
gazou = cv2.imread('data1.png', cv2_color_setting)
gazou = cv2.resize(gazou, (image_width, image_height))
suuti = gazou.reshape(image_width, image_height, color_setting).astype('float32')/255
n1 = model.predict(np.array([suuti]))
n1 = n1[0]
# 3桁目の画像の数値リスト化(データ化)と予測
gazou = cv2.imread('data2.png', cv2_color_setting)
gazou = cv2.resize(gazou, (image_width, image_height))
suuti = gazou.reshape(image_width, image_height, color_setting).astype('float32')/255
n2 = model.predict(np.array([suuti]))
n2 = n2[0]
# 2桁目の画像の数値リスト化(データ化)と予測
gazou = cv2.imread('data3.png', cv2_color_setting)
gazou = cv2.resize(gazou, (image_width, image_height))
suuti = gazou.reshape(image_width, image_height, color_setting).astype('float32')/255
n3 = model.predict(np.array([suuti]))
n3 = n3[0]
# 1桁目の画像の数値リスト化(データ化)と予測
gazou = cv2.imread('data4.png', cv2_color_setting)
gazou = cv2.resize(gazou, (image_width, image_height))
suuti = gazou.reshape(image_width, image_height, color_setting).astype('float32')/255
n4 = model.predict(np.array([suuti]))
n4 = n4[0]
#結果の表示(個別に認識した結果を、4桁目から順番に並べています。予測確率が高い数字を表示させています)
print('7セグメント連続数字画像の認識結果(予測結果):\n\n', folder[n1.argmax()], folder[n2.argmax()], folder[n3.argmax()], folder[n4.argmax()])
print('\n\n【今回認識した元の画像】')
# 元の画像を4分割でトリミングした画像の表示:複数の画像を表示させる
img_list=[data1, data2, data3, data4]
for bangou, imagenamae in enumerate(img_list):
plt.subplot(2, 4, bangou+1) #(行数,列数,何番目に画像を表示させるか)
plt.axis("off") #画像の軸をオフ
plt.title('data' +str(bangou+1))
plt.imshow(cv2.cvtColor(imagenamae, cv2.COLOR_BGR2RGB))
print(‘7セグメント連続数字画像の認識結果(予測結果):\n\n’, folder[n1.argmax()], folder[n2.argmax()], ‘.’ ,folder[n3.argmax()], folder[n4.argmax()])
などとプログラムを変更すると小数点や文字を入れられます。
⑤ 再学習。
認識に失敗した画像(data1.pngなど)を、オリジナルデータセットに追加して再学習。
色などを若干変えて2枚ほどデータセットに追加するだけで、結果が変わってくるようでした。
以下のプログラムで再学習できます。
Keras_CNN_7segment_digits_originaldataset.ipynb | Google Colaboratory 共有ファイル
(ファイル – ドライブにコピーを保存後にコピー環境で実行)
後は②〜⑤の手順を繰り返し、実践活用。
【動画で解説】CSVファイルにOCR・画像認識の出力結果のテキストデータを保存・追加(7セグメントのデジタル数字編)
【Python機械学習入門】
CSVファイルにOCR・画像認識の出力結果のテキストデータを保存・追加
(7セグメントのデジタル数字編)
視聴時間:8分2秒
以下の、「CSV形式ファイルに結果を保存版【1〜4桁:7セグメントのデジタル数字認識用:Pythonサンプルコード】」の使い方の解説動画です。
記事だけでは、わからない場合に参照いただけますと幸いです。
CSV形式ファイルに結果を保存版【1〜4桁:7セグメントのデジタル数字認識用:Pythonサンプルコード】
【CSV形式ファイルなどに1〜4桁の7セグメントのデジタル数字画像認識した出力結果を保存できるプログラム】
「出力結果を保存して、自動化・・・・」
などと業務効率化を考えている方もいるのではないかと思います。
一連の処理を自動化するためには、いくつかのステップが必要ですが、出力した結果を、何かしらのファイルに保存・追加できる状態までのプログラムがわかっている状態であれば、自動化へ向けてのモチベーションはあがりますね。
1桁なら、比較的簡単にCSV形式のファイルに保存して使えるのではないかと思いますが、数桁になると、頭を使わないと1つのセル内に出力結果がまとまらずに、思い通りの自動化ができない経験をされている方も多いのではないかと思います。
以前、他のプログラムのチュートリアル動画に、結果を保存する方法について質問を頂いていましたが、ようやく関連するプログラムをまとめることができました。
コメントくださった方は、「スプレッドシート」への出力でしたが、Googleスプレッドシートでは、CSV形式のファイルもインポートできるようでしたので、今回はとりあえずCSV形式で出力する方法をまとめておきます。
出力結果をまとめて保存できると、面白いですね。
import cv2
import matplotlib.pyplot as plt
import numpy as np
from keras.models import load_model
#画像の読み込みとリサイズ(画像を横の幅400・高さ100ピクセルにリサイズ)
img = cv2.imread('869.png') # ここに数字画像認識をしたい画像を入れます。事前に4等分を考慮して撮影した画像を利用
img = cv2.resize(img, (400, 100)) # サイズが調整されていない画像を入れた場合のエラー予防
#img = cv2.resize(img, (800, 200)) # 画像を横の幅800・高さ200ピクセルにリサイズするプログラム例
# 画像のトリミング [y1:y2, x1:x2] (img = cv2.resize(img, (400, 100)) を使った場合のプログラム例
data1 = img[0:100, 0:100] #yの範囲(縦)が0〜100・xの範囲(横)が0〜100までをトリミング
data2 = img[0:100, 100:200] #yの範囲(縦)が0〜100・xの範囲(横)が100〜200までをトリミング
data3 = img[0:100, 200:300] #yの範囲(縦)が0〜100・xの範囲(横)が200〜300までをトリミング
data4 = img[0:100, 300:400] #yの範囲(縦)が0〜100・xの範囲(横)が300〜400までをトリミング
#(img = cv2.resize(img, (800, 200)) を使った場合のプログラム例
#data1 = img[0:200, 0:200] #yの範囲(縦)が0〜200・xの範囲(横)が0〜200までをトリミング
#data2 = img[0:200, 200:400] #yの範囲(縦)が0〜200・xの範囲(横)が200〜400までをトリミング
#data3 = img[0:200, 400:600] #yの範囲(縦)が0〜200・xの範囲(横)が400〜600までをトリミング
#data4 = img[0:200, 600:800] #yの範囲(縦)が0〜200・xの範囲(横)が600〜800までをトリミング
# トリミングした画像を保存
cv2.imwrite('data1.png', data1)
cv2.imwrite('data2.png', data2)
cv2.imwrite('data3.png', data3)
cv2.imwrite('data4.png', data4)
# 学習済みモデルの読み込み
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」 。
cv2_color_setting = 0 # 学習済みモデルと同じ画像のカラー設定にする。cv2.imreadではモノクロ・グレースケールの場合は「0」。カラーの場合は「1」 。
# 4桁目の画像の数値リスト化(データ化)と予測
gazou = cv2.imread('data1.png', cv2_color_setting)
gazou = cv2.resize(gazou, (image_width, image_height))
suuti = gazou.reshape(image_width, image_height, color_setting).astype('float32')/255
n1 = model.predict(np.array([suuti]))
n1 = n1[0]
# 3桁目の画像の数値リスト化(データ化)と予測
gazou = cv2.imread('data2.png', cv2_color_setting)
gazou = cv2.resize(gazou, (image_width, image_height))
suuti = gazou.reshape(image_width, image_height, color_setting).astype('float32')/255
n2 = model.predict(np.array([suuti]))
n2 = n2[0]
# 2桁目の画像の数値リスト化(データ化)と予測
gazou = cv2.imread('data3.png', cv2_color_setting)
gazou = cv2.resize(gazou, (image_width, image_height))
suuti = gazou.reshape(image_width, image_height, color_setting).astype('float32')/255
n3 = model.predict(np.array([suuti]))
n3 = n3[0]
# 1桁目の画像の数値リスト化(データ化)と予測
gazou = cv2.imread('data4.png', cv2_color_setting)
gazou = cv2.resize(gazou, (image_width, image_height))
suuti = gazou.reshape(image_width, image_height, color_setting).astype('float32')/255
n4 = model.predict(np.array([suuti]))
n4 = n4[0]
#結果の表示(個別に認識した結果を、4桁目から順番に並べています。予測確率が高い数字を表示させています)
print('7セグメント連続数字画像の認識結果(予測結果):\n\n', folder[n1.argmax()], folder[n2.argmax()], folder[n3.argmax()], folder[n4.argmax()])
#### はじめ:CSVファイルに出力結果を追加するための処理を追加 ####
# CSVファイルに出力結果を追加
# コード内の「OCR_OUTPUT.csv」のところを「OCR_OUTPUT.txt」にするとテキストファイル形式にできます
import csv
from pathlib import Path
def print_output():
print(Path('OCR_OUTPUT.csv').read_text())
# 「OCR_OUTPUT.csv」(ヘッダー名:OCR_OUTPUT)というファイルの作成と出力結果の保存
# ここの処理では、各桁の出力結果が各セルに分散されている状態(例:「4, 5, 0, 8」などとコンマで区切られている状態)
with open('OCR_OUTPUT.csv', 'a', newline='') as f:
writer = csv.writer(f)
writer.writerow([folder[n1.argmax()], folder[n2.argmax()], folder[n3.argmax()], folder[n4.argmax()]])
print('\n\n【CSVファイルへ保存するための処理】(OCR_OUTPUT.csv)')
print('\n[保存処理中・・・]\n新たな出力結果に関しては「,」(コンマ)の処理が未実施の状態\n')
print_output()
#CSVファイルの出力結果から「,」(コンマ)を削除し、1つのセル内に出力結果を表示
ocr_output_file = 'OCR_OUTPUT.csv'
with open(ocr_output_file) as f:
data_lines = f.read()
# 文字を置換:「,」(コンマ)を「」(空白)に置換することで「,」を削除
data_lines = data_lines.replace(',', '')
# 読み込んだファイル名のまま保存
with open(ocr_output_file, mode="w") as f:
f.write(data_lines)
print('\n[保存完了]\n新たな出力結果に対して「,」(コンマ)を削除し、1セル内に結果をまとめる処理を実行\n')
print_output()
#### ここまで:CSVファイルに出力結果を追加するための処理を追加 ####
print('\n\n【今回認識した元の画像】')
# 元の画像を4分割でトリミングした画像の表示:複数の画像を表示させる
img_list=[data1, data2, data3, data4]
for bangou, imagenamae in enumerate(img_list):
plt.subplot(2, 4, bangou+1) #(行数,列数,何番目に画像を表示させるか)
plt.axis("off") #画像の軸をオフ
plt.title('data' +str(bangou+1))
plt.imshow(cv2.cvtColor(imagenamae, cv2.COLOR_BGR2RGB))
出力結果
認識結果(予測結果): 869
【出力結果の保存】
文字検出機能付きのオリジナルOCRを作ろう
また、文字検出機能付きのオリジナルOCRを自作できるプログラムも公開しました。
OCRの学習にお役立てください。
試してみた感じでは、サンプルのオリジナルデータセットでは、いくつかの数字の誤判定があるようでした。間違えた数字をそれぞれ2枚ほどオリジナルデータセットに追加して再学習させると、高精度のOCRが作れそうでした。
(現在公開中のサンプル学習済みモデルは、数字文字検出・判定用のサンプル画像の判定を全てクリアできるように再学習し直しています:間違え画像をデータセットに2枚追加しただけです)
無料でこんなことができるなんて、すごい時代ですね 😃
【ステップ3−1:7セグメントデジタル数字文字検出】
–【7セグメント編】デジタル数字文字検出(物体検出):画像の2値化・膨張処理・輪郭検出枠のカット設定
【ステップ3−2:7セグメントデジタル数字文字検出・抽出オリジナルOCR】
–【7セグメント編 – 自動文字検出・抽出OCR】連続文字判定(デジタル数字:1〜4桁以上の連続数字)+再学習
:【4桁 – 7セグメント編】連続デジタル数字画像認識プログラミング入門講座(Python・OpenCV・Keras・CNN)| 一覧ページ
:【Python等】OCRプログラミング入門講座 | 一覧ページ
【音声認識】
:【Python入門】日本語の文字起こしのやり方(音声認識:音声ファイル編)サンプルコード
【音声合成】