arm-VS2017 opencv远程人脸识别--APPLE的学习笔记

一,人脸识别问题记录:

  1. face_cascade.detectMultiScale报错empty。原来是忘记load xml对比数据集了。

二,将来优化的空间

arm开发板BB-Black的优化

1. 视频采集延迟,不顺畅。
    需要修改方案。目前是采集yuyv后压缩成jpeg然后传给客户端。客户端decode解析后再识别人脸,然后显示到窗口。
2. 开发板只能采集320*240的分辨率。
    需要修改驱动的buffer。
3. 将来功能要做成能识别出摄像头中是否有人。有人则抓拍,当做白天的小偷监控。
    目前只是识别出人脸。而且侧面是识别不了的。只能正面识别。

win+linxu PC将来优化空间

1. client端640*480也还有buffer 65535限制的问题,需要优化。---这部分可以和linuxPC先优化。

注:准备10月份之后再继续玩视频采集

三,有图有真相

人脸监控.png

代码中imwrite的抓拍效果


pic2.jpg

运行中的BB-Black开发板


BB-Black开发板连接摄像头.png

四,arm server代码

#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include <opencv2/core.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>
#include <vector>
using namespace std; 

#define MAXLINE 4096
using namespace cv;

string int2string(int value)
{
    stringstream ss;
    ss<<value;
    return ss.str();
}

int main(int argc, char** argv)
{
    int    listenfd, connfd;
    struct sockaddr_in     servaddr;

    if( (listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1 )
    {
        printf("create socket error: %s(errno: %d)\n",strerror(errno),errno);
        exit(0);
    }

    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(8080);

    int opt = 1;
    if(setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,(const void *)&opt,sizeof(opt)))
    {
    perror("setsockopt");
    return -1;
    }

    if( bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1){
    printf("bind socket error: %s(errno: %d)\n",strerror(errno),errno);
    exit(0);
    }

    if( listen(listenfd, 10) == -1){
    printf("listen socket error: %s(errno: %d)\n",strerror(errno),errno);
    exit(0);
    }
        /* ---main task process--- */
    Mat frame;
    //--- INITIALIZE VIDEOCAPTURE
    VideoCapture cap;
    vector<unsigned char> inImage;  
    // open the default camera using default API
    cap.open(0);
    cap.set(CV_CAP_PROP_FRAME_HEIGHT,240);
    cap.set(CV_CAP_PROP_FRAME_WIDTH,320);   
    if (!cap.isOpened()) 
    {
        cerr << "ERROR! Unable to open camera\n";
        return -1;
    }
        printf("open camera success\n");
        cap.read(frame);
        printf("======waiting for client's apple request======\n");
    if( (connfd = accept(listenfd, (struct sockaddr*)NULL, NULL)) == -1){
            printf("accept socket error: %s(errno: %d)",strerror(errno),errno);
            exit(0);
    }

    
    
    char cok[1]={0x55};
    char cokstart[1]={0};
    int sizelen=0;
    int sizejpg=0;
    for (;;)
    {
        // wait for a new frame from camera and store it into 'frame'
        cap.read(frame);
        // check if we succeeded
        if (frame.empty()) {
            cerr << "ERROR! blank frame grabbed\n";
            break;
        }

        if (cok[0]==0x55){
            cok[0]=0;
            //printf("read one frame!\n");
            imencode(".jpg",frame,inImage);  
            int datalen=inImage.size();

            unsigned char *msgImage=new unsigned char[datalen]; 

            unsigned char msgLen[4];
            msgLen[0]=datalen >> 24;
            msgLen[1]=datalen >> 16;
            msgLen[2]=datalen >> 8;
            msgLen[3]=datalen;
            //printf("datalen=%x\n",datalen);
            sizelen=send(connfd,msgLen,4,0);
                //printf("sizelen:%x",sizelen);
            for(int i=0;i<datalen;i++)  
            {  
                    msgImage[i]=inImage[i];  
                    //cout<<msgImage[i]<<endl;  
            } 
            recv(connfd,cokstart,1,0);
            if(cokstart[0] == 0x33)
            {
                cokstart[0]=0x0;
                //vector<char>vec;
                //Mat img_decode;
                //string filename="";
                //cokstart[0]=0x0;
                //for(int i=0;i<datalen;i++)
                //{
                //  vec.push_back(msgImage[i]);
                //}
                //img_decode =imdecode(vec,CV_LOAD_IMAGE_COLOR);
                //j++;
            
                //imshow("serpic",img_decode);
                //usleep(1000);
                //filename="sevpic"+int2string(j)+".jpg";
                //imwrite(filename,img_decode);

                sizejpg=send(connfd,msgImage,datalen,0);
                //printf("sizejpg:%x",sizejpg);
                usleep(10000);


                recv(connfd,cok,1,0);
            }
        
        }
    }   
    


    close(listenfd);
    return 0;
}

五,VS2017 client代码

// client.cpp: 定义控制台应用程序的入口点。
//

#include <stdio.h>
#include <winsock2.h>
#include <cv.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/objdetect.hpp>
#include <WINSOCK2.H> 
#include <Ws2tcpip.h>
#pragma comment(lib,"ws2_32.lib")

void detectAndDisplay(cv::Mat frame);

cv::CascadeClassifier face_cascade;
cv::CascadeClassifier eyes_cascade;

/* tansfer int to string */
std::string int2string(int value)
{
    std::stringstream ss;
    ss << value;
    return ss.str();
}

int main(int argc, char** argv)
{
    SOCKADDR_IN servaddr;
    WORD wVersionRequested;
    WSADATA wsaData;
    int err;
    /** Global variables */
    std::string face_cascade_name = "haarcascade_frontalface_alt2.xml";
    //导入级联分类器xml文件,并作文件是否存在的判断
    if (!face_cascade.load(face_cascade_name))
    {
        printf("--(!)Error loading face data\n");
        return -1;
    }
    /** Global variables */
    std::string eyes_cascade_name = "haarcascade_eye_tree_eyeglasses.xml";
    //导入级联分类器xml文件,并作文件是否存在的判断
    if (!eyes_cascade.load(eyes_cascade_name))
    {
        printf("--(!)Error loading eyes data\n");
        return -1;
    }   
    
    wVersionRequested = MAKEWORD(1, 1);
    err = WSAStartup(wVersionRequested, &wsaData);
    if (err != 0) {
        return 0;
    }

    if (LOBYTE(wsaData.wVersion) != 1 ||
        HIBYTE(wsaData.wVersion) != 1) {
        WSACleanup();
        return 0;
    }

    SOCKET sockfd = socket(AF_INET, SOCK_STREAM, 0);

    memset(&servaddr, 0, sizeof(servaddr));
    //servaddr.sin_addr.S_un.S_addr = inet_pton(AF_INET,"192.168.7.4",&servaddr.sin_addr);//服务器端的地址  
    //servaddr.sin_addr.S_un.S_addr = inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);//服务器端的地址 
    servaddr.sin_addr.S_un.S_addr = inet_addr("192.168.7.2");
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(8080);
    connect(sockfd, (SOCKADDR*)&servaddr, sizeof(SOCKADDR));


    #define BUF_SIZE 65535
    char buffer[BUF_SIZE];
    std::vector<char> vec;
    cv::Mat img_decode;
    //std::string filename = "";
    int size = 0;
    int mylen = 0;
    int j = 0;
    int getpic = 0;
    char cokstart[1] = { 0x33 };
    memset(buffer, 0, 4);
    while (1)
    {
        size = recv(sockfd, buffer, 4, 0);

        mylen = ((buffer[2] << 8)&(0xFF00)) | ((buffer[3])&(0xFF));
        if (mylen>1)
        {
            getpic = 1; //设置标志位,如第一次server没有连接上后续则不执行
        }
        if (mylen>0) {
            /*received length then send ack signal cokstart.*/
            send(sockfd, cokstart, 1, 0);
        }
        /* receive one frame of jpg data */
        while (mylen>0)
        {
            size = recv(sockfd, buffer, mylen, 0);
            printf("size is %d\n",size);
            //printf("mylen is %x\n",mylen);
            /* put char values to vector */
            for (int i = 0; i < mylen; i++)
            {
                vec.push_back(buffer[i]);
            }
            if (mylen > size)
            {
                mylen = mylen - size;
            }
            else
            {
                mylen = 0;
            }
            
        }
        if (getpic==1)
        {
            /* decode jpg data */
            img_decode = cv::imdecode(vec, CV_LOAD_IMAGE_COLOR);
            /* release vector then ready to receive next frame */
            vec.clear();
            //cout << "vector capacity:"<<vec.capacity()<<endl;
            std::vector<char>(vec).swap(vec);
            //cout << "vector capacity afterswap:"<<vec.capacity()<<endl;

            //-- 3. Apply the classifier to the frame
            detectAndDisplay(img_decode);
            
            /* display the jpg in windows */
            //cv::namedWindow("detect_pic", cv::WINDOW_AUTOSIZE);
            //if (!img_decode.empty()) {
            //  imshow("detect_pic", img_decode);
            //}

            /* reflash display window in every 33ms */
            cvWaitKey(33);

            /* save to file -- this function is optional */
            //j++;
            //filename = "pic" + int2string(j) + ".jpg";
            //imwrite(filename, img_decode);

            /* send ack signal cok to tell that I'm ready to handler next frame */
            char cok[1] = { 0x55 };
            send(sockfd, cok, 1, 0);
        }
    }
}

void detectAndDisplay(cv::Mat frame)
{
    std::vector<cv::Rect> faces;
    cv::Mat frame_gray;
    std::string filename = "";
    int k=0;
    cvtColor(frame, frame_gray, cv::COLOR_BGR2GRAY);
    equalizeHist(frame_gray, frame_gray);

    //-- Detect faces
    face_cascade.detectMultiScale(frame_gray, faces, 1.1, 2, 0 | cv::CASCADE_SCALE_IMAGE, cv::Size(20, 20));
    printf("the size of face %d",faces.size());
    for (size_t i = 0; i < faces.size(); i++)
    {
        cv::Point center(faces[i].x + faces[i].width / 2, faces[i].y + faces[i].height / 2);
        ellipse(frame, center, cv::Size(faces[i].width / 2, faces[i].height / 2), 0, 0, 360, cv::Scalar(255, 0, 255), 4, 8, 0);

        cv::Mat faceROI = frame_gray(faces[i]);
        std::vector<cv::Rect> eyes;

        //-- In each face, detect eyes
        eyes_cascade.detectMultiScale(faceROI, eyes, 1.1, 2, 0 | cv::CASCADE_SCALE_IMAGE, cv::Size(30, 30));


        for (size_t j = 0; j < eyes.size(); j++)
        {
            cv::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, cv::Scalar(255, 0, 0), 4, 8, 0);
            k++;
            filename = "pic" + int2string(k) + ".jpg";
            cv::imwrite(filename, frame);
        }
    }
    /* save to file -- this function is optional */

    //-- Show what you got
    cv::namedWindow("detect_pic", cv::WINDOW_AUTOSIZE);
    if (!frame.empty()) {
        imshow("detect_pic", frame);
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容