Take’s diary

Macとマイコンに関すること--ワクワクの製作日記

Jetson TX2 にインストールした OpenFremeworks でも YOLOを動かす。

TX2でYOLOがどのくらいのスピードになるか?

f:id:TAKEsan:20181004220526j:plain

      ちょっと埃をかぶってますが、以下の動画は紛れもなくこのTX2で実行してます。

 これは、weightデータがTiny YOLOではなく標準のYOLO V2です。使ったデータは今回の場合80クラスを認識しますが、コンピューターにとって全世界が80項目しかないので誤認識があります。でもハマったものはなかなか素晴らしい結果でした。

     今回TX2でYOLOを実行させた結果です。画像のスピードは問題なし。YOLOの認識速度もなかなか!!(画像がボケているのにこの辺りがAIですかね......)

 前の記事でJetson XvierにインストールしたopenFrameworksYOLOを動かしてみましたが、なかなか良い結果が出たので、じゃーTX2で実行したらどうなるのかってのが今回の実験です。

TX2へのOpenframeworksのインストールはこの記事を参照して下さい。

takesan.hatenablog.com

 で、YOLOのインストールは

takesan.hatenablog.com

TX2Xavierに勝とうっていうのは所詮無理な話で、

 少しでもXavierに近づけるためにマルチスレッドを利用します(OF上ではofThreadを利用)。Xavierでも裏スレッドを1個使って実現させましたが、今回は2個使いますGPUはマルチスレッド対応していないということが頭に入ってました。でも、「微妙に時間をずらすことでGPUをうまく使えないか」ってことが今回の発想です。ここでもやはりデータ変換が鍵を握ってて、ちょっと時間がかかりましたが、なんとなく狙い通りになってるようです。

まずyolov2.cfgの設定ですが

最初の方を

batch=32

subdivisions=8

weight=416

height=416

にしました。weight、heightとも608にするのが理想的ですが、あまり認識に変化が無いようなのでスピード重視です。yolov2.cfgが何者かは、前の記事を確認して下さい。

 また、Web CameraのopenFrameworks側設定画像は640x480。相当粗い画像ですがYOLOはそれでも満足の行く結果を出してしまいます。これもスピード対策。openFrameworkeのソースは次の通りです。

 ただし、まだバグが残っているようでmake runしてもエラーが出る場合があります。その場合は、何度もmake run してみて下さい(Xavierも同じ)

main.cpp


#include "ofMain.h"
#include "ofApp.h"
//========================================================================
int main( ){

	ofSetupOpenGL(640,480, OF_WINDOW);			// <-------- setup the GL context

	// this kicks off the running of my app
	// can be OF_WINDOW or OF_FULLSCREEN
	// pass in width and height too:
	ofRunApp( new ofApp());

}

で、ofApp.h


#pragma once

#include "ofMain.h"
#include "ofxCv.h"

class ofApp : public ofBaseApp{
	public:
		void setup();
		void update();
		void draw();
		
		void keyPressed(int key);
		void keyReleased(int key);
		void mouseMoved(int x, int y);
		void mouseDragged(int x, int y, int button);
		void mousePressed(int x, int y, int button);
		void mouseReleased(int x, int y, int button);
		void mouseEntered(int x, int y);
		void mouseExited(int x, int y);
		void windowResized(int w, int h);
		void dragEvent(ofDragInfo dragInfo);
		void gotMessage(ofMessage msg);
		
		
		ofVideoGrabber video;
		ofImage img;

最後にofApp.cpp


#include "ofApp.h"
#include "src1/yolo_v2_class.hpp"    // imported functions from DLL

std::string  names_file = 	"data/coco.names";
std::string  cfg_file = 	"cfg/yolov2.cfg";
std::string  weights_file = "yolov2.weights";

float const thresh = 0.20;

cv::Mat 		mat;
ofTrueTypeFont cop20,cop50;
Detector detector(cfg_file, weights_file);
std::vector result_vec,result_vec1,result_vec2 ;
float ttt,ttt1,ttt2,sss,sss1;  //Time
image_t xxx,yyy,zzz;
std::vector objects_names_from_file(std::string const filename) {
    std::ifstream file(filename);
    std::vector file_lines;
    if (!file.is_open()) return file_lines;
    for(std::string line; getline(file, line);) file_lines.push_back(line);
    std::cout << "object names loaded \n";
    file.close();
    return file_lines;
}

std::vector obj_names;
  
void show_console_result(std::vector const result_vec, std::vector const obj_names) {

    for (auto &i : result_vec) {
        if (obj_names.size() > i.obj_id) 
			ofNoFill();
			ofSetLineWidth(1);
        
			//Color Set!!
			int const colors[6][3] = { { 1,0,1 },{ 0,0,1 },{ 0,1,1 },{ 0,1,0 },{ 1,1,0 },{ 1,0,0 } };
			int const offset = i.obj_id * 123457 % 6;
			int const color_scale = 150 + (i.obj_id * 123457) % 100;
			ofSetColor(colors[offset][0]*color_scale, colors[offset][1]*color_scale, colors[offset][2]*color_scale);
			ofDrawRectRounded(i.x,i.y,i.w,i.h,5);
			//Mozi Draw!!
			string ss;
			ss=" "+ obj_names[i.obj_id]+" "+ofToString(i.prob*100,1);
			//ofFill();
			//ofDrawRectangle(i.x,i.y,i.w,20);
			ofSetColor(255);
			cop20.drawString(ss, i.x,i.y+15);
    }
}
static image_t make_empty_image(int w, int h, int c)
    {
        image_t out;
        out.data = 0;
        out.h = h;
        out.w = w;
        out.c = c;
        return out;
    }

static image_t make_image_custom(int w, int h, int c)
    {
        image_t out = make_empty_image(w, h, c);
        out.data = (float *)calloc(h*w*c, sizeof(float));
        return out;
    }
static image_t ipl_to_image(IplImage* src)
    {
        unsigned char *data = (unsigned char *)src->imageData;
        int h = src->height;
        int w = src->width;
        int c = src->nChannels;
        int step = src->widthStep;
        image_t out = make_image_custom(w, h, c);
        int count = 0;

        for (int k = 0; k < c; ++k) {
            for (int i = 0; i < h; ++i) {
                int i_step = i*step;
                for (int j = 0; j < w; ++j) {
                    out.data[count++] = data[i_step + j*c + k] / 255.;
                }
            }
        }

        return out;
    }

void detect_x(image_t x)
{
	    result_vec = detector.detect(x,thresh,false); 
}
void detect_y(image_t x)
{
	    result_vec1 = detector.detect(x,thresh,true); 
}
void detect_z(image_t x)
{
	    result_vec2 = detector.detect(x,thresh,true); 
}
//--------------------------------------------------------------
//  DetectNet部分をマルチスレッドにする。
class Detect_x: public ofThread {
public:
	
	void threadedFunction(){

		ok=false;
		detect_x(xxx);    
                ok2=true  ;       
		ok=true;
	}
	bool ok;
};

Detect_x Found_X;
//--------------------------------------------------------------
//  DetectNet部分をマルチスレッドにする。
class Detect_y: public ofThread {
public:
	
	void threadedFunction(){

		ok1=false;
		
			cv::Mat imgy;
			cv::cvtColor(mat, imgy, cv::COLOR_RGB2BGR);
			std::shared_ptr image_ptr1(new image_t, [](image_t *imgy) { detector.free_image(*imgy); delete imgy; });
			std::shared_ptr ipl_small1 = std::make_shared(imgy);
			*image_ptr1 = ipl_to_image(ipl_small1.get());
			yyy=*image_ptr1;

		detect_y(yyy);    
		ok3=true  ;       
		ok1=true;
	}
	bool ok1;
};

Detect_y Found_Y;

//--------------------------------------------------------------
void ofApp::setup(){
obj_names = objects_names_from_file(names_file);
    cop20.load("cooperBlack.ttf",10,true,true,true);
    cop50.load("cooperBlack.ttf",30,true,true,true);
    img.allocate(640,480,OF_IMAGE_COLOR);
    video.setDeviceID( 0 );
	//video.setDesiredFrameRate( 30 );
	video.setup(640,480,OF_PIXELS_RGBA);
	Found_X.ok=true;
	Found_Y.ok1=true;
	ok2=true;
	ok3=true;
}

//--------------------------------------------------------------
void ofApp::update(){
//ofLog() << ofGetFrameRate();
	video.update();
	if(video.isFrameNew()==true){
		img.setFromPixels(video.getPixels().getData(),video.getWidth(),video.getHeight(),OF_IMAGE_COLOR);
		mat=ofxCv::toCv(img);
                if (Found_X.ok){
			cv::Mat imgx;
			cv::cvtColor(mat,imgx, cv::COLOR_RGB2BGR);
			std::shared_ptr image_ptr(new image_t, [](image_t *imgx) { detector.free_image(*imgx); delete imgx; });
			std::shared_ptr ipl_small = std::make_shared(imgx);
			*image_ptr = ipl_to_image(ipl_small.get());
			xxx=*image_ptr;
                        
			Found_X.startThread();
                }
		else if(Found_Y.ok1)  Found_Y.startThread();
    }
}
//--------------------------------------------------------------
void ofApp::draw(){
   ofSetColor(255);
   video.draw( 0, 0 );
   Found_X.lock();
   show_console_result(result_vec, obj_names);
   Found_X.unlock();
   Found_Y.lock();
   show_console_result(result_vec1, obj_names);
   Found_Y.unlock();
}
//--------------------------------------------------------------
void ofApp::keyPressed(int key){
}
//--------------------------------------------------------------
void ofApp::keyReleased(int key){
}
//--------------------------------------------------------------
void ofApp::mouseMoved(int x, int y){
}
//--------------------------------------------------------------
void ofApp::mouseDragged(int x, int y, int button){
}
//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button){
}
//--------------------------------------------------------------
void ofApp::mouseReleased(int x, int y, int button){
}
//--------------------------------------------------------------
void ofApp::mouseEntered(int x, int y){
}
//--------------------------------------------------------------
void ofApp::mouseExited(int x, int y){
}
//--------------------------------------------------------------
void ofApp::windowResized(int w, int h){
}
//--------------------------------------------------------------
void ofApp::gotMessage(ofMessage msg){
}
//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo){ 
}