「秒」の画像解析状況
先回の投稿「ラズパイ4で数字を画像認識する(OPEN CV テンプレートマッチング) 」と考え方は同じです。OpenCVのテンプレートマッチング機能を利用して、デジタル目覚し時計の「秒」部を文字列変換するプログラムを作成してみました。
文字列変換状況の動画を掲載します。
結果の動画内容は良好と思っています。2文字しか変換していないこともありますが、「秒」の変化に追従しています。
但し、デジタル時計はもともと薄暗い背景に黒い文字なので、2値化の閾値設定や照明の当て方に少し工夫が必要でした。普通の卓上照明を使いましたが、照らし方によって影が入るなど、単純に明るくすれば良い訳ではないことを理解しました。また、エクセルシートの数字と異なり文字間隔や外枠との隙間が小さいので、検索領域設定や一部の外枠を消去するなどの処理を変更しました。約1時間程度の試行錯誤を経て、動画の様な状態になりました。
テンプレート作成プログラム
下記の通り、「0」~「9」のテンプレートを作成しました。

テンプレート作成プログラムです。特定領域の画像を保存してくれます。ファイル保存してくれるだけなので、対象画像を一つづつ処理する必要があります。
#テンプレート作成
import sys
import cv2
import math
import numpy as np
capture = cv2.VideoCapture(0)
try:
if capture.isOpened() is False:
print("カメラを開けませんでした。")
sys.exit()
X_S0=462
Y_S0=227
WDT=31
HGT=56
cntr_top=284
cntr_lft=10
contours = np.array([[cntr_lft,cntr_top],[cntr_lft,cntr_top+50],[cntr_lft+500,cntr_top+50],[cntr_lft+500,cntr_top]])
while True:
ret, frame = capture.read()
#ret, frame = cv2.threshold(frame ,200,255, cv2.THRESH_BINARY)
gray_frame = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
ret, gray_frame = cv2.threshold(gray_frame ,40,255, cv2.THRESH_BINARY)
cv2.fillPoly(gray_frame,pts=[contours],color=(255,255,255))
if cv2.waitKey(1) & 0xFF==ord('q'):
break
img_crop0 = gray_frame[Y_S0:Y_S0+HGT,X_S0:X_S0+WDT]
cv2.imwrite("t_plt0.jpg",img_crop0)
cv2.rectangle(gray_frame,(X_S0,Y_S0),(X_S0+WDT,Y_S0+HGT),(0, 0, 0),thickness=1)
cv2.imshow('frame',gray_frame)
capture.release()
cv2.destroyAllWindows()
except:
print("Error:",sys.exc_info()[0])
print(sys.exc_info()[1])
import traceback
print(traceback.format_tb(sys.exc_info()[2]))
文字列変換プログラム
下図の通りUSBカメラで時計を連続的に撮像し、「秒」を文字列変換しています。

プログラムは下記の通りです。
import sys
import cv2
import numpy as np
import math
import time
try:
capture=cv2.VideoCapture(0)
if capture.isOpened() is False:
print("カメラを開けませんでした。")
sys.exit()
X_S=[430,460]
Y_S=[230,229]
WDT=31
HGT=60
cntr_top1=284
cntr_lft1=10
cntr_top2=10
cntr_lft2=425
cntr01 = np.array([[cntr_lft1,cntr_top1],[cntr_lft1,cntr_top1+50],[cntr_lft1+500,cntr_top1+50],[cntr_lft1+500,cntr_top1]])
cntr02 = np.array([[cntr_lft2,cntr_top2],[cntr_lft2,cntr_top2+500],[cntr_lft2+5,cntr_top2+500],[cntr_lft2+5,cntr_top2]])
while(True):
ret,frm_org =capture.read()
ret, frame = cv2.threshold(frm_org ,45,255, cv2.THRESH_BINARY)
cv2.fillPoly(frame,pts=[cntr01],color=(255,255,255))
cv2.fillPoly(frame,pts=[cntr02],color=(255,255,255))
getVal=["*","*"]
for i in range(2):
T_XS = X_S[i]-3
T_YS = Y_S[i]-10
T_XE = T_XS + WDT+6
T_YE = T_YS + HGT+10
if i==1:
cv2.rectangle(frame,(T_XS,T_YS),(T_XE,T_YE),(0, 0, 255),thickness=1)
else:
cv2.rectangle(frame,(T_XS,T_YS),(T_XE,T_YE),(0, 255, 0),thickness=1)
img_crop = frame[T_YS:T_YE,T_XS:T_XE]
maxVal_All = 0.4
num_dsp = -1
#0〜9のテンプレートと照合
for j in range(10):
i_tmpl=cv2.imread("tpl"+str(j)+".jpg")
result= cv2.matchTemplate(img_crop,i_tmpl,cv2.TM_CCOEFF_NORMED)
mmr=cv2.minMaxLoc(result)
maxVal=mmr[1]
if maxVal > maxVal_All:
num_dsp = j
maxVal_All = maxVal
if num_dsp != -1:
getVal[i] = str(num_dsp)
print(getVal)
cv2.putText(frame,getVal[0]+getVal[1],(420,350),cv2.FONT_HERSHEY_SIMPLEX,2,(0,0,255),2,cv2.LINE_AA)
cv2.imshow('frame',frame)
if cv2.waitKey(1) & 0xFF==ord('q'):
break
capture.release()
cv2.destroyAllWindows()
except:
print("Error:",sys.exc_info()[0])
print(sys.exc_info()[1])
import traceback
print(traceback.format_tb(sys.exc_info()[2]))
まとめ
最初の準備(設定)に少し時間がかかるので、もっと手軽に使えると良いと思っています。