2016年5月8日 星期日

Raspberry Pi: Real-Time Face Detection With Camera Module

since: 2016/05/08
update: 2016/05/08
reference:
1. openframeworks
2. I touchs: openFrameworks: Control The Raspberry Pi Camera Module

A. 功能測試: opencvHaarFinderExample
    // 單張照片臉部辨識
    $ cd /home/pi/of_v0.9.3/examples/addons/opencvHaarFinderExample
    $ make
    $ ./bin/opencvHaarFinderExample    // 結果


-----------------------------------------------------------------------------------------------
B. 功能測試: example-texture-mode
     // Camera Module
     $ cd /home/pi/of_v0.9.3/addons/
     $ git clone https://github.com/jvcleave/ofxRPiCameraVideoGrabber
     $ cd /home/pi/of_v0.9.3/addons/ofxRPiCameraVideoGrabber/example-texture-mode
     $ make
     $ ./bin/example-texture-mode

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

C. Face Detection With Camera Module
     1. addons.make
         ofxOpenCv
         ofxRPiCameraVideoGrabber

***********************************************

     2. main.cpp
#include "ofMain.h"
#include "ofApp.h"
#include "ofGLProgrammableRenderer.h"

int main()
{
    ofSetLogLevel(OF_LOG_VERBOSE);
   
    // read config file
    vector<string> _linesOfTheFile;
    ofBuffer _buffer = ofBufferFromFile("config.txt");
    for (auto line : _buffer.getLines()){
        _linesOfTheFile.push_back(line);
    }
   
    // local variables
    int _debug = ofToBool(_linesOfTheFile[1]);
    int _camWidth = ofToInt(_linesOfTheFile[4]);
    int _camHeight = ofToInt(_linesOfTheFile[7]);
    bool _fullScreen = ofToBool(_linesOfTheFile[10]);
   
    // show debug message
    if(_debug) {
        ofLog() << "****** main()";
        ofLog() << "debug: " << _debug;
        ofLog() << "OpenGL width: " << _camWidth;
        ofLog() << "OpenGL height: " << _camHeight;
        ofLog() << "fullScreen: " << _fullScreen;
    }
   
    ofGLESWindowSettings settings;
    //settings.width = 320;
    //settings.height = 240;

    settings.width = _camWidth;
    settings.height = _camHeight;
   
    settings.setGLESVersion(2);
    ofCreateWindow(settings);
   
    ofRunApp( new ofApp());
}


***********************************************

     3. ofApp.h
#pragma once

#include "ofMain.h"
#include "TerminalListener.h"
#include "RPiVideoGrabber.h"
#include "ofxCvHaarFinder.h"

class ofApp : public ofBaseApp, public KeyListener{

    public:

        void setup();
        void update();
        void draw();
        void keyPressed(int key);

    void onCharacterReceived(KeyListenerEventData& e);
    TerminalListener consoleListener;
   
    //wrapper class for drop-in replacement of ofVideoGrabber
    RPiVideoGrabber vidGrabber;
   
    //@add for CvHaarFinder
    ofxCvHaarFinder finder;
    ofImage grayImg;
    //ofImage img;

    //@add second record
    float countROI;
    long readSeconds; // read from totalSeconds record file
    long writeSeconds; // write to totalSeconds record file
    long latestSeconds; // latestSeconds
   
    // config file
    bool debug;
    int camWidth;
    int camHeight;
    bool fullScreen;
    int frameRate;
    bool concurrentVisit;
    float minROI;
    float maxROI;
    float weightROI;
    string recordFile;
};


***********************************************

    4. ofApp.cpp
#include "ofApp.h"

//--------------------------------------------------------------

void ofApp::setup()
{
    ofSetLogLevel(OF_LOG_VERBOSE);
   
    // read config file
    vector<string> linesOfTheFile;
    ofBuffer buffer = ofBufferFromFile("config.txt");
    for (auto line : buffer.getLines()){
        linesOfTheFile.push_back(line);
    }
    //for (int i = 0; i < linesOfTheFile.size(); i++) {
    //    ofLog(OF_LOG_VERBOSE, "cur.width = %s", linesOfTheFile[i].c_str());
    //}

   
    debug = ofToBool(linesOfTheFile[1]);
    camWidth = ofToInt(linesOfTheFile[4]);
    camHeight = ofToInt(linesOfTheFile[7]);
    fullScreen = ofToBool(linesOfTheFile[10]);
    frameRate = ofToInt(linesOfTheFile[13]);
    concurrentVisit = ofToBool(linesOfTheFile[16]);
    minROI = ofToFloat(linesOfTheFile[19]);
    maxROI = ofToFloat(linesOfTheFile[22]);
    weightROI = ofToFloat(linesOfTheFile[25]);
    recordFile = linesOfTheFile[28];
   
    if(debug)
    {
        ofLog() << "****** ofApp::setup()";
        ofLog() << "debug: " << debug;
        ofLog() << "camWidth: " << camWidth;
        ofLog() << "camHeight: " << camHeight;
        ofLog() << "fullScreen: " << fullScreen;
        ofLog() << "frameRate: " << frameRate;
        ofLog() << "concurrentVisit: " << concurrentVisit;
        ofLog() << "minROI: " << minROI;
        ofLog() << "maxROI: " << maxROI;
        ofLog() << "weightROI: " << weightROI;
        ofLog() << "recordFile: " << recordFile;
    }
   
    // read totalSeconds record file
    vector<string> totalSecondsFile;
    ofBuffer sbuffer = ofBufferFromFile(recordFile);
    for (auto line : sbuffer.getLines()){
        totalSecondsFile.push_back(line);
    }
   
    readSeconds = ofToFloat(totalSecondsFile[0]);
   
    if(debug)
    {
        ofLog() << "****** read totalSeconds record file";
        ofLog() << "readSeconds: " << readSeconds;
    }
   
    //ofSetFrameRate(5);
    ofSetFrameRate(frameRate);
   
    //allows keys to be entered via terminal remotely (ssh)
    consoleListener.setup(this);
   
    //vidGrabber.setDesiredFrameRate(30);
    vidGrabber.setDesiredFrameRate(frameRate);
    vidGrabber.initGrabber(camWidth, camHeight);
   
    //@add for CvHaarFinder
    //img.load("test.jpg");

    finder.setup("haarcascade_frontalface_default.xml");
    //finder.findHaarObjects(img);
}

//--------------------------------------------------------------
void ofApp::update()
{
    ofBackground(100, 100, 100);
    vidGrabber.update();
   
    if(vidGrabber.isFrameNew())
    {
        //ofPixels & pixels = vidGrabber.getPixels();
        //finder.findHaarObjects(pixels);

        grayImg.setFromPixels(vidGrabber.getPixels());
        grayImg.setImageType(OF_IMAGE_GRAYSCALE);

       
        finder.findHaarObjects(grayImg);
    }
}


//--------------------------------------------------------------
void ofApp::draw(){

    ofSetHexColor(0xffffff);
    //ofSetColor(ofColor::white);
   
    vidGrabber.draw(0, 0);
   
    //@add for CvHaarFinder
    //img.draw(0, 0);

    ofNoFill();
   
    for(unsigned int i = 0; i < finder.blobs.size(); i++) {
       
        ofRectangle cur = finder.blobs[i].boundingRect;
       
        //if(debug){
        //    ofLog(OF_LOG_VERBOSE, "ROI width = %f", cur.width);
        //    ofLog(OF_LOG_VERBOSE, "ROI height = %f", cur.height);
        //}

       
        //if((cur.width >= 50.0 && cur.width <= 150.0) &&
        //   (cur.height >= 50.0 && cur.height <= 150.0)) {

        if((cur.width >= (minROI * camWidth) && cur.width <= (maxROI * camWidth)) &&
           (cur.height >= (minROI * camWidth) && cur.height <= (maxROI * camWidth))) {
            countROI++;
            ofSetColor(255, 0, 0); // red color
            ofDrawRectangle(cur.x, cur.y, cur.width, cur.height);
           
            if(debug) {
                ofSetColor(ofColor::yellow);
                ofDrawBitmapString("ROI = " + ofToString(cur.width) + " x " + ofToString(cur.height), camWidth/5, camHeight/1.02);
            }
            // not concurrent Visit
            if(!concurrentVisit){
                break;
            }
        }
        else {
            ofSetColor(0, 0, 255); // blue color
            ofDrawRectangle(cur.x, cur.y, cur.width, cur.height);
        }
    }
   
    // writeSeconds
    writeSeconds = readSeconds + (countROI / frameRate * weightROI); // weightROI: for calibrate detect missing
   

    if(writeSeconds > latestSeconds){
        // Write data
        if(debug) {
            // totalSeconds record file
            ofLog() << "****** write totalSeconds record file: " << writeSeconds;
        }
       
        ofBuffer secondsBuff;
        secondsBuff.set(ofToString(writeSeconds));
        bool fileWritten = ofBufferToFile(recordFile, secondsBuff);
       
        latestSeconds = writeSeconds;
    }
   
    if(debug){
        // show message
        ofSetColor(ofColor::white);
        ofDrawBitmapString("total seconds: " + ofToString(writeSeconds), camWidth/5, camHeight/1.2);
        ofDrawBitmapString(ofToString(minROI * camWidth) + " <= ROI <= " + ofToString(maxROI * camWidth), camWidth/5, camHeight/1.1);
    }
   
    ofSetColor(100, 100, 100);
}

//--------------------------------------------------------------
void ofApp::keyPressed  (int key)
{
    ofLog(OF_LOG_VERBOSE, "%c keyPressed", key);
    //if (key == 'e')
    //{
    //}
    //@add for VideoGrabber

    if(key == 'd' || key == 'D'){
        debug = !debug;
    }
}

void ofApp::onCharacterReceived(KeyListenerEventData& e)
{
    keyPressed((int)e.character);
}


***********************************************

   5. bin/data 資料夾
        a. haarcascade_frontalface_default.xml // from ofxOpenCv

        b. totalSeconds.txt // record second
            0

        c. config.txt // config file
# debug (true/false)
false

# cam width (int)
320

# cam height (int)
240

# full screen (true/false)
false

# frame rate (int)
5

# concurrent visit (true/false)

false

# minimum width ratio of ROI(region of interest) (float)
0.125

# maximum width ratio of ROI(region of interest) (float)
0.5

# weight of ROI (float)
1.0

# recordFile (string)
totalSeconds.txt

沒有留言:

張貼留言

注意:只有此網誌的成員可以留言。