国旗判定器で国旗を判定してみる
国旗判定器を作る、で判定ファイル作成に用いた画像で判定がうまくいくことを確認しましたが、他の画像でうまく判定できるか試します。判定用リストファイル、判定コードはそのままです。
次の3つの画像で試します。
(1)いらすとやから入手したフランス国旗のイラスト
(2)インド料理店の看板に印刷されていたインド国旗の写真
(3)韓国料理店の看板に印刷されていた韓国国旗の写真
実行結果(1)
ちゃんとフランスと判定されます。
実行結果(2)
ちゃんとインドと判定されます。
実行結果(3)
誤って日本の国旗と判定されました。
リストを見ると2番目に正解のkoreaがあり惜しいことが分かります。また距離を細かく見ると
画像全体 Japan 0.020… Korea 0.013…
上半分 Japan 0.004… Korea 0.017…
左半分 Japan 0.014… Korea 0.013…
となっており、上半分の距離で判定間違いしていることが分かります。日の丸と韓国国旗の上半分は白地に赤でほとんど同じなので間違えたと推定できます。
韓国国旗が正しく判定されるように画像の上半分を判定に使う代わりに下半分を使ってみます。
コード (判定リストファイルの作成)
import os # osのインポート import cv2 # OpenCVのインポート import numpy as np # numpyをnpという名前でインポート import csv # CSVモジュールのインポート list_bgr = [] # データ格納用リストの生成 dir_path = 'flag/' # 画像ファイルのあるフォルダの相対パス files = os.listdir(dir_path) # フォルダ内のファイルのリスト生成 for i in files: # ファイルの数だけ繰り返す filename = i.split('.')[0] # ファイル名iを'.'で分割し前の部分を取得(拡張子の除去) img = cv2.imread(dir_path+i) # 画像の読み出し height,width = img.shape[0:2] # 画像の高さ、幅の取得 half_height = int(height/2) #画像の高さの半分 half_width = int(width/2) #画像の幅の半分 img_bottom = img[half_height:] #下半分の画像生成 img_left = img[:,:half_width] #左半分の画像生成 #BGR各チャンネルの比率を求める bgr = np.sum(img ,axis = (0,1)) b_ratio,g_ratio,r_ratio = bgr/np.sum(bgr) #下半分の画像のBGR各チャンネルの比率を求める bgr_bottom = np.sum(img_bottom ,axis = (0,1)) b_bottom_ratio,g_bottom_ratio,r_bottom_ratio = bgr_bottom/np.sum(bgr_bottom) #左半分の画像のBGR各チャンネルの比率を求める bgr_left = np.sum(img_left ,axis = (0,1)) b_left_ratio,g_left_ratio,r_left_ratio = bgr_left/np.sum(bgr_left) #求めたチャンネル比率をリストに追加 list_bgr.append([filename,b_ratio,g_ratio,r_ratio,b_bottom_ratio,g_bottom_ratio,r_bottom_ratio,b_left_ratio,g_left_ratio,r_left_ratio]) #リストをcsvファイルに保存 with open('flag_check/flag_check.csv', 'w') as file: writer = csv.writer(file, lineterminator='\n') writer.writerows(list_bgr)
コード (国旗画像の判定)
# 画像のインライン表示のためのjupiter notebookコマンド %matplotlib inline import cv2 # OpenCVのインポート import numpy as np # numpyをnpという名前でインポート import csv # CSVモジュールのインポート import pprint # pprintモジュールのインポート from matplotlib import pyplot as plt img = cv2.imread('flag_check/test.png') # 画像の読み出し height,width = img.shape[0:2] # 画像の高さ、幅の取得 half_height = int(height/2) #画像の高さの半分 half_width = int(width/2) #画像の幅の半分 img_bottom = img[half_height:] #下半分の画像生成 img_left = img[:,:half_width] #左半分の画像生成 # BGR各チャンネルの比率を求める bgr = np.sum(img ,axis = (0,1)) b_r,g_r,r_r = bgr/np.sum(bgr) # 下半分の画像のBGR各チャンネルの比率を求める bgr_bottom = np.sum(img_bottom ,axis = (0,1)) b_bottom_r,g_bottom_r,r_bottom_r = bgr_bottom/np.sum(bgr_bottom) # 左半分の画像のBGR各チャンネルの比率を求める bgr_left = np.sum(img_left ,axis = (0,1)) b_left_r,g_left_r,r_left_r = bgr_left/np.sum(bgr_left) check_result = [] # 比較用リストの生成 with open('flag_check/flag_check.csv') as f: # flag_check.csvを開く reader = csv.reader(f) # test.pngのBGR値とflag_check.csvの各行のBGR値の距離を求めリストcheck_resultに加える for row in reader: filename,b_ratio,g_ratio,r_ratio,b_bottom_ratio,g_bottom_ratio,r_bottom_ratio,b_left_ratio,g_left_ratio,r_left_ratio = row distance = ((b_r-float(b_ratio))**2+(g_r-float(g_ratio))**2+(r_r-float(r_ratio))**2)**0.5 distanceb = ((b_bottom_r-float(b_bottom_ratio))**2+(g_bottom_r-float(g_bottom_ratio))**2+(r_bottom_r-float(r_bottom_ratio))**2)**0.5 distancel = ((b_left_r-float(b_left_ratio))**2+(g_left_r-float(g_left_ratio))**2+(r_left_r-float(r_left_ratio))**2)**0.5 distance_sum = distance+distanceb+distancel check_result.append([filename,distance_sum,distance,distanceb,distancel]) sortsecond = lambda val: val[1] # リスト2番目の数値(インデックス1)を参照する関数 check_result.sort(key=sortsecond) # リスト2番目の数値をキーにしてcheck_resultをソート ans_img = cv2.imread('flag/'+check_result[0][0]+'.png') # check_result一番目の行のfile名を読み出し同じ名前のpngファイルをans_imgへ ans_img_rgb = cv2.cvtColor(ans_img, cv2.COLOR_BGR2RGB) # ans_imgをRGBに変換表示 plt.imshow(ans_img_rgb) # ans_img_rgbを表示 pprint.pprint(check_result,width=120) # リストを表示(行サイズ120文字で折り返し)
実行結果(3)
今度は正しく韓国国旗が判定されました。