实时美颜摄像并生成H264视频流

倾然丶 夕夏残阳落幕 提交于 2020-08-11 16:34:54

为什么美颜摄像这么简单的功能,OpenCV这个开源项目网上很少有代码呢?对于在windows平台下,生成h264视频流也比价麻烦,没有现成的api可以使用,需要借助MinGw编译libx264,或者ffmpeg才能使用。

图玩智能为企业提供提供更优质、更稳定的美颜产品及服务,欢迎随时咨询www.toivan.com.

要推送直播视频流现在先做到下面几个步骤:

 1.OpenCV捕捉摄像头的图像

2.进行识别需要美颜的部分(人脸识别,肤色识别)

 3.进行美颜(提升亮度,直方图均衡,滤波)

 4.生成YUV视频 5.生成h264

主要功能代码:

/** Global variables */

//-- Note, either copy these two files from opencv/data/haarscascades to your current folder, or change these locations

string face_cascade_name = "haarcascade_frontalface_alt.xml";

 

CascadeClassifier face_cascade;

CascadeClassifier eyes_cascade;

string window_name_onlyface = "Capture - only Face";

string window_name_face = "Capture - Face ";

 

 

/**

* @function detectAndDisplay

*/

void detectAndenhance( Mat &frame )

{

        std::vector<Rect> faces;

        Mat frame_gray;

        Mat hatAlpha;

 

        //hatAlpha = imread("2.png",-1);//圣诞帽的图片

 

        cvtColor( frame, frame_gray, COLOR_BGR2GRAY );

        //equalizeHist( frame_gray, frame_gray );

        //-- Detect faces

        face_cascade.detectMultiScale( frame_gray, faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(30, 30) );

 

        for( size_t i = 0; i < faces.size(); i++ )

        {

               Rect face(faces[i].x,faces[i].y,faces[i].x + faces[i].width,faces[i].y + faces[i].height);

               cvSetImageROI(&IplImage(frame),face);

 

              

 

               // Do the porcess

               blur(frame,frame,Size(7,7),Point(-1,-1));

               //////////////////////////////////////////////

               cvResetImageROI( &IplImage(frame) );

               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 );

 

               // line(frame,Point(faces[i].x,faces[i].y),center,Scalar(255,0,0),5);

 

               Mat faceROI = frame_gray( faces[i] );

               std::vector<Rect> eyes;

 

               imshow( window_name_onlyface, faceROI );

              

        }

        //-- Show what you got

        imshow( window_name_face, frame );

        //imwrite("merry christmas.jpg",frame);

}

 

/** @函数 detectAndDisplay */

void detectAndDisplay( Mat frame )

{

        std::vector<Rect> faces;

        Mat frame_gray;

 

        cvtColor( frame, frame_gray, CV_BGR2GRAY );

        equalizeHist( frame_gray, frame_gray );

 

        //-- 多尺寸检测人脸

        face_cascade.detectMultiScale( frame_gray, faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(30, 30) );

 

        for( int i = 0; i < faces.size(); i++ )

        {

               Point center( faces[i].x + faces[i].width*0.5, faces[i].y + faces[i].height*0.5 );

               ellipse( frame, center, Size( faces[i].width*0.5, faces[i].height*0.5), 0, 0, 360, Scalar( 255, 0, 255 ), 4, 8, 0 );

 

               Mat faceROI = frame_gray( faces[i] );

               std::vector<Rect> eyes;

 

               //-- 在每张人脸上检测双眼

               eyes_cascade.detectMultiScale( faceROI, eyes, 1.1, 2, 0 |CV_HAAR_SCALE_IMAGE, Size(30, 30) );

 

               for( int j = 0; j < eyes.size(); j++ )

               {

                       Point center( faces[i].x + eyes[j].x + eyes[j].width*0.5, faces[i].y + eyes[j].y + eyes[j].height*0.5 );

                       int radius = cvRound( (eyes[j].width + eyes[i].height)*0.25 );

                       circle( frame, center, radius, Scalar( 255, 0, 0 ), 4, 8, 0 );

               }

        }

        //-- 显示结果图像

        imshow( window_name_face, frame );

}

 

 

 

// add by shiter 2016/3/3

 

Mat equalizeChannelHist(const Mat & inputImage) 

        if( inputImage.channels() >= 3

        { 

               vector<Mat> channels; 

               split(inputImage, channels); 

 

               Mat B,G,R; 

 

               equalizeHist( channels[0], B ); 

               equalizeHist( channels[1], G ); 

               equalizeHist( channels[2], R ); 

 

               vector<Mat> combined; 

               combined.push_back(B); 

               combined.push_back(G); 

               combined.push_back(R); 

 

               Mat result; 

               merge(combined, result); 

 

               return result; 

        }

        else{return inputImage;}

 

        return inputImage; 

 

 

Mat equalizeIntensityHist(const Mat & inputImage) 

        if(inputImage.channels() >= 3

        { 

               Mat ycrcb; 

 

               cvtColor(inputImage, ycrcb, COLOR_BGR2YCrCb); 

 

               vector<Mat> channels; 

               split(ycrcb, channels); 

 

               equalizeHist(channels[0], channels[0]); 

 

               Mat result; 

               merge(channels,ycrcb); 

 

               cvtColor(ycrcb, result, COLOR_YCrCb2BGR); 

 

               return result; 

        } 

 

        return Mat(); 

 

 

 

//皮肤检测,并针对皮肤进行增强,模糊

void MySkinEnhance(Mat &frame)

{

        Mat input_image =frame; 

        Mat output_mask; 

        Mat output_image; 

        Mat mask; 

        //肤色椭圆 

        /*椭圆皮肤模型*/ 

        Mat skinCrCbHist = Mat::zeros(Size(256, 256), CV_8UC1); 

        ellipse(skinCrCbHist, Point(113, 155.6), Size(23.4, 15.2), 43.0, 0.0, 360.0, Scalar(255, 255, 255), -1); 

 

        Mat element = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1) ); 

 

        if(input_image.empty()) 

               return

 

        Mat ycrcb_image; 

        output_mask = Mat::zeros(input_image.size(), CV_8UC1); 

        cvtColor(input_image, ycrcb_image, CV_BGR2YCrCb); //首先转换成到YCrCb空间 

 

        for(int i = 0; i < input_image.rows; i++) //利用椭圆皮肤模型进行皮肤检测 

        { 

               uchar* p = (uchar*)output_mask.ptr<uchar>(i); 

               Vec3b* ycrcb = (Vec3b*)ycrcb_image.ptr<Vec3b>(i); 

               for(int j = 0; j < input_image.cols; j++

               { 

                       if(skinCrCbHist.at<uchar>(ycrcb[j][1], ycrcb[j][2]) > 0

                               p[j] = 255

               } 

        }    

 

        //morphologyEx(output_mask,output_mask,MORPH_CLOSE,element); 

 

         //output_mask.setTo(0); 

              

               dilate(output_mask,output_mask,Mat(32,32,CV_8U),Point(-1,-1),2);

               //imwrite("dilate.jpg",dst);

        // output_image.setTo(0); 

               input_image.copyTo(output_image, output_mask); 

              

               Mat enhance = output_image;

               medianBlur(output_image,enhance,11);

               //blur(enhance,enhance,Size(4,4),Point(-1,-1),4);

               imshow("blur face",enhance);

               for(int i = 0; i < output_image.rows; i++) //

               { 

                       uchar* p = (uchar*)output_mask.ptr<uchar>(i); 

 

                       for(int j = 0; j < output_image.cols; j++

                       { 

                               if((enhance.at<Vec3b>(i,j)[0] < 50) && (enhance.at<Vec3b>(i,j)[1] < 50)&& (enhance.at<Vec3b>(i,j)[2] < 50) )

                               {

                                      //不是纯黑的

                                     

                                     

                               }

                               else

                               {

 

                                      frame.at<Vec3b>(i,j)[0] =  enhance.at<Vec3b>(i,j)[0];

 

                                      frame.at<Vec3b>(i,j)[1] = enhance.at<Vec3b>(i,j)[1];

                                      frame.at<Vec3b>(i,j)[2] = enhance.at<Vec3b>(i,j)[2];

                               }

                       } 

               }    

               // 图像融合

               //addWeighted(input_image, 0.95, enhance, 0.05, 0.0, input_image); 

               imshow("ouput image",frame);

 

}

 

 

//提高亮度对比度

void highlight(Mat &frame)

{

        Mat src,dst; 

        double alpha =1.5

        double beta = 20

 

        src = frame;

        if(!src.data) 

        { 

               cout<<"Failed to load image!"<<endl; 

               return

        } 

 

 

 

        //dst = Mat::zeros(src.size(),src.type()); 

        for (int i = 0;i<src.rows;++i)

        {

               //uchar* inData=src.ptr<uchar>(i);

              

               for(int j= 0;j<src.cols;++j)

               {

                        

                               /*src.at<Vec3b>(i,j)[0] = saturate_cast<uchar>(src.at<Vec3b>(i,j)[0]*alpha+beta);

                               src.at<Vec3b>(i,j)[1] = saturate_cast<uchar>(src.at<Vec3b>(i,j)[1]*alpha+beta);

                               src.at<Vec3b>(i,j)[2] = saturate_cast<uchar>(src.at<Vec3b>(i,j)[2]*alpha+beta); */

                               //上面的效率低,下面的有越界

                               src.at<Vec3b>(i,j)[0] = (src.at<Vec3b>(i,j)[0]*alpha+beta);

                               src.at<Vec3b>(i,j)[1] = (src.at<Vec3b>(i,j)[1]*alpha+beta);

                               src.at<Vec3b>(i,j)[2] = (src.at<Vec3b>(i,j)[2]*alpha+beta);

                      

               }

        }

 

        namedWindow("Handled Image"); 

        imshow("Handled Image",src); 

        //waitKey(); 

}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!