【4桁】連続数字画像認識プログラミング入門(Python・OpenCV・SVM)

【4桁】連続数字画像認識プログラミング入門(Python・OpenCV・SVM)

 

動画:【4桁に挑戦】手書き連続数字画像認識プログラミング入門(Python・OpenCV・SVM)

 


視聴時間:2分36秒

機械学習モデルのサポートベクターマシーン(SVM:support vector machine)で手書き数字画像を学習後、800 × 200(横800 × 縦200)の画像に4等分に数字が配置されている場合に活用できる、4桁の数字を認識できる簡単なプログラムを作成してみました。

 




 

【追記:2021年3月3日】

初期のコードは、力ずくな感じのするプログラムでしたが、予測する処理を関数化しfor文でシンプルなプログラムにしたコードも追加しておきました。日々の学習にお役立てください。

 

今回のプログラムは、以前YouTubeに投稿させていただいた以下の数字画像認識プログラムを改変して作っています。
興味のある方は、併せてご活用ください。

Pythonで機械学習・人工知能(AI)プログラミング入門 | scikit-learn SVM 学習データの確認〜画像認識(数値予測)編 by RehabC – デジタルで遊ぶ。(YouTube動画)

 

 

サンプル画像・サンプルコードリンク:手書き連続数字画像認識プログラム

 

【4桁】連続数字画像認識プログラミング入門(Python・OpenCV・SVM)で試せるサンプル画像です。
動画のデモで利用した画像です。

 

すぐに使えるGoogle Colaboratoryサンプルコードリンク

SVM-4digits-recognition.ipynb | Google Colaboratory
(手書き連続数字画像認識プログラム)

 

数字画像認識 – 4桁の連続数字認識(連続文字認識):
800 × 200(横800 × 縦200)の画像を4等分し、個別に認識した結果をまとめて表示させることで4桁の連続数字を認識できるプログラムです。

print(‘認識結果(予測結果):’, int(n1), int(n2), ‘.’ ,int(n3), int(n4))
などとプログラムを変更すると小数点も入れられます。

学習データが手書き数字文字のため、デジタルの数字(7セグメント)は認識しにくいかもしれません。
追記 – はじめ
2021年2月12日 CNNで7セグメントのオリジナル学習済みモデルを作成できるプログラムなどを作成中です。お楽しみに♪

7セグメントのデジタル数字画像認識プログラム - 4桁の連続数字認識(連続文字認識)
2021年2月13日にとりあえずの形はできました。
今後チュートリアルを作ります。

→ 2021年2月14日 記事を公開しました。
【4桁 – 7セグメント編】連続デジタル数字画像認識プログラミング入門(Python・OpenCV・Keras・CNN)

追記 – おわり
 

・機械学習モデル:SVM(Support Vector Machine:サポートベクターマシン )
・データセット:手書き数字画像

 

 

バージョン情報(Python・各種ライブラリ)

 

 

python 3.6.9
sklearn(scikit-learn)0.22.2.post1
opencv-python 4.1.2
PIL 7.0.0
matplotlib 3.2.2

ローカル環境で、指定したバージョンのインストールが難しい場合、Python以外は最新のバージョンを入れてみてください。

 

 

【プログラムのライセンス】

 

 

The MIT License

Copyright 2020 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.

 

 

初期のプログラム【4桁の手書き連続数字画像認識プログラム:Pythonサンプルコード】

 

 

OpenCVの座標系とトリミングの関係

 

import sklearn.datasets
import sklearn.svm
import numpy
import PIL.Image
import matplotlib.pyplot as plt
import cv2

# 画像の読み込みとリサイズ(画像を横の幅800・高さ200ピクセルにリサイズする場合のプログラム例です)
img = cv2.imread('4508_800*200.png') #ここに数字画像認識をしたい画像を入れます(事前に4等分を考慮して撮影した画像を利用)
img = cv2.resize(img, (800,  200)) # サイズが調整されていない画像を入れた場合のエラー予防を追加
#img = cv2.resize(img, (400,  100)) 


# 画像のトリミング [y1:y2, x1:x2]  (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までをトリミング

#(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までをトリミング


# トリミングした画像を保存
cv2.imwrite('data1.png', data1)
cv2.imwrite('data2.png', data2)
cv2.imwrite('data3.png', data3)
cv2.imwrite('data4.png', data4)


# 4桁目の画像の数値リスト化(データ化)と、手書き数字のデータセットでの学習と予測
gazou = PIL.Image.open('data1.png').convert("L")
gazou = gazou.resize((8,8),PIL.Image.ANTIALIAS)
suuti = numpy.asarray(gazou, dtype = float)
suuti = numpy.floor(16 - 16 * (suuti / 256))
suuti = suuti.flatten()

suuji = sklearn.datasets.load_digits()
ai = sklearn.svm.SVC(gamma = 0.001)
ai.fit(suuji.data, suuji.target)
n1 = ai.predict(suuti.reshape(1, -1))


# 3桁目の画像の数値リスト化(データ化)と予測
gazou = PIL.Image.open('data2.png').convert("L")
gazou = gazou.resize((8,8),PIL.Image.ANTIALIAS)
suuti = numpy.asarray(gazou, dtype = float)
suuti = numpy.floor(16 - 16 * (suuti / 256))
suuti = suuti.flatten()

n2 = ai.predict(suuti.reshape(1, -1))


# 2桁目の画像の数値リスト化(データ化)と予測
gazou = PIL.Image.open('data3.png').convert("L")
gazou = gazou.resize((8,8),PIL.Image.ANTIALIAS)
suuti = numpy.asarray(gazou, dtype = float)
suuti = numpy.floor(16 - 16 * (suuti / 256))
suuti = suuti.flatten()

n3 = ai.predict(suuti.reshape(1, -1))


# 1桁目の画像の数値リスト化(データ化)と予測
gazou = PIL.Image.open('data4.png').convert("L")
gazou = gazou.resize((8,8),PIL.Image.ANTIALIAS)
suuti = numpy.asarray(gazou, dtype = float)
suuti = numpy.floor(16 - 16 * (suuti / 256))
suuti = suuti.flatten()

n4 = ai.predict(suuti.reshape(1, -1))

# 結果の表示(個別に認識した結果を4桁目から順番に並べています)
print('認識結果(予測結果):', int(n1), int(n2), int(n3), int(n4))

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)) 

 

出力結果

 

出力結果:初期のプログラム【4桁の手書き連続数字画像認識プログラム:Pythonサンプルコード】

 

 

改変したプログラム【4桁の手書き連続数字画像認識プログラム:Pythonサンプルコード】

 

 

OpenCVの座標系とトリミングの関係

 

関数化してfor文で結果を出力させる際に、それぞれの認識結果が縦に出力されるのが難点でしたが、「end=’ ‘」の記述で横一列に出力できることがわかったので上記のコードをシンプルに改変しておきました。
これで見た目がスッキリしましたね。

 

import sklearn.datasets
import sklearn.svm
import numpy
import PIL.Image
import matplotlib.pyplot as plt
import cv2

# 画像の読み込みとリサイズ(画像を横の幅800・高さ200ピクセルにリサイズする場合のプログラム例です)
img = cv2.imread('9638_800*200.png') #ここに数字画像認識をしたい画像を入れます(事前に4等分を考慮して撮影した画像を利用)
img = cv2.resize(img, (800,  200)) # サイズが調整されていない画像を入れた場合のエラー予防を追加
#img = cv2.resize(img, (400,  100)) 


# 画像のトリミング [y1:y2, x1:x2]  (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までをトリミング

#(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までをトリミング


# トリミングした画像を保存
cv2.imwrite('data1.png', data1)
cv2.imwrite('data2.png', data2)
cv2.imwrite('data3.png', data3)
cv2.imwrite('data4.png', data4)


# 手書き数字のデータセットで学習
suuji = sklearn.datasets.load_digits()
ai = sklearn.svm.SVC(gamma = 0.001)
ai.fit(suuji.data, suuji.target)


# 1〜4桁目の画像の数値リスト化(データ化)と予測。何度も実行する処理を関数化
# 結果を出力させる際に関数を使ってfor文で何枚も予測させると、縦に結果が出力されるのが難点でしたが、「end=' '」の記述で解決しました
print('認識結果(予測結果):\n')

def cognition_img(input_file):
  gazou = PIL.Image.open(input_file).convert("L")
  gazou = gazou.resize((8,8),PIL.Image.ANTIALIAS)
  suuti = numpy.asarray(gazou, dtype = float)
  suuti = numpy.floor(16 - 16 * (suuti / 256))
  suuti = suuti.flatten()
  n = ai.predict(suuti.reshape(1, -1))
  print(int(n), end=' ')  # 横一列に表示させるため「, end=' '」を使います
  return


import glob
import os

# 元の画像から切り取った4つの画像「data1.png」〜「data4.png」を取得
img_list = glob.glob('data*png')
# data1〜data4を順番に並べる
img_list =  sorted(file_list)
# 画像を予測する関数「cognition_img」に「data1.png〜data4.png」を順番に入れる  
for file in img_list:
  cognition_img(file)


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)) 

 

出力結果

 

出力結果:改変したプログラム【4桁の手書き連続数字画像認識プログラム:Pythonサンプルコード】

 

 

【Python入門】無料講座をチェック

 

 

Pythonをはじめとした入門講座(Python基礎コース)や、機械学習プログラミング講座(AIエンジニア養成コース)などを手掛けている、

・テックジム

によって開催されている無料講座「ゼロからはじめるPython入門講座」は累計で1万人以上(2021年確認時点の全国の累計)が参加されている講座です。現在、Pythonで簡単なゲームを作る講座がオンライン(Zoom)で参加できます。

* 2021年3月1日現在のテックジム東京本校開催分のみの累計参加者数は9,059名

 

講座名:
ゼロからはじめるPython入門講座(by テックジム)

対象者:
・中学生以上の学生・社会人・シニア
・パソコンが普通に使える方

準備が必要な物
・パソコン
・Gmail

 

「講座で得られるメリット」「参加者の声」「開催スケジュール」などの詳細はリンク先でご確認ください。
参加・詳細はこちら
ゼロからはじめるPython入門講座 | テックジム

また、無料入門講座に参加後に、無料解説動画も用意してくださっているようです。講座が終了後に復習できるのでありがたいですね。

記事ページにまとめておきましたので、気になる方はチェックしてみてください。
無料のPython入門講座をチェック – 累計1万人以上が受講したプログラミング講座

 

 

by 子供プログラマー | プログラミング入門ウェブ教室

 

 

【Python等】OCRプログラミング入門講座(一覧)

次は、7セグメントのデジタル数字のOCRに挑戦
【4桁 – 7セグメント編】連続デジタル数字画像認識プログラミング入門(Python・OpenCV・Keras・CNN)

縦書き・横書き対応の日本語手書き文字のOCR開発に挑戦
【日本語手書きOCR編】連続文字画像認識プログラミング入門(Python・OpenCV・Keras・CNN)

 

【音声認識】

【Python入門】日本語の文字起こしのやり方(音声認識:音声ファイル編)サンプルコード 

 

【音声合成】

【PyTorch入門】日本語のテキスト音声合成(E2E-TTS)- ESPnet・Tacotron 2版