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

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

最近有个小需求,要推送直播视频流,我在网上查了一下有live555或者用librtmp来推送,但是前者还需要修改源代码,也挺麻烦的,现在先做到了下面几个步骤:

1.OpenCV捕捉摄像头的图像

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

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

4.生成YUV视频

5.生成h264


现在用librtmp时候,出现了

ERROR:RTMP_Connect0,failed to connect socket,10061(unknow error)

不知道是咋回事了,怀疑是1935端口被禁,但是一时半会儿不知道咋弄。


主要功能代码:


[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. /** Global variables */  
  2. //-- Note, either copy these two files from opencv/data/haarscascades to your current folder, or change these locations  
  3. string face_cascade_name = "haarcascade_frontalface_alt.xml";  
  4.   
  5. CascadeClassifier face_cascade;  
  6. CascadeClassifier eyes_cascade;  
  7. string window_name_onlyface = "Capture - only Face";  
  8. string window_name_face = "Capture - Face ";  
  9.   
  10.   
  11. /** 
  12. * @function detectAndDisplay 
  13. */  
  14. void detectAndenhance( Mat &frame )  
  15. {  
  16.     std::vector<Rect> faces;  
  17.     Mat frame_gray;  
  18.     Mat hatAlpha;  
  19.   
  20.     //hatAlpha = imread("2.png",-1);//圣诞帽的图片  
  21.   
  22.     cvtColor( frame, frame_gray, COLOR_BGR2GRAY );  
  23.     //equalizeHist( frame_gray, frame_gray );  
  24.     //-- Detect faces  
  25.     face_cascade.detectMultiScale( frame_gray, faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(30, 30) );  
  26.   
  27.     forsize_t i = 0; i < faces.size(); i++ )  
  28.     {  
  29.         Rect face(faces[i].x,faces[i].y,faces[i].x + faces[i].width,faces[i].y + faces[i].height);  
  30.         cvSetImageROI(&IplImage(frame),face);  
  31.   
  32.           
  33.   
  34.         // Do the porcess  
  35.         blur(frame,frame,Size(7,7),Point(-1,-1));  
  36.         //  
  37.         cvResetImageROI( &IplImage(frame) );  
  38.         Point center( faces[i].x + faces[i].width/2, faces[i].y + faces[i].height/2 );  
  39.         ellipse( frame, center, Size( faces[i].width/2, faces[i].height/2), 0, 0, 360, Scalar( 255, 0, 255 ), 2, 8, 0 );  
  40.   
  41.         // line(frame,Point(faces[i].x,faces[i].y),center,Scalar(255,0,0),5);  
  42.   
  43.         Mat faceROI = frame_gray( faces[i] );  
  44.         std::vector<Rect> eyes;  
  45.   
  46.         imshow( window_name_onlyface, faceROI );  
  47.           
  48.     }  
  49.     //-- Show what you got  
  50.     imshow( window_name_face, frame );  
  51.     //imwrite("merry christmas.jpg",frame);  
  52. }  
  53.   
  54. /** @函数 detectAndDisplay */  
  55. void detectAndDisplay( Mat frame )  
  56. {  
  57.     std::vector<Rect> faces;  
  58.     Mat frame_gray;  
  59.   
  60.     cvtColor( frame, frame_gray, CV_BGR2GRAY );  
  61.     equalizeHist( frame_gray, frame_gray );  
  62.   
  63.     //-- 多尺寸检测人脸  
  64.     face_cascade.detectMultiScale( frame_gray, faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(30, 30) );  
  65.   
  66.     forint i = 0; i < faces.size(); i++ )  
  67.     {  
  68.         Point center( faces[i].x + faces[i].width*0.5, faces[i].y + faces[i].height*0.5 );  
  69.         ellipse( frame, center, Size( faces[i].width*0.5, faces[i].height*0.5), 0, 0, 360, Scalar( 255, 0, 255 ), 4, 8, 0 );  
  70.   
  71.         Mat faceROI = frame_gray( faces[i] );  
  72.         std::vector<Rect> eyes;  
  73.   
  74.         //-- 在每张人脸上检测双眼  
  75.         eyes_cascade.detectMultiScale( faceROI, eyes, 1.1, 2, 0 |CV_HAAR_SCALE_IMAGE, Size(30, 30) );  
  76.   
  77.         forint j = 0; j < eyes.size(); j++ )  
  78.         {  
  79.             Point center( faces[i].x + eyes[j].x + eyes[j].width*0.5, faces[i].y + eyes[j].y + eyes[j].height*0.5 );  
  80.             int radius = cvRound( (eyes[j].width + eyes[i].height)*0.25 );  
  81.             circle( frame, center, radius, Scalar( 255, 0, 0 ), 4, 8, 0 );  
  82.         }  
  83.     }  
  84.     //-- 显示结果图像  
  85.     imshow( window_name_face, frame );  
  86. }  
  87.   
  88.   
  89.   
  90. // add by shiter 2016/3/3  
  91.   
  92. Mat equalizeChannelHist(const Mat & inputImage)    
  93. {    
  94.     if( inputImage.channels() >= 3 )    
  95.     {    
  96.         vector<Mat> channels;    
  97.         split(inputImage, channels);    
  98.   
  99.         Mat B,G,R;    
  100.   
  101.         equalizeHist( channels[0], B );    
  102.         equalizeHist( channels[1], G );    
  103.         equalizeHist( channels[2], R );    
  104.   
  105.         vector<Mat> combined;    
  106.         combined.push_back(B);    
  107.         combined.push_back(G);    
  108.         combined.push_back(R);    
  109.   
  110.         Mat result;    
  111.         merge(combined, result);    
  112.   
  113.         return result;    
  114.     }  
  115.     else{return inputImage;}  
  116.   
  117.     return inputImage;    
  118. }    
  119.   
  120.   
  121. Mat equalizeIntensityHist(const Mat & inputImage)    
  122. {    
  123.     if(inputImage.channels() >= 3)    
  124.     {    
  125.         Mat ycrcb;    
  126.   
  127.         cvtColor(inputImage, ycrcb, COLOR_BGR2YCrCb);    
  128.   
  129.         vector<Mat> channels;    
  130.         split(ycrcb, channels);    
  131.   
  132.         equalizeHist(channels[0], channels[0]);    
  133.   
  134.         Mat result;    
  135.         merge(channels,ycrcb);    
  136.   
  137.         cvtColor(ycrcb, result, COLOR_YCrCb2BGR);    
  138.   
  139.         return result;    
  140.     }    
  141.   
  142.     return Mat();    
  143. }    
  144.   
  145.   
  146.   
  147. //皮肤检测,并针对皮肤进行增强,模糊  
  148. void MySkinEnhance(Mat &frame)  
  149. {  
  150.     Mat input_image =frame;    
  151.     Mat output_mask;    
  152.     Mat output_image;    
  153.     Mat mask;    
  154.     //肤色椭圆    
  155.     /*椭圆皮肤模型*/    
  156.     Mat skinCrCbHist = Mat::zeros(Size(256, 256), CV_8UC1);    
  157.     ellipse(skinCrCbHist, Point(113, 155.6), Size(23.4, 15.2), 43.0, 0.0, 360.0, Scalar(255, 255, 255), -1);    
  158.   
  159.     Mat element = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1) );    
  160.   
  161.     if(input_image.empty())    
  162.         return ;    
  163.   
  164.     Mat ycrcb_image;    
  165.     output_mask = Mat::zeros(input_image.size(), CV_8UC1);    
  166.     cvtColor(input_image, ycrcb_image, CV_BGR2YCrCb); //首先转换成到YCrCb空间    
  167.   
  168.     for(int i = 0; i < input_image.rows; i++) //利用椭圆皮肤模型进行皮肤检测    
  169.     {    
  170.         uchar* p = (uchar*)output_mask.ptr<uchar>(i);    
  171.         Vec3b* ycrcb = (Vec3b*)ycrcb_image.ptr<Vec3b>(i);    
  172.         for(int j = 0; j < input_image.cols; j++)    
  173.         {    
  174.             if(skinCrCbHist.at<uchar>(ycrcb[j][1], ycrcb[j][2]) > 0)    
  175.                 p[j] = 255;    
  176.         }    
  177.     }       
  178.   
  179.     //morphologyEx(output_mask,output_mask,MORPH_CLOSE,element);    
  180.   
  181.      //output_mask.setTo(0);    
  182.           
  183.         dilate(output_mask,output_mask,Mat(32,32,CV_8U),Point(-1,-1),2);  
  184.         //imwrite("dilate.jpg",dst);  
  185.     // output_image.setTo(0);    
  186.         input_image.copyTo(output_image, output_mask);    
  187.           
  188.         Mat enhance = output_image;  
  189.         medianBlur(output_image,enhance,11);  
  190.         //blur(enhance,enhance,Size(4,4),Point(-1,-1),4);  
  191.         imshow("blur face",enhance);  
  192.         for(int i = 0; i < output_image.rows; i++) //  
  193.         {    
  194.             uchar* p = (uchar*)output_mask.ptr<uchar>(i);    
  195.   
  196.             for(int j = 0; j < output_image.cols; j++)    
  197.             {    
  198.                 if((enhance.at<Vec3b>(i,j)[0] < 50) && (enhance.at<Vec3b>(i,j)[1] < 50)&& (enhance.at<Vec3b>(i,j)[2] < 50) )   
  199.                 {  
  200.                     //不是纯黑的  
  201.                       
  202.                       
  203.                 }  
  204.                 else  
  205.                 {  
  206.   
  207.                     frame.at<Vec3b>(i,j)[0] =  enhance.at<Vec3b>(i,j)[0];  
  208.   
  209.                     frame.at<Vec3b>(i,j)[1] = enhance.at<Vec3b>(i,j)[1];  
  210.                     frame.at<Vec3b>(i,j)[2] = enhance.at<Vec3b>(i,j)[2];  
  211.                 }  
  212.             }    
  213.         }       
  214.         // 图像融合  
  215.         //addWeighted(input_image, 0.95, enhance, 0.05, 0.0, input_image);    
  216.         imshow("ouput image",frame);  
  217.   
  218. }  
  219.   
  220.   
  221. //提高亮度对比度  
  222. void highlight(Mat &frame)  
  223. {  
  224.     Mat src,dst;    
  225.     double alpha =1.5;    
  226.     double beta = 20;    
  227.   
  228.     src = frame;   
  229.     if(!src.data)    
  230.     {    
  231.         cout<<"Failed to load image!"<<endl;    
  232.         return ;    
  233.     }    
  234.   
  235.   
  236.   
  237.     //dst = Mat::zeros(src.size(),src.type());    
  238.     for (int i = 0;i<src.rows;++i)   
  239.     {  
  240.         //uchar* inData=src.ptr<uchar>(i);  
  241.           
  242.         for(int j= 0;j<src.cols;++j)   
  243.         {  
  244.                
  245.                 /*src.at<Vec3b>(i,j)[0] = saturate_cast<uchar>(src.at<Vec3b>(i,j)[0]*alpha+beta);  
  246.                 src.at<Vec3b>(i,j)[1] = saturate_cast<uchar>(src.at<Vec3b>(i,j)[1]*alpha+beta);  
  247.                 src.at<Vec3b>(i,j)[2] = saturate_cast<uchar>(src.at<Vec3b>(i,j)[2]*alpha+beta); */  
  248.                 //上面的效率低,下面的有越界  
  249.                 src.at<Vec3b>(i,j)[0] = (src.at<Vec3b>(i,j)[0]*alpha+beta);   
  250.                 src.at<Vec3b>(i,j)[1] = (src.at<Vec3b>(i,j)[1]*alpha+beta);   
  251.                 src.at<Vec3b>(i,j)[2] = (src.at<Vec3b>(i,j)[2]*alpha+beta);  
  252.               
  253.         }  
  254.     }  
  255.   
  256.     namedWindow("Handled Image");    
  257.     imshow("Handled Image",src);    
  258.     //waitKey();    
  259. }  




实现效果:实时实现的话我只加了肤色检测和简单的滤波,具体美化还需要进一步调试

参数和算法 的组合可以在代码中调整参数实现,可以把膨胀的参数调大一点这个整个人脸就差不多可以经过肤色检测全部搞出来。

完整工程代码:http://download.csdn.net/detail/wangyaninglm/9453146



参考文献:


肤色检测:http://blog.csdn.NET/yangtrees/article/details/8269984

人像优化:http://blog.csdn.net/u011630458/article/details/46275469

肤色检测:http://blog.csdn.net/wj080211140/article/details/23384927

改变对比读:http://blog.csdn.net/ubunfans/article/details/24373811


直接推送直播流:http://blog.csdn.net/wangyaninglm/article/details/51056101


  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值