星空つづり

星空・天体写真などの記録を綴るブログ

<< June 2020 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 >>

<< 牛窓にて | TOP |

2020.06.23 Tuesday

Python:OpenCVによる画像パターン認識のための機械学習に便利な支援ツールを作ってみた

昨今、PythonでAIを勉強している人は多いと思います。

ネットや関連雑誌・書籍では、OpenCVを使った画像認識させるってところが入り口になっていることが多いですよね。

 

静止画でもWEBカメラの動画映像からでも簡単に認識させることができるのは大変面白いですが、認識のために必要なのが学習済みのカスケード分類器(xmlファイル)。

顔認識を代表として学習済みのカスケード分類器はネット上で手に入れることが出来ますが、独自のオブジェクトを認識させるためには、自前でオブジェクトの画像をたくさん学習させ、分類器を作成する必要があります。

 

このページでは、途中の作業で必要な poslist , neglist ファイルの作成支援を行うツールを配布しています。

まずは、OpenCVを使ったパターン認識の機械学習をさせるための流れを確認しておきましょう。

 

▼学習環境を作る

・必要な実行ファイルやフォルダを準備する

※ここでは説明しませんので他のサイトを参考に

(参考サイト)

【Python版OpenCV入門】使い方とサンプル集

OpenCVの勉強(分類器を作成してみる)

openCVで人物特定の分類器を自作

OpenCV 物体検出、分類器作成と検出テスト その2

 

▼オブジェクトが写っている写真、写っていない写真をそれぞれ集める

・精度を上げるためには数百枚〜数千枚必要です。ネット画像などを収集します

・一枚の画像から歪み、回転などを加えて複数枚作成できる opencv_createsamples.exe を活用する方法もある

 

▼オブジェクトが写っている写真からPositive-list (Poslist.txt)を作成する

・オブジェクトのみをトリミングした写真を用意するか、写真から領域選択をしてその座標をPoslistに記録します

※このページでは、各画像をロードしてPoslist作成時の領域選択を行い、Poslistファイルに座標記録する支援ツールを配布しています

 

▼オブジェクトが写っていない写真からNegative-list (Neglist.txt)を作成する

・画像は何でもOK

・Neglist.txtは画像リストとしてフルパスでのファイル名一覧を準備する

※このページでは、フォルダ内のファイルから一発でフルパスのファイル名一覧(Neglist.txt)を作成する支援ツールを配布しています

 

▼カスケード分類器の作成

※ここでは説明しませんので他のサイトを参考に

 

▼できあがった分類器(xmlファイル)をセットしてパターン認識出来るかどうか検証

※ここでは説明しませんので他のサイトを参考に

 

流れとしてはそんなところでしょうか。流れの中で二つの支援ツールを用意したので以下に貼り付けておきます。ご自由にお使いください。

それぞれの支援ツールは分類器作成用フォルダにコピーしてお使いください。

 

ポジティブリスト作成支援ツール

 

以下のスクリプトをコピペして tool-poslist-maker.py として保存して使用してください

使用方法はスクリプト内に記載しています

動作中の画面は以下の感じです

 

 

----------------------------------------------------------------

# OpenCV機会学習用PosListの作成ツール

# tool-poslist-maker.py
#
# 目的:OpenCV分類器におけるポジティブイメージの範囲指定に必要な
# Poslist.txtの作成を行います
# 学習させたい対象物を画像内で囲うことで、画像上の対象数と最大範囲を
# Poslistの要求形式にて書き出しします
#
# 使用方法:
# 指定の横幅にて縦横比維持で画像表示されますので、
# ダブルクリックで四角形の対角をそれぞれ指定してください。
# 一枚の画像内で、MAXPOINT の設定値まで指定できます。
# 対象物全ての囲いが終われば、(s)キー押下にてPoslistへ書き込み後、
# 次の画像を自動的にロードします
# 作業を途中でやめたい場合は、ESCキー押下で終了します。
# なお、次回開始時は、Poslist.txtをリードして、続きの画像ファイルから
# 作業できるようにしています。
# なお、日本語などの2バイト系文字を含む画像ファイル名は避けてください
# このツールを使う前処理として、画像ファイルは連番(例:0001.jpg)名に
# しておくことをお勧めします
# また、作業中の修正機能は組み込んでいません。対角指定の位置を間違った
# 場合は、その場ESCで終了させ、再度ツールを実行させてください
#
# 2020/05/26 original ver.1.00
# coded by Sirius@星空つづり(岡山アストロクラブ 大島)
#
# 改変使用、改変後の再配布などご自由に。ただし改変後配布の際は、改変者
# 名をこのコメント次行に必ず追記してください
#
#

import glob,os,codecs
import cv2


# mouse callback function ダブルクリックで左上、右下の座標を順に記録
def draw_rect(event,x,y,flag,param):
    global done,sx,sy,ex,ey,PCount
    if event == cv2.EVENT_LBUTTONDBLCLK:
        if PCount < MAXPOINT:
            if done:
                ex.append(x)
                ey.append(y)
                print(PCount+1,') end=',x,y)
                cv2.rectangle(img,(sx[PCount],sy[PCount]),(x,y),(255,255,0),5)
                done = False
                PCount += 1
            else:
                sx.append(x)
                sy.append(y)
                print(PCount+1,') start=',x,y)
                done = True
                cv2.circle(img,(x,y),10,(255,255,255),-1)
        else:
            print('MAX POINTS!')

 

if __name__ == '__main__':

    FILE_PATH = './pos/' # ポジティブイメージ(.jpg)ファイルの格納フォルダ
    FILE_NAME = FILE_PATH + 'poslist.txt'
    
    VIEW_WINDOW_NAME = 'View'
    MAXPOINT = 20
    WINDOW_RESIZE_WIDTH = 800
    msg = 'All input is completed.'

    file_list = sorted(glob.glob(FILE_PATH + '*.jpg'))

    # Poslistが既にあれば、前回の続きからやるようにする
    try:
        with codecs.open(FILE_NAME,'r','utf-8') as fr:
            lines = fr.readlines()
            lineCount = len(lines)
            print('From the last continuation')
            del file_list[0:lineCount]
    except Exception as e:
        print('Create poslist as a new file')

    for imgfile in file_list:
        sx,sy = [],[] #左上座標格納用空リスト
        ex,ey = [],[] #右下座標格納用空リスト
        PCount = 0 #指定した四角形の数
        done = False #左上座標取得済み=True

        img = cv2.imread(imgfile)
        imgfile = os.path.basename(imgfile)
        print('Loading..Image:',imgfile)
        
        # 画像ファイルの大きさを取得
        height = img.shape[0]
        width = img.shape[1]

        # 横幅固定(縦横比はオリジナル維持)のウィンドウに画像ロード
        resizew = WINDOW_RESIZE_WIDTH
        resizeh = int(height * (resizew/width))

        cv2.namedWindow(VIEW_WINDOW_NAME,cv2.WINDOW_NORMAL)
        cv2.resizeWindow(VIEW_WINDOW_NAME,resizew,resizeh)

        cv2.setMouseCallback(VIEW_WINDOW_NAME,draw_rect)

        while True:
            cv2.imshow(VIEW_WINDOW_NAME,img)
            k = cv2.waitKey(20) & 0xFF
            if k == 27: # ESCで終了へ
                break
            elif k == ord('s'): # s押下時、範囲指定が一でもあればそれらの領域数と最大領域を保存
                if PCount > 0:
                    with codecs.open(FILE_NAME,'a','utf-8') as ft:
                        line = '{} {}'.format(imgfile,PCount)
                        ci = 0
                        while ci < PCount:
                            line = line + ' {} {} {} {}'.format(sx[ci],sy[ci],ex[ci],ey[ci])
                            ci += 1
                        line = line + '¥n'
                        ft.write(line)
                        print('Saved..',line)
                    break

        cv2.destroyAllWindows()
        if k == 27:
            msg = 'End with ESC key.'
            break
        else:
            continue
    print(msg)

----------------------------------------------------------------

 

 

ネガティブリスト作成支援ツール

 

以下のスクリプトをコピペして tool-neglist-maker.py として保存して使用してください

使用方法はスクリプト内に記載しています

 

----------------------------------------------------------------

# OpenCV機会学習用NegListの作成ツール
# tool-neglist-maker.py

#
# 目的:OpenCV分類器におけるネガティブイメージのファイルリスト、
# neglist.txt を作成します。
#
# 使用方法:
# /neg フォルダ内のjpg画像に対してフルパスでのファイルリストを作成します
# プログラムを実行するだけです。
#
# なお、日本語などの2バイト系文字を含む画像ファイル名は避けてください
# このツールを使う前処理として、画像ファイルは連番(例:0001.jpg)名に
# しておくことをお勧めします
#
# 2020/05/26 original ver.1.00
# coded by Sirius@星空つづり(岡山アストロクラブ 大島)
#
# 改変使用、改変後の再配布などご自由に。ただし改変後配布の際は、改変者
# 名をこのコメント次行に必ず追記してください
#
#


import glob,codecs,os

if __name__ == '__main__':

    # ネガティブイメージ(.jpg)ファイルの格納フォルダ
    FILE_PATH = './neg/'
    FILE_NAME = FILE_PATH + 'neglist.txt'
    
    msg = 'Create neglist.txt as a new file.'

    file_list = sorted(glob.glob(FILE_PATH + '*.jpg'))
    with codecs.open(FILE_NAME,'w','utf-8') as ft:
        for imgfile in file_list:
            line = os.path.abspath(imgfile) + '¥n'
            ft.write(line)

    print(msg)

----------------------------------------------------------------


▲top