實現(xiàn)人臉識別 (vs2013+opencv3.0)

臉部識別實現(xiàn)(vs2013+opencv3.0)

第一種實現(xiàn)

  1. 這種是通過研究源碼 更改而來,第二種是第一種的簡化,代碼少了很多,而且邏輯比較清楚;具體的實現(xiàn)在代碼里面有注釋,雖然是英文的,還是比較簡單,需要注意的一個api就是:cascade.detectMultiScale()

  2. cascade.detectMultiScale()理解:

            #include "opencv2/objdetect.hpp"
            #include "opencv2/imgcodecs.hpp"
            #include "opencv2/videoio.hpp"
            #include "opencv2/highgui.hpp"
            #include "opencv2/imgproc.hpp"
            #include "opencv2/core/utility.hpp"
            
            #include "opencv2/videoio/videoio_c.h"
            #include "opencv2/highgui/highgui_c.h"
            
            #include <cctype>
            #include <iostream>
            #include <iterator>
            #include <stdio.h>
            
            using namespace std;
            using namespace cv; 
            void detectAndDraw(Mat& img, CascadeClassifier& cascade,
            CascadeClassifier& nestedCascade,
            double scale, bool tryflip);
        
        //要使用到的兩個cascade文件,用于聯(lián)合檢測人臉,opencv自帶了多個xml文件,在opencv安裝目錄下的/source/data/haarcascades/ 文件夾內(nèi)
        string cascadeName = "D:\\opencv\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt.xml";
        //D:\opencv\opencv\sources\data\haarcascades
        string nestedCascadeName = "D:\\opencv\\opencv\\sources\\data\\haarcascades\\haarcascade_eye_tree_eyeglasses.xml";//檢測眼睛
        
        int main()
        {
            CvCapture* capture = 0;
            Mat frame, frameCopy, image;
            CascadeClassifier cascade, nestedCascade;//D:\\code\\opencv\\face\\face\\face\\2.jpg
            char *srcImageFile = "D:\\code\\opencv\\face\\face\\face\\2.jpg";//測試圖片
            double scale = 1.3;
            if (!cascade.load(cascadeName))//載入cascade文件
            {
                cerr << "ERROR: Could not load classifier cascade" << endl;
                return -1;
            }
        
            cv::VideoCapture camera(CV_CAP_ANY);
            if (!camera.isOpened())
                return -1;
        
            // 得到幀率  
            double rate = camera.get(CV_CAP_PROP_FPS);
        
            cvNamedWindow("result", 1);
            while (true)
            {
                if (!camera.read(image))
                    break;
                detectAndDraw(image, cascade, nestedCascade, scale, 0);//檢測人臉
                int c = waitKey(20);
                if ((char)c == 27)break;
            }
            //以下部分為實現(xiàn)加載圖片然后檢測
            //image = imread(srcImageFile);
            //cout << "In image read" << endl;
            //if (!image.empty())
            //{
            //  detectAndDraw(image, cascade, nestedCascade, scale, 0);//檢測人臉
            //  waitKey(0);
            //}
            cvDestroyWindow("result");
            camera.release();
            return 0;
        }
        
        void detectAndDraw(Mat& img, CascadeClassifier& cascade,CascadeClassifier& nestedCascade,double scale, bool tryflip)
        {
            int i = 0;
            double t = 0;
            vector<Rect> faces, faces2;
            const static Scalar colors[] = {
                CV_RGB(0, 0, 255),
                CV_RGB(0, 128, 255),
                CV_RGB(0, 255, 255),
                CV_RGB(0, 255, 0),
                CV_RGB(255, 128, 0),
                CV_RGB(255, 255, 0),
                CV_RGB(255, 0, 0),
                CV_RGB(255, 0, 255) };//用于畫線
            Mat gray, smallImg(cvRound(img.rows / scale), cvRound(img.cols / scale), CV_8UC1);
        
            cvtColor(img, gray, COLOR_BGR2GRAY);
            resize(gray, smallImg, smallImg.size(), 0, 0, INTER_LINEAR);
            equalizeHist(smallImg, smallImg);
        
            t = (double)cvGetTickCount();
            cascade.detectMultiScale(smallImg, faces,
                1.1, 2, 0
                //|CASCADE_FIND_BIGGEST_OBJECT
                //|CASCADE_DO_ROUGH_SEARCH
                | CASCADE_SCALE_IMAGE,
                Size(30, 30));
            if (tryflip)
            {
                flip(smallImg, smallImg, 1);
                cascade.detectMultiScale(smallImg, faces2,
                    1.1, 2, 0
                    //|CASCADE_FIND_BIGGEST_OBJECT
                    //|CASCADE_DO_ROUGH_SEARCH
        
                    | CASCADE_SCALE_IMAGE,
                    Size(30, 30));
                for (vector<Rect>::const_iterator r = faces2.begin(); r != faces2.end(); r++)
                {
                    faces.push_back(Rect(smallImg.cols - r->x - r->width, r->y, r->width, r->height));
                }
            }
            t = (double)cvGetTickCount() - t;
            printf("detection time = %g ms\n", t / ((double)cvGetTickFrequency()*1000.));
            for (vector<Rect>::const_iterator r = faces.begin(); r != faces.end(); r++, i++)
            {
                Mat smallImgROI;
                vector<Rect> nestedObjects;
                Point center;
                Scalar color = colors[i % 8];
                int radius;
        
                double aspect_ratio = (double)r->width / r->height;
                if (0.75 < aspect_ratio && aspect_ratio < 1.3)
                {
                    center.x = cvRound((r->x + r->width*0.5)*scale);
                    center.y = cvRound((r->y + r->height*0.5)*scale);
                    radius = cvRound((r->width + r->height)*0.25*scale);
                    circle(img, center, radius, color, 3, 8, 0);
                }
                else
                    rectangle(img, cvPoint(cvRound(r->x*scale), cvRound(r->y*scale)),
                    cvPoint(cvRound((r->x + r->width - 1)*scale), cvRound((r->y + r->height - 1)*scale)),
                    color, 3, 8, 0);
                if (nestedCascade.empty())
                    continue;
                smallImgROI = smallImg(*r);
                nestedCascade.detectMultiScale(smallImgROI, nestedObjects,
                    1.1, 2, 0
                    //|CASCADE_FIND_BIGGEST_OBJECT
                    //|CASCADE_DO_ROUGH_SEARCH
                    //|CASCADE_DO_CANNY_PRUNIN
        
                    | CASCADE_SCALE_IMAGE
                    ,
                    Size(30, 30));
                for (vector<Rect>::const_iterator nr = nestedObjects.begin(); nr != nestedObjects.end(); nr++)
                {
                    center.x = cvRound((r->x + nr->x + nr->width*0.5)*scale);
                    center.y = cvRound((r->y + nr->y + nr->height*0.5)*scale);
                    radius = cvRound((nr->width + nr->height)*0.25*scale);
                    circle(img, center, radius, color, 3, 8, 0);
                }
            }
            cv::imshow("result", img);
        }
    

第二種實現(xiàn)形式

    #include "opencv2/objdetect.hpp"
    #include "opencv2/highgui.hpp"
    #include "opencv2/imgproc.hpp"
    
    #include <iostream>
    #include <stdio.h>
    
    using namespace std;
    using namespace cv;
    
    
    void detectAndDisplay(Mat frame);
    
    String face_cascade_name = "D://opencv//opencv//sources//data//haarcascades//haarcascade_frontalface_alt.xml";
    String eyes_cascade_name = "D://opencv//opencv//sources//data//haarcascades//haarcascade_eye_tree_eyeglasses.xml";
    CascadeClassifier face_cascade;
    CascadeClassifier eyes_cascade;
    String window_name = "Capture - Face detection";
    
    int main(void)
    {
        VideoCapture capture;
        Mat frame;
    
    
        if (!face_cascade.load(face_cascade_name)){ printf("--(!) Error loading face casecade\n"); return -1; }
        if (!eyes_cascade.load(eyes_cascade_name)){ printf("--(!) Error loading eyes cascade\n");  return -1;}
    
    
        //cv::VideoCapture camera(CV_CAP_ANY);
        //if (!camera.isOpened())
        //  return -1;
    
        //open the capture ;and pay attation the CV_CAP_ANY,when you input 0.it' failed ,it appears the device parm is not 0,it convient input CV_CAP_ANY;
        capture.open(CV_CAP_ANY);
        if (!capture.isOpened()){printf("-- Error opening video capture \n");return -1;}
        
        //capture read the frame;
        while (capture.read(frame))
        {
            if (frame.empty()){printf(" -- (!)Error No Capture frame --break"); break;}
            detectAndDisplay(frame);
            int c = waitKey(20);
            if ((char)c == 27){ break; }
    
        }
        return 0;
    }
    
    
    void detectAndDisplay(Mat frame)
    {
        std::vector<Rect> faces;
        Mat frame_gray;
    
        //convert to gray image,and equailzehist 
        cvtColor(frame, frame_gray, COLOR_BGR2GRAY);
        equalizeHist(frame_gray, frame_gray);
    
        //detect face
        face_cascade.detectMultiScale(frame_gray, faces, 1.1, 2, 0 | CASCADE_SCALE_IMAGE, Size(30, 30));
    
    
        for (size_t i = 0; i < faces.size(); i++)
        {
            //gain the face center coordinate 
            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), 2, 8, 0);
    
    
            Mat faceROI = frame_gray(faces[i]);
            std::vector<Rect> eyes;
            eyes_cascade.detectMultiScale(faceROI, eyes, 1.1, 2, 0 | CASCADE_SCALE_IMAGE, Size(30, 30));
    
            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, 8, 0);
            }
        }
        imshow(window_name, frame);
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市信轿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌缝彬,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件哺眯,死亡現(xiàn)場離奇詭異谷浅,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進店門一疯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來撼玄,“玉大人,你說我怎么就攤上這事违施』ゴ浚” “怎么了瑟幕?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵磕蒲,是天一觀的道長。 經(jīng)常有香客問我只盹,道長辣往,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任殖卑,我火速辦了婚禮站削,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘孵稽。我一直安慰自己许起,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布菩鲜。 她就那樣靜靜地躺著园细,像睡著了一般。 火紅的嫁衣襯著肌膚如雪接校。 梳的紋絲不亂的頭發(fā)上猛频,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天,我揣著相機與錄音蛛勉,去河邊找鬼鹿寻。 笑死,一個胖子當(dāng)著我的面吹牛诽凌,可吹牛的內(nèi)容都是我干的毡熏。 我是一名探鬼主播,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼侣诵,長吁一口氣:“原來是場噩夢啊……” “哼痢法!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起窝趣,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤疯暑,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后哑舒,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體妇拯,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了越锈。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片仗嗦。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖甘凭,靈堂內(nèi)的尸體忽然破棺而出稀拐,到底是詐尸還是另有隱情,我是刑警寧澤丹弱,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布德撬,位于F島的核電站,受9級特大地震影響躲胳,放射性物質(zhì)發(fā)生泄漏蜓洪。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一坯苹、第九天 我趴在偏房一處隱蔽的房頂上張望隆檀。 院中可真熱鬧,春花似錦粹湃、人聲如沸恐仑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽裳仆。三九已至,卻和暖如春济赎,著一層夾襖步出監(jiān)牢的瞬間鉴逞,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工司训, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留构捡,地道東北人。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓壳猜,卻偏偏與公主長得像勾徽,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子统扳,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,675評論 2 359

推薦閱讀更多精彩內(nèi)容