"BOKU"のITな日常

還暦越えの文系システムエンジニアの”BOKU”は新しいことが大好きです。

エラー(誤分類)の画像をEXCELで一覧するマクロ(VBA)を使う/Neural Network Console応用編

今回はNeural Network Consoleで「output_result.csv」に出力された評価結果を、EXCELに取り込んで、画像を一覧するマクロ(VBA)を作ってみます。

f:id:arakan_no_boku:20190326212937j:plain
 

元々手作業でやってたものが元です

 

Neural Network Consoleで「output_result.csv」に出力された評価結果を、EXCELに取り込んで分類に失敗したファイルを識別する方法を前回やりました。

arakan-pgm-ai.hatenablog.com

そうすると。

識別できるのはいいけど、ひとつひとつ画像を開いたりするのが面倒だ。

との・・ご意見をいただきました(笑)

なので、とりあえず前回の要領でEXCELファイルができている前提で、ボタンを押したら確認する一覧表ができますよ・・程度の簡単なマクロ(VBA)をつくってみようかな・・というわけです。

 

EXCELのマクロ(VBA)を使ったことがある方を前提に説明します

 

今回は前回の続きでMNIST画像(28×28サイズ)を想定したものになってます。

やるのは、こんな感じでもやれますという考え方の例と、サンプルソースの紹介です。

前回の記事が、EXCELを使うので、今回もVBAを使います。、

もしEXCELVBAプログラム(マクロ)を使ったことがない方は、以下の記事とかで基本的な部分を確認ください。

allabout.co.jp

さて。

始めます。

 

動作仕様です

 

元になるのは、こちらの記事の手順で作成したEXCELシートです。

arakan-pgm-ai.hatenablog.com

このフォーマットのA列からD列・・つまり、画像ファイル名と正解ラベル・評価結果・OK/NG判定結果の4列をコピーして使います。

f:id:arakan_no_boku:20181129230600j:plain

 

受取側のEXCELの動作仕様です

 

まず、xlsm で保存したEXCELに2つのシートを作ります。

名前は「output」と「result」にしてます。

f:id:arakan_no_boku:20181129231117j:plain

outputシートは元ネタです。

こんな感じのレイアウトにします。

f:id:arakan_no_boku:20181129231738j:plain

A列1・2行目にまたがったボタンは「開発」リボンにあるフォームのボタンです。

f:id:arakan_no_boku:20181130011349j:plain

ここに、上記のEXCELからA列~D列のデータ部分をコピーしたものを貼り付けて使います。

貼り付けたイメージはこちらです。

f:id:arakan_no_boku:20181129232237j:plain

そして「result」シートには、なんとなく結果のヘダーを作っておきます。

f:id:arakan_no_boku:20181129232508j:plain

ポイントはA列の行の幅と高さを画像にあわせておくとカッコいいということ。

MNISTの28×28サイズのまま画像を表示しても小さくて見づらいので、5倍くらいに拡大して表示するようにします。

なので、幅「17.4」高さ「108」くらいに調整してます。

そして「output」シートの「resultシート作成」ボタンを押すと、マクロが動いて、outputシートの各行の画像ファイルのパスから画像を表示して、ついでに正解ラベルと評価結果をコピーします。

動かした結果の例がこちらです。

f:id:arakan_no_boku:20181129233254j:plain

いい感じです。

つまり、NG分だけフィルタして貼り付ければ、簡単にアンマッチ画像チェックのリストが作れます・・という。

いちいち、手で拾わなくてもいいよ・・という。

ただ、それだけの話ですが。

そして、消すのもスマートにできないといけないから、「resultシートクリア」ボタンも用意してます。

こういうツールです。

 

VBAのソースと補足説明です

 

最初にソース全体をのせます。

' resultシート作成ボタンに対応する
'
Sub make_image_list()
    Dim input_sheet, result_sheet As String
    Dim out_row, in_row, max_row As Integer
        
    input_sheet = "output"
    result_sheet = "result"
    out_row = 2
    max_row = Sheets(input_sheet).Cells(Rows.Count, 1).End(xlUp).row
    Sheets(result_sheet).Select
    Application.ScreenUpdating = False
    For in_row = 4 To max_row
        Sheets(result_sheet).Cells(out_row, 1).Select
        Call add_picture(Sheets(input_sheet).Cells(in_row, 1).Text, 5)
        Sheets(result_sheet).Cells(out_row, 2) = Sheets(input_sheet).Cells(in_row, 2).Text
        Sheets(result_sheet).Cells(out_row, 3) = Sheets(input_sheet).Cells(in_row, 3).Text
        out_row = out_row + 1
    Next in_row
    Application.ScreenUpdating = True
End Sub

' resultシートクリアボタンに対応する
'
Sub clear_all()
  Dim img_shape As Shape
  Dim result_sheet As String
  Dim row, max_row As Integer
  result_sheet = "result"
  
  For Each img_shape In Sheets(result_sheet).Shapes
    If img_shape.Type = msoPicture Then img_shape.Delete
  Next img_shape
  
  max_row = Sheets(result_sheet).Cells(Rows.Count, 2).End(xlUp).row
  For row = 2 To max_row
    Sheets(result_sheet).Cells(row, 2).ClearContents
    Sheets(result_sheet).Cells(row, 3).ClearContents
  Next row
End Sub

' 画像ファイル名とパス(file_name)と拡大率(zoom)を受け取り画像を拡大表示する
' 
Sub add_picture(file_name As String, zoom As Integer)
    Dim img_file_name As String
    Dim img_shape As Shape
    
    img_file_name = file_name
    
    Set img_shape = ActiveSheet.Shapes.AddPicture( _
          Filename:=img_file_name, _
          LinkToFile:=False, _
          SaveWithDocument:=True, _
          Left:=Selection.Left, _
          Top:=Selection.Top, _
          Width:=0, _
          Height:=0)
          
    With img_shape
        .ScaleHeight zoom, msoTrue
        .ScaleWidth zoom, msoTrue
    End With
End Sub

補足説明にはいる前に、ちょっとお断りを。

上記のマクロ名や変数は「make_image_list()」のように、小文字でアンダーバー(_)つなぎにしてます。

VBAだと「makeImageList()」のような記法の方が一般的なので、気持ち悪いなと思われる場合は、使う時には適当にお好きな名前に変更してください。

さて。

resultシートに画像を表示する 「make_image_list()」からです。

このマクロを「resultシート作成」ボタンに関連づけます。

まあ、やってることと言えば

max_row = Sheets(input_sheet).Cells(Rows.Count, 1).End(xlUp).row

 で、A列(Cellsの第二引数は1がA列、2がB列・・です)のデータが存在する最終行を取得して、4行目からmax_row行まで、ループで1行ずつ処理しているだけです。

そして、「Sheets(result_sheet).Select」でresultシートをアクティブにして、パフォーマンスを稼ぐために「Application.ScreenUpdating = False」で画面再描画を抑制しています。

画像を表示するのは

Call add_picture(Sheets(input_sheet).Cells(in_row, 1).Text, 5)

で、画像ファイルのフルパスとファイル名を「output」シートのA列から取得して、zoomに「5」を指定することで5倍にしています。

add_picture()マクロは、EXCELで画像ファイルからセルに貼り付ける時の、定番の書き方そのものなので、特に補足はしません。

たぶん。

同様のソースや解説は、ググればいっぱいでてきますので。

今度は。

クリアするほう「clear_all()」です。

このマクロは「resultシートクリア」ボタンに関連づけます。

画像ファイルをクリアする部分。

For Each img_shape In Sheets(result_sheet).Shapes
    If img_shape.Type = msoPicture Then img_shape.Delete
Next img_shape

テキスト部分をクリアする部分

max_row = Sheets(result_sheet).Cells(Rows.Count, 2).End(xlUp).row
For row = 2 To max_row
    Sheets(result_sheet).Cells(row, 2).ClearContents
    Sheets(result_sheet).Cells(row, 3).ClearContents
Next row

にわけてます。

ちょっと効率悪いですけど、1セルずつ「数式と値だけを消す」ClearContentsを使ってます。

Deleteとかしてしまうと、書式も消えて面倒なので。

そのくらいですかね。

ポイントは。

あとは、これをベースにして、ちょこちょこ書き換えてもらえば、時々のデータにあわせてできると思います。

 

最後にちょっと言い訳です

 

あえて・・ですけど。

エラー処理とか、汎用的にする配慮とかは一切してません。

こういうブログでサンプルにするのに、あまり、行数を増やしたくなかったということもありますが、あくまで、自分で作って自分で使う。

そういう想定のツールだというのもあります。

正直。

学習とかに使うデータセットは都度違います。

シンプルな土台だけ用意しといて、細かい調整をソースコードの修正で行う方が、実は下手に重たい汎用的なツールを使うより、速くて確実だと・・自分では言ってるのですけどね。

単なる、横着の言い訳かもしれません(笑)

そのへんはご容赦ください。

今回はこんなところで。

ではでは。