Welcome to Mashykom WebSite



TensorFlowを用いた物体検出(Object Detection)のページ

コンピュータビジョンの分野における物体検出(Object Detection)とは、ある画像の中から定められた物体の位置とカテゴリー(クラス)を検出することを指します。物体検出の問題は、性質のわからない、数が不明な物体をビデオ画像やカメラ画像から特定するという問題になります。検出対象はサイズが異なり、画像全体に広がっています。十分な速度と高精度を提供するという制約によって、そのタスク固有の難しさが生まれます。物体検出は依然としてコンピュータビジョンの難しい部分ですが、デジタルカメラの単純な顔検出から画像検索やビデオ監視まで、コンピュータビジョンの多くの分野に応用されています。自走車にとってリアルタイムの歩行者検出は重要であるし、また、人や車を自動でカウントすることは都市計画において重要です。Deep Learningアルゴリズムの発展によって、物体検出の精度は目まぐるしい勢いで進歩しており、現実の社会でも、自動運転技術では実用化されています。
  このページでは、Deep Learning(CNN)を応用した一般物体検出アルゴリズムをPythonでコード化したライブラリの代表的な事例を取り上げて、物体検出プログラムの実装について説明します。anacanda3でpython3.6パッケージ、TensorFlow、Kerasなどの環境はセットアップされているとします。Mac OSでもUbuntu16.04のどちらでも正常に動作することは確認しています。Keras+Tensorflowがインストールされていれば、Windowsでも正常に作動すると思います。

 ここでは、物体検出のアルゴリズムとして、SSD: Single Shot MultiBox Detector 、 YOLO(You Only Look Once) 及び R-CNN (Regions with CNN features) を取り上げます。GPUを搭載していないPCを前提にしているので、リアルタイムでの物体検出では、処理速度が遅く、画像の切り替わりがスムーズでないことはやむを得ません。また、動作確認は明記されたTensorflowやKerasなどのバージョンで行っていますので、バージョンアップなどが行われた環境ではエラーなどが出て正常に作動しない可能性もありますので、ご注意ください。このページが最初に書かれた時(2018年3月)のソフトウエ環境は

scikit-learnのバージョン:0.19.1
numpyのバージョン:1.14.3
scipyのバージョン:0.19.1
matplotlibのバージョン:2.1.0
PIL(Pillow)のバージョン:4.2.1
opencv-pythonのバージョン:3.4.0
kerasのバージョン:2.1.5
tensorflowのバージョン:1.8.0

でした。動作確認はこのTensorflowやKerasなどのバージョンで行っていました。しかし、KerasやTensorflowのバージョンアップなどが行われた環境ではエラーなどが出て正常に作動しない可能性もありますので、ご注意ください。なお、2019年4月2日時点では、使用されているソフトウエアの環境は以下の通りにアップグレードされています。
numpyのバージョン:1.16.1
scipyのバージョン:1.1.0
matplotlibのバージョン:2.2.2
PIL(Pillow)のバージョン:5.1.0
opencv-pythonのバージョン:4.0.0
kerasのバージョン:2.2.4
tensorflowのバージョン:1.13.1
です。

この環境で起こるエラーなどについては、注意書きとして付記しました。

Last updated: 2019.4.24


物体検出のCNNアルゴリズムと主要なライブラリ


 機械学習の観点では、画像からの物体検出は、同時に2つの問題を解決する必要があります。画像の特定の領域が物体であるかどうかを判断し、どの物体であるかを調べることが必須です。現在の物体検出モデルの多くは、ニューラルネットワークの特定のアーキテクチャである畳み込みニューラルネットワーク(CNN)上に構築されています。

 2017年1月、Facebookの研究チームであるFacebook AI Research(FAIR)が物体検出ライブラリであるDetectronをオープンソースとして公開しました。Facebookが開発したDetectronは、Deep Learning(CNN)を応用した物体検出ライブラリのCaffeを基礎としています。Facebookのrepositoryはここです。Detectronは、Apache 2.0ライセンスのもとで利用可能なPythonライブラリとして提供され、GitHubから入手可能で、事前訓練されたモデルが含まれています。

 Detectronのリリースの数週間後に、GoogleのTensorflow Image Recognition APIがアップデートされて公開されました。TensorFlowのrepositoryはここです。両方のライブラリとも、物体検出のための最新のディープラーニングアルゴリズムを実装しています。GoogleのTensorflow Image Recognition APIは、40種類のディープラーニング・アルゴリズムの巨大なTensorFlow Researchリポジトリの一部となっています。

 両方のライブラリに含まれる事前訓練されたモデルは、PASCAL VOCデータセット、COCOデータセットなどでトレーニングされています。これには、80個の物体カテゴリ、200,000個以上のラベル付きイメージ、150万個の物体インスタンスが含まれます。FacebookのDetectronとGoogleのTensorflow Image Recognition APIの両方は主に研究目的であり、まだ商用製品としての準備が整っていません。

 ただし、caffe系のパッケージを正常に動作させるための環境設定は複雑です。とりわけ、pythonのバージョンに依存して、C++でのビルドで様々なエラーが出ます。OSの構造を熟知していないC++の初心者には難しいと思われます。なお、要求される環境はNVIDIA GPU, Linux, Python2となっています。Python3では作動しないと思われます。

 他方、TensorFlow Object Detection APIは、OSに依存せず、インストールが簡単で、独自のモデルを訓練するために使用することが簡単であると言われています。そのGitHubリポジトリには、インストール、モデルトレーニング、転移学習のためのJupyter Notebookがいくつか含まれています。Googleの物体検出ライブラリ向けの、他のチュートリアルはオンラインで入手できます。

 TensorFlowなどのライブラリに実装されている物体検出アルゴリズムは

Region Proposal : 物体らしい箇所を検出
Classification : 検出箇所のラベル分類
Bounding Box Regression : 正確な物体を囲う位置座標を推定

というRegion Proposal, Classification, Bounding Box Regression の 3 phase に大きく別れています。物体検出の分野で重要とされている指標は、mAP (mean Average Precision) と FPS (Frame Per Second) です。つまり、物体検出精度と処理速度です。   

  Deep Learning(CNN)を応用した一般物体検出アルゴリズムで有名なものとしては、3種類挙げられます。R-CNN (Regions with CNN features)の発展系Faster R-CNN、YOLO(You Only Look Once)、SSD: Single Shot MultiBox Detectorに大別できます。それらに対応する論文は
  • Ren, Shaoqing, et al. "Faster R-CNN: Towards real-time object detection with region proposal networks." Advances in neural information processing systems. 2015. 原論文はここからダウンロードできます。
  • Redmon, Joseph, et al. "You only look once: Unified, real-time object detection." arXiv preprint arXiv:1506.02640 (2015). 原論文はここからダウンロードできます。
  • Liu, Wei, et al. "SSD: Single Shot MultiBox Detector." arXiv preprint arXiv:1512.02325 (2015). 原論文はここからダウンロードできます。

  • です。論文の内容までは説明しません。興味のある人は読んで見てください。これらのアルゴリズムを組み込んだプログラムはTensorFlowで実装可能となっています。

     これらのアルゴリズムを実装したモデルの精度を比較した結果が多数ネット上で閲覧できます。これらによると、 YOLO系とSSD系の一騎打ちのようです。

     以下では、TensorFlowを用いて、SSD系とYOLO系のアルゴリズムを実装する事例をいくつか紹介します。最後に、R-CNN (Regions with CNN features)を紹介します。anacondaがインストールされていることを前提にします。また、Kerasのインストールとバックエンドのtensorflowがインストールされていることも前提にします。KerasとTensorflowのインストールについては、KerasとTensorFlowのインストールが説明されているページを読んでください。


    SSD:Single Shot MultiBox Detector in TensorFlow


     SSDの元コードはCaffeで書かれていますが、TensorFlowのコードに書き換えられたバージョンを使います。 アルゴリズムはVGG-based SSD networks (with 300 and 512 inputs)となっています。TF checkpointsはSSD Caffeモデルから直接的に変換したものです。TF-Slim modelsの構成はResNet、 Inception 及び VGGを含みます。

    TensorFlowライブラリなどのバージョンは以下の通りです。
    python3==3.6
    tensorflow==1.8.0
    opencv-python==3.4.0
    この環境のもとで、 TensorFlowで実装されたSSDのコードを利用します。ソースコードは
    https://github.com/balancap/SSD-Tensorflow
    で提供されています。 以下のコマンドでファイルのダウンロードと、SSDの学習モデルの解凍を実施します。
    
    $ git clone https://github.com/balancap/SSD-Tensorflow
    $ cd SSD-Tensorflow/checkpoints
    $ unzip ssd_300_vgg.ckpt.zip
    
    

    git clone が成功しないときは、GitHubに直接アクセスしてから、リポジトリをダウンロードするといいでしょう。

     学習済みのモデルを利用しましょう。検出部分は二つの主要なステップからなります。SSD network on the image と post-processing the output using common algorithms (top-k filtering and Non-Maximum Suppression algorithm)です。

     jupyter notebook を起動して、ファイルnotebooks/ssd_notebook.ipynbを開いてください。このスクリプトを実行する。以下のような注意が表示されますが、無視してください。
    /Users/koichi/anaconda3/lib/python3.6/site-packages/h5py/__init__.py:36: 
    FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. 
    In future, it will be treated as `np.float64 == np.dtype(float).type`.
      from ._conv import register_converters as _register_converters
    

    In[8]のセルで、画像の指定を
    img = mpimg.imread(path + image_names[-1])
    とすると、以下のような画像が表示されます。
    ssd_1.jpg
    検出物体の分類が数値のまま表示されています。15は人物、7は自動車、2は自転車ですね。2列目はクラスに該当する確率です。

     このソースコードにはカメラやビデオからの画像処理が含まれていません。カメラやビデオからの画像処理をするためには、ファイルを修正する必要があります。カメラやビデオからの画像処理の部分を加えたファイルが、karaage0703さんのGitHubにあります。以下のForkedされたGithubのリポジトリから
    SSD-Tensorflow_2
    をダウンロードします。あるいは、追加したスクリプト(ssd_camera.py, ssd_video.py )をコピぺします。PCに接続したwebカメラを用いるときは、ssd_camera.pyの中の、137行目にあるcv2.VieoCaptureの引数を1にします。
    cam = cv2.VideoCapture(1)
    に修正します。番号1はpcのusbに接続したweb cameraを指定します。この修正の後、SSD-Tensorflow_2ディレクトリに移動して
    
    (SSD-Tensorflow_2)$python ssd_camera.py 
    
    

    と実行すると、
    (INFO:tensorflow:Restoring parameters from ./checkpoints/ssd_300_vgg.ckpt)
    True
    elapsed_time:1.6441619396209717[sec]
    elapsed_time:1.5960886478424072[sec]
    elapsed_time:1.6152000427246094[sec]
    elapsed_time:1.5574941635131836[sec]
    elapsed_time:1.5478308200836182[sec]
    elapsed_time:1.5470259189605713[sec]
    elapsed_time:1.542952060699463[sec]
    elapsed_time:1.542001724243164[sec]
    elapsed_time:1.5505783557891846[sec]
    elapsed_time:2.081794023513794[sec]
    
    

    とターミナルに表示されて、web cameraからの画像がデスクトップに表示されます。検出された物体には長方形の枠取りと名称が表示されます。動画は 'output.mp4'という名前で保存されます。物体のクラスはVOC 分類での20種類だけとなっています。PASCAL VOCでの物体カテゴリー数は20個で以下の通りです。VOC categories SSD-Tensorflow では20種類の物体の検出ができますが、これ以上の種類の物体は識別できません。


    SSD: Single Shot MultiBox Detector to Keras framework


     ここでは、Keras+Tensorflowの上で、SSDを実装します。Kerasを利用すると、スクリプトが簡単化されます。TensorFlowライブラリなどのバージョンは以下の通りです。

    Keras==2.1.5
    python3==3.6
    tensorflow==1.8.0
    opencv-python==3.4.0
    この環境のもとで、以下のリポジトリにあるソースコードを使用します。Keras v2.xに対応するコードは以下のGitHubレポジトリにあります。
    Keras v2に対応するコード
    を git clone またはダウンロードしてください。ssd_v2.pyがKeras v2に対応するSSDアルゴリズムを実装したコードです。(ssd.pyがKeras v1に対応したコードです。)

     なお、SSD300の学習済み重みweights_SSD300.hdf5が必要です。学習済み重みは
    こちらから
    ダウンロード出来ます。なお、 3x3 convolution for pool6モデルには、古いweights_300x300_old.hdf5 が必要です。重み付きデータはダウンロードして、'ssd_keras_ver2_1' directory に移動しておきます。

     当該ディレクトリに学習済み重みweights_SSD300.hdf5を配置したら、Jupyter Notebookを開いて、SSD_ipynb を実行してください。以下のような画像を含めた数種類の枠取り済みの画像が表示されます。
    ssd_2.jpg
    ssd_3.jpg
    枠の上部に検出物体の名称が表示されています。自動車の模型がTVモニターに間違って検出されています。

     web cameraでキャプチャーした映像からリアルタイムで物体検出することを取り上げます。'testing_utils'に配置されている 'videotest_example.py' を使います。PCにUSB接続のweb cameraを接続してから、以下のように入力します。
    
    $ cd testing_utils/
    $ python videotest_example.py 
    
     

    と実行します。1回だけの入力で成功しないかもしれませんが、2回目の入力では成功すると思います。時間の経過とともに、pngファイルが番号順に表示され、画像ファイルが 'tesing_utils' フォルダーに保存されていきます。GPUなしのCPUだけのPCでは検出画像はスムーズな表示切り替えにはなりません。

     なお、Keras v1に対応したソースコードは以下のGitHubからダウンロードできます。
    Keras v1に対応するコード
    このコードはKeras v1.2.2, Tensorflow v1.0.0, OpenCV v3.1.0で正常に作動します。Jupyter Notebookを起動して、SSD_ipynbを開いて、このファイルを実行します。しかし、Keras v2で上記のソースコード実行すると、エラーが出ます。Keras v2を利用するときは、修正バージョンが必要です。

     web cameraでキャプチャーした映像からリアルタイムで物体検出するとき、Keras v1に対応するリポジトリのファイルには一部エラーがありますので、コードの修正、及び検出結果の書き出しのために、以下の通りソースコードを修正します。/testing_utils/videotest.pyのファイルを開いて、

    # 87行目(修正)
    vidw = vid.get(cv2.CAP_PROP_FRAME_WIDTH)
    vidh = vid.get(cv2.CAP_PROP_FRAME_HEIGHT)

    # 99行目(追加)
    num_frame = 0

    # 183行目(追加)
    cv2.imwrite("frame_" + str('{0:04d}'.format(num_frame)) +".png", to_draw)

    # 184行目(追加)
    num_frame += 1

    と修正します。

     /testing_utils/videotest_example.pyを開いて、# 24行目を修正して、自身の動画ファイルを指定します。
    vid_test.run('./myvideo.mp4')

    と修正します。追加する文は列の先頭を揃えてください。こちらのKeras v2に対応するコードからダウンロードしたコードは修正済みです。Keras v2 に対応したssd-kerasのコードは、このFerrari の GitHub にも存在します。しかし、webcam からのライブ映像の物体検出のためのプログラムは用意されていません。


    YOLO(You Only Look Once) in TensorFlow framework: version 1



     YOLO(You Only Look Once)とは、畳み込みニューラルネットワーク(CNN:Convolutional Neural Network)を用いた物体検出アルゴリズムです。現時点ではv2、v3までのアップグレードが存在します。また、Tiny YOLOというサイズの小さなバージョンも開発されています。YOLOは、SSDの物体検出アルゴリズムとは異なり、画像をバウンディングボックスで分割してクラス分類を行なっている。

     YOLO(YOLOv1)では、結果として、45FPSの処理速度を実現した。YOLO9000(YOLOv2)では、YOLOv1を改良し、1000種類の物体検出が可能になっています。しかし、各シーンごとに実際に利用するライブ映像での検出カテゴリーの種類は50種類以下だろうと思います。COCO Datasetに対して、40FPSにおいて、23.7 mAP(mean Average Precision)を達成した。YOLOv3では、220FPSにおいて33.1mAPを実現していると言われています。ちなみに、SSD300では、46FPSにおいて41.2mAPとなっています。YOLOの公式サイトはここです

     必要な環境は、ssdと同じく、
    python3==3.6
    tensorflow==1.8.0
    opencv==3.4.0
    を使用します。
     画像識別とリアル・タイムの物体検出を行います。web cameraからのリアル・タイムの物体検出を行うために、darkflowという名称のYOLOパッケージをインストールすることにします。GitHubのリポジトリはhttps://github.com/thtrieu/darkflowです。このrepositoryからパッケージを git clone してください。
    
    $ git clone https://github.com/thtrieu/darkflow.git
    $ cd darkflow
    
    
    以下の3つのコマンドうちいずれかでインストールができます。

    1. python3 setup.py build_ext --inplace

    2. pip install -e .

    3. pip install .
    この3つの違いはよくわかりませんが、1. でインストールしました。1.では、build the Cython extensions in place. NOTE: If installing this way you will have to use ./flow in the cloned darkflow directory と説明があるので、これを選択しました。プログラムの実行は ./flow コマンドを使用します。ディレクトリdarkflowに移動して

    (darkflow)$ ./flow --h

    と入力すると、オプションが表示されます。
    次に、YOLOの公式サイトからweightファイルをダウンロードします。以下の公式サイト内の 'here(258MB)' をクリックするとYOLOV3のweightsがダウンロードできます。ここでは、サイズの小さなyolo.weightsをダウンロードします。なので、
    
    $ wget https://pjreddie.com/media/files/yolo.weights
    
    

    と入力します。このサイトからもダウンロードできます。ダウンロードしたyolo.weightsをdarkflow/bin/ フォルダーに移動してください。
     画像ファイルからの物体検出は以下のコマンドを入力します。以下のオプションでは、デフォルトのフォルダー'sample_img' からすべての入力画像が読み込ままれ、検出結果は 'sample_img/out/'フォルダーに出力されます。
    
    $ ./flow --imgdir sample_img/ --model cfg/yolo.cfg --load bin/yolo.weights 
    
    

    自分の好きな画像を使用したいときは、入力画像の指定'sample_img/'を、例えば、'image/'のように変えます。'image/'の中に検出したい画像を配置してください。

    検出された画像の代表例は
    YOLO_2.png
    です。これ以外のweightsの組み合わせ、例えば、'yolo-tiny.cfg'と'yolo-tiny.weights'ではうまく検出ができません。また、'tiny-yolo.cfg'は見つかりません。

     自分でpythonプログラムを作成して、このdarkflowを利用する方法について説明します。 return_predict(img) は numpy.ndarray の形式です。イメージファイル'img'は前もって読み込んでおいてreturn_predict(img)に渡します。以下のように書きます。
    
    from darkflow.net.build import TFNet
    import cv2
    
    options = {"model": "cfg/yolo.cfg", "load": "bin/yolo.weights", "threshold": 0.1}
    
    tfnet = TFNet(options)
    
    imgcv = cv2.imread("./sample_img/sample_dog.jpg")
    result = tfnet.return_predict(imgcv)
    print(result)
    
    

    動画からの物体検出の方法ついて説明します。動画のファイルが'videofile.avi'であるとき
    
    $ ./flow --model cfg/yolo.cfg --load bin/yolo.weights --demo videofile.avi
    
    

    と入力します。実際の例はdemo gifにあります。

     次に、リアル・タイムでの物体検出のプログラムを見ましょう。上記のコマンドの最後のオプションに 'camera' を指定して、以下のように入力します。
    
    $ ./flow --model cfg/yolo.cfg --load bin/yolo.weights --demo camera
    
    

    web_camera(あるいは、PC内蔵)のカメラからの映像の物体検出が実行されます。検出された物体名が枠取りの上部に表示されます。web cameraの映像からリアル・タイムで物体検出するときは、以下のコードも利用できます。
    
    from darkflow.net.build import TFNet
    import cv2
    import numpy as np
     
    options = {"model": "cfg/yolo.cfg", "load": "bin/yolo.weights", "threshold": 0.1}
    tfnet = TFNet(options)
     
    # カメラの起動
    cap = cv2.VideoCapture(1)
     
    class_names = ['aeroplane', 'bicycle', 'bird', 'boat', 'bottle', 
                  'bus', 'car', 'cat', 'chair', 'cow', 'diningtable', 
                  'dog', 'horse', 'motorbike', 'person', 'pottedplant',
                  'sheep', 'sofa', 'train', 'tvmonitor']
     
    num_classes = len(class_names)
    class_colors = []
    for i in range(0, num_classes):
        hue = 255*i/num_classes
        col = np.zeros((1,1,3)).astype("uint8")
        col[0][0][0] = hue
        col[0][0][1] = 128
        col[0][0][2] = 255
        cvcol = cv2.cvtColor(col, cv2.COLOR_HSV2BGR)
        col = (int(cvcol[0][0][0]), int(cvcol[0][0][1]), int(cvcol[0][0][2]))
        class_colors.append(col) 
        
    def main():
        
        while(True):
            
            # 動画ストリームからフレームを取得
            ret, frame = cap.read()
            result = tfnet.return_predict(frame)
     
            for item in result:
                tlx = item['topleft']['x']
                tly = item['topleft']['y']
                brx = item['bottomright']['x']
                bry = item['bottomright']['y']
                label = item['label']
                conf = item['confidence']
     
                if conf > 0.6:
                    
                    for i in class_names:
                        if label == i:
                            class_num = class_names.index(i)
                            break
                    
                    #枠の作成
                    cv2.rectangle(frame, (tlx, tly), (brx, bry), class_colors[class_num], 2)
                    
                    #ラベルの作成
                    text = label + " " + ('%.2f' % conf)  
                    cv2.rectangle(frame, (tlx, tly - 15), (tlx + 100, tly + 5), class_colors[class_num], -1)
                    cv2.putText(frame, text, (tlx, tly), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,0,0), 1)
     
            # 表示
            cv2.imshow("Show FLAME Image", frame) 
     
            # 'q'を押したら終了。
            k = cv2.waitKey(10);
            if k == ord('q'):  break;
     
        cap.release()
        cv2.destroyAllWindows()
        
    if __name__ == '__main__':
        main()
    	
    

    このコードはai-coordinatorさんのサイトから援用したものです。検出可能な物体カテゴリーは20種類です。

     このコードをコピペして、web_camera.pyという名前で、darkflowフォルダーに保存してください。このフォルダーに移動して、以下のように入力すると実行されます。
    
    (darkflow)$ python web_camera,py
    
    Using TensorFlow backend.
    Parsing ./cfg/yolo.cfg
    Parsing cfg/yolo.cfg
    Loading bin/yolo.weights ...
    Successfully identified 203934260 bytes
    Finished in 0.039871931076049805s
    Model has a coco model name, loading coco labels.
    
    Building net ...
    Source | Train? | Layer description                | Output size
    -------+--------+----------------------------------+---------------
           |        | input                            | (?, 608, 608, 3)
     Load  |  Yep!  | conv 3x3p1_1  +bnorm  leaky      | (?, 608, 608, 32)
     Load  |  Yep!  | maxp 2x2p0_2                     | (?, 304, 304, 32)
     Load  |  Yep!  | conv 3x3p1_1  +bnorm  leaky      | (?, 304, 304, 64)
     Load  |  Yep!  | maxp 2x2p0_2                     | (?, 152, 152, 64)
     Load  |  Yep!  | conv 3x3p1_1  +bnorm  leaky      | (?, 152, 152, 128)
     Load  |  Yep!  | conv 1x1p0_1  +bnorm  leaky      | (?, 152, 152, 64)
     Load  |  Yep!  | conv 3x3p1_1  +bnorm  leaky      | (?, 152, 152, 128)
     Load  |  Yep!  | maxp 2x2p0_2                     | (?, 76, 76, 128)
     Load  |  Yep!  | conv 3x3p1_1  +bnorm  leaky      | (?, 76, 76, 256)
     Load  |  Yep!  | conv 1x1p0_1  +bnorm  leaky      | (?, 76, 76, 128)
     Load  |  Yep!  | conv 3x3p1_1  +bnorm  leaky      | (?, 76, 76, 256)
     Load  |  Yep!  | maxp 2x2p0_2                     | (?, 38, 38, 256)
     Load  |  Yep!  | conv 3x3p1_1  +bnorm  leaky      | (?, 38, 38, 512)
     Load  |  Yep!  | conv 1x1p0_1  +bnorm  leaky      | (?, 38, 38, 256)
     Load  |  Yep!  | conv 3x3p1_1  +bnorm  leaky      | (?, 38, 38, 512)
     Load  |  Yep!  | conv 1x1p0_1  +bnorm  leaky      | (?, 38, 38, 256)
     Load  |  Yep!  | conv 3x3p1_1  +bnorm  leaky      | (?, 38, 38, 512)
     Load  |  Yep!  | maxp 2x2p0_2                     | (?, 19, 19, 512)
     Load  |  Yep!  | conv 3x3p1_1  +bnorm  leaky      | (?, 19, 19, 1024)
     Load  |  Yep!  | conv 1x1p0_1  +bnorm  leaky      | (?, 19, 19, 512)
     Load  |  Yep!  | conv 3x3p1_1  +bnorm  leaky      | (?, 19, 19, 1024)
     Load  |  Yep!  | conv 1x1p0_1  +bnorm  leaky      | (?, 19, 19, 512)
     Load  |  Yep!  | conv 3x3p1_1  +bnorm  leaky      | (?, 19, 19, 1024)
     Load  |  Yep!  | conv 3x3p1_1  +bnorm  leaky      | (?, 19, 19, 1024)
     Load  |  Yep!  | conv 3x3p1_1  +bnorm  leaky      | (?, 19, 19, 1024)
     Load  |  Yep!  | concat [16]                      | (?, 38, 38, 512)
     Load  |  Yep!  | conv 1x1p0_1  +bnorm  leaky      | (?, 38, 38, 64)
     Load  |  Yep!  | local flatten 2x2                | (?, 19, 19, 256)
     Load  |  Yep!  | concat [27, 24]                  | (?, 19, 19, 1280)
     Load  |  Yep!  | conv 3x3p1_1  +bnorm  leaky      | (?, 19, 19, 1024)
     Load  |  Yep!  | conv 1x1p0_1    linear           | (?, 19, 19, 425)
    -------+--------+----------------------------------+---------------
    Running entirely on CPU
    Finished in 16.047261953353882s
    
    

      PCにUSB接続されたweb cameraからのライブ映像が表示され、物体検出が行われます。検出された物体名とその確率が枠取りの上部に表示されます。検出済みのライブ動画は保存されません。終了はターミナルで[Ctrl+c]を入力してください。

     物体検出のカテゴリー種類数を増加するために、検出した物体の識別のために、別のCNN、例えば、VGG16 などを使用するという方法があります。これを実現するためには、Kerasを使用する必要が生じます。



    YOLO(You Only Look Once) in TensorFlow framework: version 2(darknet)


     ここでは、YOLOVv2をダウンロードして用います。環境は上のケースと同じです。

    python3==3.6
    tensorflow==1.8.0
    opencv==3.4.0
    を使用します。
     ここで用いるYOLOのコードはdarknetと呼ばれるパッケージです。公式サイトはここですこの公式サイトで説明されている手続きに従って、インストールします。まずはGithubからクローンしましょう。そしてクローンしたフォルダに入ります。その後、makeしてビルドします。
    
    $ git clone https://github.com/pjreddie/darknet.git
    $ cd darknet
    $ make
    
    

    エラーが出ないで、コンパイルが正常に実行できたならば、
    
    (darknet)$ ./darknet
    
    

    と入力して、動作を確認します。以下のような表示が出ます。
    
    usage: ./darknet 
    
    

    これで、darknetは正常に作動します。working directoryに cfg/ディレクトリが存在しているので、pretrained modelのweigtsをダウンロードすれば、YOLOV2の実行ができます。
    
    (darknet)$ wget https://pjreddie.com/media/files/yolov2.weights
    
    

    と入力して、学習済み重み yolov2.weights をダウンロードします。
     YOLOv2モデルを用いた物体検出の実行は
    
    (darknet)$ ./darknet detect cfg/yolov2.cfg yolov2.weights data/dog.jpg
    
    

    と入力します。すると、
    layer     filters    size              input                output
        0 conv     32  3 x 3 / 1   416 x 416 x   3   ->   416 x 416 x  32  0.299 BFLOPs
        1 max          2 x 2 / 2   416 x 416 x  32   ->   208 x 208 x  32
        2 conv     64  3 x 3 / 1   208 x 208 x  32   ->   208 x 208 x  64  1.595 BFLOPs
        3 max          2 x 2 / 2   208 x 208 x  64   ->   104 x 104 x  64
        4 conv    128  3 x 3 / 1   104 x 104 x  64   ->   104 x 104 x 128  1.595 BFLOPs
    
    -----(中略)
    
       27 reorg              / 2    26 x  26 x  64   ->    13 x  13 x 256
       28 route  27 24
       29 conv   1024  3 x 3 / 1    13 x  13 x1280   ->    13 x  13 x1024  3.987 BFLOPs
       30 conv    425  1 x 1 / 1    13 x  13 x1024   ->    13 x  13 x 425  0.147 BFLOPs
       31 detection
    mask_scale: Using default '1.000000'
    Loading weights from yolov2.weights...Done!
    data/dog.jpg: Predicted in 6.236366 seconds.
    dog: 81%
    truck: 74%
    bicycle: 83%
    
    

    という結果が表示されます。検出された画像は
    YOLO_1.png
    です。

     web-cameraからのライブ映像で物体検出を実行するためのスクリプトを作成するために、MakefileでOpenCV=1として、makeするときにエラーが出てしまいます。インストールされたOpneCV2との相性が良くないようで、エラーを消せません。CUDAを使用していないことと関係しているようで、解決できません。なので、web cameraでキャプチャーした映像からリアル・タイムの物体検出を行うことはできませんでした。このエラーが解決するまで、このライブラリを使用することは諦めて、類似のライブラリを活用します。



    YOLO(You Only Look Once) in Keras framework: version 3


     Keras+Tensorflow framework 上で動作するYOLOアルゴリズムを実装します。'https://github.com/qqwweee/keras-yolo3'から

    forkedされたGitHubのリポジトリをダウンロードします。'keras-yolo3-master' という名前でフォルダーが作成されます。'keras-yolo3'としてください。

     Darknetで作成された学習済みモデルの重みをTensorflow形式に変換して、YOLOアルゴリズムをコード化します。  ここでは、YOLOVv3をダウンロードして用います。使用する環境は
    python3==3.6
    tensorflow==1.8.0
    Keras==2.1.5
    を使用します。

     YOLOv3 weights をYOLO websiteからダウンロードします。
    
    $ wget https://pjreddie.com/media/files/yolov3.weights
    
    

     次に、Darknet YOLO model の重みを Keras modelの重みに変換します。keras-yolo3 directoryを working directoryとして、yolov3.weights を keras-yolo3 ディレクトリに移動して、以下のように入力します。
    
    $ python convert.py yolov3.cfg yolov3.weights model_data/yolo.h5
    
    

    model_dataのフォルダーに yolo.h5という重みファイルが作成されます。画像ファイルからの物体検出はコード 'yolo.py' を使います。以下のように入力します。
    
    $ python yolo.py
    
    

    次のように表示されて、画像ファイルの入力が促されます。
    
    Using TensorFlow backend.
    model_data/yolo.h5 model, anchors, and classes loaded.
    Input image filename:
    
    

    画像ファイルを指定すると、検出済みの画像がpngファイルで表示されます。例えば、以下のような検出済み画像が表示されます。
    YOLO_4.png
     リアルタイムでの物体検出には、以下のようなスクリプトを作成します。
    from yolo import YOLO
    from yolo import detect_video
    
    if __name__ == '__main__':
        video_path = 1
        output_path = './output.avi'
        detect_video(YOLO(), video_path, output_path)
        # detect_video(YOLO(),video_path)
    

    このコードを、'yolo_camera.py' という名前で保存してください。次に、
    
    $ python yolo_camera.py
    
    

    と入力すると、USB接続したweb cameraからの映像が表示され、物体が検出されます。ターミナルには以下のような表示が出ます。以下の結果は、私の自宅で、机の前に置いたweb cameraからの映像で物体検出を実行した事例です。
    Using TensorFlow backend.
    model_data/yolo.h5 model, anchors, and classes loaded.
    !!! TYPE:    
    (416, 416, 3)
    Found 12 boxes for img
    book 0.32 (292, 384) (321, 444)
    book 0.37 (40, 297) (177, 341)
    book 0.62 (2, 357) (64, 572)
    book 0.73 (85, 395) (168, 598)
    book 0.79 (37, 394) (123, 592)
    book 0.81 (229, 382) (300, 593)
    book 0.96 (132, 391) (207, 594)
    book 0.97 (185, 388) (259, 590)
    laptop 1.00 (396, 547) (1221, 945)
    bottle 0.99 (597, 292) (675, 496)
    bottle 1.00 (246, 453) (473, 950)
    person 0.98 (624, 3) (1280, 933)
    6.729872999014333
    
    

    8冊の本、ラップトップPC、2本のペットボトルと人物が検出されています。2列目の数字は検出の正当確率を表示しています。最後の2列の数字は物体の推定位置を示します。検出済み動画は、'output.avi'ファイルで保存されます。動画のサイズは、数秒間で10MBを超えますので、注意してください。動画の保存をしたくないときは、'yolo_camera.py' にある1行
    detect_video(YOLO(), video_path, output_path) をコメントアウトして
    #detect_video(YOLO(), video_path, output_path)
    detect_video(YOLO(),video_path)
    と修正してください。検出できる物体のカテゴリー数は80種類(coco_classes)となっています。coco categories の内容。ちなみに、PASCAL voc_classes での種類数は20個です。

     なお、Tensorflowを1.13.1にバージョンアップしたら、[tensorflow. python. framework. errors_impl. AbortedError]というエラーが出て動きません。Tensorflowをダウングレードする以外に解決策はないようです。


    R-CNN (Regions with CNN features) in Keras framework


     最後に、R-CNN (Regions with CNN features)の発展系であるFaster R-CNNの Python 実装を取り上げます。最新の物体検出であるMask R-CNNをインストールします。github.com/matterport/Mask_RCNNからMask R-CNNのソースコードをダウンロードしてください。Mask_RCNN-masterというフォルダーが作成されて、そこにパッケージが配置されます。インストールを実行するために、

    
    $ cd Mask_RCNN-master
    (Mask_RCNN-master)$ python3 setup.py install
    
    

    と入力して、パッケージを実行可能にします。このモデルは、Python 3, Keras, and TensorFlow 上で実装されたMask R-CNNとなっていて、各イメージのインスタンスに対して bounding boxes and segmentation masks を生成します。これは、 Feature Pyramid Network (FPN) and a ResNet101 backbone に基づいています。必要とされる環境は
    numpy
    scipy
    Pillow
    cython
    matplotlib
    scikit-image
    tensorflow>=1.3.0
    keras>=2.0.8
    opencv-python
    h5py
    imgaug
    IPython[all]
    

    ですが、ここまでに、ほぼすべてのモジュールはインストールされています。この後でエラーなどが出ることがあれば、
    
    $ pip3 install package-name
    
    

    と念のためのインストールをしてみてください。

     また、このRCNNを使うためには、COCOAPIのインストールが必要になります。なので、GitHubからダウンロードしてインストールします。GitHubからダウンロードが完了したら、cocoapi-master というフォルダーが作成されます。
    
    $ cd cocoapi-master/PythonAPI
    (cocoapi-master/PythonAPI)$ python setup.py install
    
    

    と入力して、インストールします。

     最初に、exampleを実行してみましょう。jupyter notebookを起動して、Mask_RCNN-master/samples/demo.ipynb を開いてください。
    Mask R-CNN Demo
    A quick intro to using the pre-trained model to detect and segment objects.
    というタイトルのブックが開きますので、上から順番にセルを実行してください。最初のセルを実行すると、以下のように、pretrained modelがダウンロードされます。
    Downloading pretrained model to /Users/koichi/Object-Detection/Mask_RCNN-master/mask_rcnn_coco.h5 ...
    ... done downloading pretrained model!

    最後に以下の画像が表示されます。
    RCNN_1.png
    画像はランダムに選択されていますので、毎回の実行ごとに異なります。

     Tensorflowを1.13.1にバージョンアップしたら、[AttributeError: module 'keras.engine.topology' has no attribute 'load_weights_from_hdf5_group_by_name']というエラーが出流可能性があります。

     次に、web cameraからのライブ映像の物体検出を取り上げます。以下のpython コードを作成してください。

    live_camera.py という名前でMask_RCNN-master/samples/ディレクトリに保存してください。
    
    $ cd Mask_RCNN-master/samples/
    $ python live_camera.py
    
    

    と入力して実行します。検出された物体を各色でマスクされた映像が表示されます。ラップトップPCのディスプレイからすると、映像のサイズが少し大きすぎるかもしれません。各自でサイズは調整してください。物体クラスはCOCO分類の80種類です。

     検出の精度は素晴らしいのですが、やはり、CPUでは処理に相当な時間がかかり、画像の切り替えが遅すぎて、リアルタイム感がありません。[Ctrl+c]を入力してからの終了処理も数十秒かかります。遅すぎて実用に耐えないと思います。

     Tensorflowを1.13.1にバージョンアップしたら、[AttributeError: module 'keras.engine.topology' has no attribute 'load_weights_from_hdf5_group_by_name']というエラーが出流可能性があります。その場合、KerasをKeras=2.1.6にダウングレードすれば正常に作動しますが、それ以外の解決策は見出せません。

    PyTorchでObject Detectionのページに移る

    このページの先頭に戻る