「秒」の画像解析状況
先回の投稿「ラズパイ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]))
まとめ
最初の準備(設定)に少し時間がかかるので、もっと手軽に使えると良いと思っています。