Pythonでいろいろやってみる

Pythonを使った画像処理や機械学習などの簡単なプログラムを載せています。

国旗判定器で国旗を判定してみる

国旗判定器を作る、で判定ファイル作成に用いた画像で判定がうまくいくことを確認しましたが、他の画像でうまく判定できるか試します。判定用リストファイル、判定コードはそのままです。

次の3つの画像で試します。
(1)いらすとやから入手したフランス国旗のイラスト
f:id:T_A_T:20190430182759p:plain

(2)インド料理店の看板に印刷されていたインド国旗の写真
f:id:T_A_T:20190430182919p:plain

(3)韓国料理店の看板に印刷されていた韓国国旗の写真
f:id:T_A_T:20190430183037p:plain

実行結果(1)

ちゃんとフランスと判定されます。 f:id:T_A_T:20190430183615p:plain

実行結果(2)

ちゃんとインドと判定されます。 f:id:T_A_T:20190430183910p:plain

実行結果(3)

誤って日本の国旗と判定されました。 f:id:T_A_T:20190430184145p:plain
リストを見ると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)

今度は正しく韓国国旗が判定されました。
f:id:T_A_T:20190430193245p:plain

ブログランキングに参加しています

にほんブログ村 IT技術ブログへ
にほんブログ村