OpenCV T-API的測試(二)

嘗試視頻處理


上一次就是簡單的跑了下邊緣檢測函卒,在上次的代碼中全部都是使用的OpenCV原生API戏溺,最后的數(shù)據(jù)也說明了OpenCL是有用的。

這一次嘗試人臉識別拦止,同樣有是CPU和OpenCL測試县遣。

但是這一次無法像上次那樣打印出全部數(shù)據(jù)然后做總結(jié),只能大體上根據(jù)FPS和硬件使用率來判斷。

首先放上代碼:
facedetect.cpp

#include <iostream>
#include "opencv2/objdetect.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
using namespace std;
using namespace cv;

void detect_cpu(cv::Mat frame);
void detect_opencl(cv::Mat frame); // Transparent API

CascadeClassifier face_cascade;
CascadeClassifier eyes_cascade;

int main( int argc, const char** argv )
{
    // read xml files
    string face_cascade_file = haarcascade_frontalface_alt.xml的路徑;
    string eye_cascade_file = haarcascade_eye_tree_eyeglasses.xml的路徑;
    face_cascade.load(face_cascade_file);
    if( !face_cascade.load(face_cascade_file) ){
        cerr << "Error loading face cascade\n";
        return -1;
    }

    eyes_cascade.load(eye_cascade_file);
    if( !eyes_cascade.load(eye_cascade_file) ){
        cerr << "Error loading eyes cascade\n";
        return -1;
    }

    VideoCapture capture;
    capture.open(0); // read frame from camera 0
    if (!capture.isOpened()){
        cerr << "Error opening video capture\n";
        return -1;
    }
    while (1){    
        Mat frame;
        capture >> frame;
        detect_cpu(frame);
        // detect_opencl(frame);
        char key = (char)waitKey(1);
        if(key == 27 || key == 'q' || key == 'Q')break;
    }
    return 0;
}


void detect_opencl(cv::Mat frame){
    double start = (double)getTickCount();
    UMat Uframe;
    frame.copyTo(Uframe); // copy Mat frame -> UMat Uframe
    UMat Uframe_gray;
    cvtColor( Uframe, Uframe_gray, COLOR_BGR2GRAY );
    equalizeHist( Uframe_gray, Uframe_gray );
    //-- Detect faces
     std::vector<Rect> faces;
     face_cascade.detectMultiScale( Uframe_gray, faces );

     for ( size_t i = 0; i < faces.size(); i++ ){
         Point center( faces[i].x + faces[i].width/2, faces[i].y + faces[i].height/2 );
        ellipse( Uframe, center, Size( faces[i].width/2, faces[i].height/2 ), 0, 0, 360, Scalar( 255, 0, 255 ), 4 );
         UMat faceROI = Uframe_gray( faces[i] );
        //-- In each face, detect eyes
         std::vector<Rect> eyes;
         eyes_cascade.detectMultiScale( faceROI, eyes );

         for ( size_t j = 0; j < eyes.size(); j++ ){
             Point eye_center( faces[i].x + eyes[j].x + eyes[j].width/2, faces[i].y + eyes[j].y + eyes[j].height/2 );
             int radius = cvRound( (eyes[j].width + eyes[j].height)*0.25 );
             circle( Uframe, eye_center, radius, Scalar( 255, 0, 0 ), 4 );
         }
     }
    double time_consume = ((double)getTickCount()  - start) / getTickFrequency();
    double fps = 1.0 / time_consume;
    char str[50];
    sprintf(str,"Resolution: %dx%d and FPS:%.2f",Uframe.cols,Uframe.rows,fps);
    putText(Uframe,str,Point(0,30),FONT_HERSHEY_TRIPLEX,1,Scalar(0,0,255),2,8); //show resolution and fps
    imshow( "Process with OpenCL", Uframe ); //show Uframe

}

void detect_cpu(cv::Mat frame){
    double start = (double)getTickCount();
    Mat frame_gray;
    cvtColor( frame, frame_gray, COLOR_BGR2GRAY );
    equalizeHist( frame_gray, frame_gray );
    //-- Detect faces
    std::vector<Rect> faces;
    face_cascade.detectMultiScale( frame_gray, faces );
    for ( size_t i = 0; i < faces.size(); i++ )
    {
        Point center( faces[i].x + faces[i].width/2, faces[i].y + faces[i].height/2 );
        ellipse( frame, center, Size( faces[i].width/2, faces[i].height/2 ), 0, 0, 360, Scalar( 255, 0, 255 ), 4 );
        Mat faceROI = frame_gray( faces[i] );
        //-- In each face, detect eyes
        std::vector<Rect> eyes;
        eyes_cascade.detectMultiScale( faceROI, eyes );
        for ( size_t j = 0; j < eyes.size(); j++ )
        {
            Point eye_center( faces[i].x + eyes[j].x + eyes[j].width/2, faces[i].y + eyes[j].y + eyes[j].height/2 );
            int radius = cvRound( (eyes[j].width + eyes[j].height)*0.25 );
            circle( frame, eye_center, radius, Scalar( 255, 0, 0 ), 4 );
        }
    }

    double time_consume = ((double)getTickCount()  - start) / getTickFrequency();
    double fps = 1.0 / time_consume;
    char str[50];
    sprintf(str,"Resolution: %dx%d and FPS:%.2f",frame.cols,frame.rows,fps); //show resolution and fps
    putText(frame,str,Point(0,30),FONT_HERSHEY_TRIPLEX,1,Scalar(0,0,255),2,8);
    imshow("Process with CPU",frame);
}

xml文件出填上正確的的文件絕對路徑艺玲,參考編譯命令如下
clang++ -std=c++11 facedetect.cpp -o facedetect `pkg-config --cflags --libs opencv4`

運行結(jié)果:


CPU運行結(jié)果

可以看到括蝠,幀數(shù)很低,基本上就像是放映PPT饭聚,而且CPU占用飚滿。

要使用OpenCL運行搁拙,請注釋掉40行的detect_cpu(frame)函數(shù)秒梳,然后取消掉下一行的detect_opencl(frame),重新編譯運行箕速。

這里問題就來了:OpenCL的運行結(jié)果酪碘,和CPU是一樣的。(就連硬件占用率也一樣盐茎,參考上圖)

這就不免讓人感到很疑惑了兴垦,OpenCV官方說明是絕大多數(shù)的API是可以直接用UMat的,那么我代碼里面字柠,與OpenCV相關(guān)的函數(shù)就應(yīng)該都沒有問題探越,于是抱著試試的心態(tài),我做了些更改:

注釋掉以下代碼窑业,僅做最基本的顏色空間轉(zhuǎn)換和直方圖均量化:

// std::vector<Rect> faces;
    // face_cascade.detectMultiScale( Uframe_gray, faces );

    // for ( size_t i = 0; i < faces.size(); i++ ){
    //     Point center( faces[i].x + faces[i].width/2, faces[i].y + faces[i].height/2 );
    //     ellipse( Uframe, center, Size( faces[i].width/2, faces[i].height/2 ), 0, 0, 360, Scalar( 255, 0, 255 ), 4 );
    //     UMat faceROI = Uframe_gray( faces[i] );
    //     //-- In each face, detect eyes
    //     std::vector<Rect> eyes;
    //     eyes_cascade.detectMultiScale( faceROI, eyes );

    //     for ( size_t j = 0; j < eyes.size(); j++ ){
    //         Point eye_center( faces[i].x + eyes[j].x + eyes[j].width/2, faces[i].y + eyes[j].y + eyes[j].height/2 );
    //         int radius = cvRound( (eyes[j].width + eyes[j].height)*0.25 );
    //         circle( Uframe, eye_center, radius, Scalar( 255, 0, 0 ), 4 );
    //     }
    // }

然后再重新編譯钦幔,查看運行結(jié)果:


OpenCL基本處理(沒有識別的部分)

這樣一看,CPU使用率下來了常柄,然后是有GPU使用率的鲤氢,雖然使用率很低。最后就是FPS西潘,有點虛飄(攝像頭每秒能捕捉的幀數(shù)都沒有這么高卷玉,但是至少明顯的延遲是沒有的)

原因分析


忽略那虛飄的FPS,考慮實際的問題:OpenCV中人臉檢測使用的是 detectMultiScale函數(shù)喷市。它可以檢測出圖片中所有的人臉相种,并使用std::vector保存各個人臉的坐標(biāo)、大小东抹,函數(shù)由分類器對象調(diào)用蚂子。

首先,我們要定義保存臉部和眼部的vector缭黔,然后使用detectMultiScale函數(shù)將識別到的臉部和眼部信息保存至我們定義的std::vector<Rect> facesstd::vector<Rect> eyes中食茎,vector中有了點(Point)的信息,那么我們便可以使用循環(huán)遍歷后繪制橢圓(ellipse)和圓形(circle)馏谨。

1.問題就出在detectMultiScale函數(shù)上别渔,執(zhí)行這個函數(shù)的時間是最長的。
2.具體到變量就在std::vector faces上:OpenCV官網(wǎng)的說明是,當(dāng)有不滿足T-API使用需求的函數(shù)或變量哎媚,UMat就會變成普通的Mat喇伯;那么很顯然,我們的vector并沒有放入OpenCL設(shè)備中去計算拨与。

所以去掉了識別處理的這部分稻据,會發(fā)現(xiàn)其實GPU有占用率(雖然很小)买喧。

后續(xù)解決辦法


挖坑嘛捻悯,固然是有的,至于這個坑能不能填起來淤毛,我就不確定了今缚。
detectMultiScale這個函數(shù)是不支持T-API的。故沒有較好的解決辦法低淡。除非是了解算法原理后姓言,重新寫一個OpenCL版本的函數(shù)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蔗蹋,一起剝皮案震驚了整個濱河市何荚,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌纸颜,老刑警劉巖兽泣,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異胁孙,居然都是意外死亡唠倦,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門涮较,熙熙樓的掌柜王于貴愁眉苦臉地迎上來稠鼻,“玉大人,你說我怎么就攤上這事狂票『虺荩” “怎么了?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵闺属,是天一觀的道長慌盯。 經(jīng)常有香客問我,道長掂器,這世上最難降的妖魔是什么亚皂? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮国瓮,結(jié)果婚禮上灭必,老公的妹妹穿的比我還像新娘狞谱。我一直安慰自己,他們只是感情好禁漓,可當(dāng)我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布跟衅。 她就那樣靜靜地躺著,像睡著了一般播歼。 火紅的嫁衣襯著肌膚如雪伶跷。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天秘狞,我揣著相機與錄音撩穿,去河邊找鬼。 笑死谒撼,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的雾狈。 我是一名探鬼主播廓潜,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼善榛!你這毒婦竟也來了辩蛋?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤移盆,失蹤者是張志新(化名)和其女友劉穎悼院,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體咒循,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡据途,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了叙甸。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片颖医。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖裆蒸,靈堂內(nèi)的尸體忽然破棺而出熔萧,到底是詐尸還是另有隱情,我是刑警寧澤僚祷,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布佛致,位于F島的核電站,受9級特大地震影響辙谜,放射性物質(zhì)發(fā)生泄漏俺榆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一筷弦、第九天 我趴在偏房一處隱蔽的房頂上張望肋演。 院中可真熱鬧抑诸,春花似錦、人聲如沸爹殊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽梗夸。三九已至层玲,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間反症,已是汗流浹背辛块。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留铅碍,地道東北人润绵。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像胞谈,于是被迫代替她去往敵國和親尘盼。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,877評論 2 345