zoukankan      html  css  js  c++  java
  • 【OpenCV】图像代数运算:平均值去噪,减去背景

    代数运算,就是对两幅图像的点之间进行加、减、乘、除的运算。四种运算相应的公式为:


    代数运算中比较常用的是图像相加和相减。图像相加常用来求平均值去除addtive噪声或者实现二次曝光(double-exposure)。图像相减用于减去背景或周期噪声,污染等。

    图像相加


    OpenCV中提供了相加的函数
    [cpp] view plain copy
    1. void cvAcc(   
    2.            const CvArr* image,//输入图像  
    3.            CvArr* sum,  //累积图像   
    4.            const CvArr* mask=NULL//可选的运算  
    5.  );  
    我们还需要用到一个线性变换转换函数来对相加的结果求平均
    [cpp] view plain copy
    1. void cvConvertScale(   
    2.         const CvArr* src, //输入数组  
    3.         CvArr* dst,//输出数组  
    4.         double scale=1,//比例  
    5.         double shift=0 //缩放比例,可选  
    6. );  
    7. #define cvCvtScale cvConvertScale  
    8. #define cvScale  cvConvertScale  
    9. #define cvConvert( src, dst )  cvConvertScale( (src), (dst), 1, 0 )  


    实践:平均值去噪

    我们用NASA的一段幸运团的视频做实验,截取视频的某几个连续帧求平均值:
    [cpp] view plain copy
    1. int main()  
    2. {  
    3.     CvCapture* capture=cvCaptureFromFile("media.avi");  
    4.     IplImage* frame=  NULL;  
    5.     IplImage * imgsum =NULL;  
    6.       
    7.     int start=301;  
    8.     int end=304;  
    9.     cvSetCaptureProperty(capture, CV_CAP_PROP_POS_FRAMES, start);  
    10.       
    11.     int count = start;  
    12.     while( cvGrabFrame(capture) && count <= end )  
    13.     {  
    14.         frame = cvRetrieveFrame(capture);// 获取当前帧  
    15.         if(imgsum==NULL){  
    16.             imgsum=cvCreateImage(cvGetSize(frame),IPL_DEPTH_32F,3);  
    17.             cvZero(imgsum);  
    18.         }  
    19.         cvAcc(frame,imgsum);  
    20.   
    21.         char testname[100];  
    22.         sprintf(testname,"%s%d%s","image",count,".jpg");  
    23.         cvShowImage(testname,frame);  
    24.         cvSaveImage(testname,frame);  
    25.           
    26.         count++;  
    27.     }  
    28.     IplImage * imgavg = cvCreateImage(cvGetSize(frame),IPL_DEPTH_8U,3);  
    29.     cvConvertScale(imgsum,imgavg,1.0/4.0);  
    30.       
    31.     cvShowImage("imageavg",imgavg);  
    32.     cvSaveImage("imageavg_4.jpg",imgavg);  
    33.       
    34.     cvWaitKey(0);  
    35.     cvReleaseCapture(&capture);  
    36.     return 0;  
    37. }  
    以下从左到右分别是连续两帧、四帧、八帧、十六帧求均值的结果:
       

       


    实践:图像二次曝光

    曝光和去噪是一样的,也是对几幅图像求平均
    [cpp] view plain copy
    1. //通过求平均二次曝光  
    2. int main()  
    3. {  
    4.     IplImage* image1=  cvLoadImage("psu3.jpg");  
    5.     IplImage* image2=  cvLoadImage("psu4.jpg");  
    6.       
    7.     IplImage * imgsum =cvCreateImage(cvGetSize(image1),IPL_DEPTH_32F,3);  
    8.     cvZero(imgsum);  
    9.     cvAcc(image1,imgsum);  
    10.     cvAcc(image2,imgsum);  
    11.   
    12.     IplImage * imgavg = cvCreateImage(cvGetSize(image1),IPL_DEPTH_8U,3);  
    13.     cvConvertScale(imgsum,imgavg,1.0/2.0);  
    14.   
    15.     cvShowImage("imageavg",imgavg);  
    16.     cvSaveImage("avg.jpg",imgavg);  
    17.   
    18.     cvWaitKey(0);  
    19.     cvReleaseImage(&image1);  
    20.     cvReleaseImage(&image2);  
    21.     cvReleaseImage(&imgsum);  
    22.     cvReleaseImage(&imgavg);  
    23.     return 0;  
    24. }  
    下图是对同学街舞截图的“二次曝光”效果:


    图像相减


    OpenCV中用cvAbsDiff函数计算两数组的差的绝对值
    [cpp] view plain copy
    1. void cvAbsDiff(   
    2.         const CvArr* src1,//第一个输入数组  
    3.         const CvArr* src2,//第二个输入数组  
    4.         CvArr* dst//输出数组  
    5. );  


    实践:减去背景

    减去背景是通过两幅图像代数相减,可以判断出前景区域和运动区域,这是最简单(很多时候也是效果很好的)运动检测方法。
    [cpp] view plain copy
    1. //减去背景  
    2. int main()  
    3. {  
    4.     IplImage* pFrame = NULL;   
    5.     IplImage* pFrImg = NULL;  
    6.     IplImage* pBkImg = NULL;  
    7.   
    8.     CvMat* pFrameMat = NULL;  
    9.     CvMat* pFrMat = NULL;  
    10.     CvMat* pBkMat = NULL;  
    11.   
    12.     CvCapture* pCapture = NULL;  
    13.   
    14.     int nFrmNum = 0;  
    15.   
    16.     //创建窗口  
    17.     cvNamedWindow("video", 1);  
    18.     cvNamedWindow("background",1);  
    19.     cvNamedWindow("foreground",1);  
    20.   
    21.     pCapture = cvCaptureFromFile("media.avi");  
    22.     while(pFrame = cvQueryFrame( pCapture ))  
    23.     {  
    24.         nFrmNum++;  
    25.   
    26.         //如果是第一帧,需要申请内存,并初始化  
    27.         if(nFrmNum == 1)  
    28.         {  
    29.             pBkImg = cvCreateImage(cvSize(pFrame->width, pFrame->height),  IPL_DEPTH_8U,1);  
    30.             pFrImg = cvCreateImage(cvSize(pFrame->width, pFrame->height),  IPL_DEPTH_8U,1);  
    31.   
    32.             pBkMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);  
    33.             pFrMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);  
    34.             pFrameMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);  
    35.   
    36.             //转化成单通道图像再处理  
    37.             cvCvtColor(pFrame, pBkImg, CV_BGR2GRAY);  
    38.             cvCvtColor(pFrame, pFrImg, CV_BGR2GRAY);  
    39.   
    40.             cvConvert(pFrImg, pFrameMat);  
    41.             cvConvert(pFrImg, pFrMat);  
    42.             cvConvert(pFrImg, pBkMat);  
    43.         }  
    44.         else  
    45.         {  
    46.             cvCvtColor(pFrame, pFrImg, CV_BGR2GRAY);  
    47.             cvConvert(pFrImg, pFrameMat);  
    48.             //当前帧跟背景图相减  
    49.             cvAbsDiff(pFrameMat, pBkMat, pFrMat);  
    50.             //二值化前景图  
    51.             cvThreshold(pFrMat, pFrImg, 60, 255.0, CV_THRESH_BINARY);  
    52.             //更新背景  
    53.             cvRunningAvg(pFrameMat, pBkMat, 0.003, 0);  
    54.             //将背景转化为图像格式,用以显示  
    55.             cvConvert(pBkMat, pBkImg);  
    56.   
    57.             cvShowImage("video", pFrame);  
    58.             cvShowImage("background", pBkImg);  
    59.             cvShowImage("foreground", pFrImg);  
    60.   
    61.             if( cvWaitKey(2) >= 0 )  
    62.                 break;  
    63.         }  
    64.     }  
    65.     cvDestroyWindow("video");  
    66.     cvDestroyWindow("background");  
    67.     cvDestroyWindow("foreground");  
    68.     cvReleaseImage(&pFrImg);  
    69.     cvReleaseImage(&pBkImg);  
    70.     cvReleaseMat(&pFrameMat);  
    71.     cvReleaseMat(&pFrMat);  
    72.     cvReleaseMat(&pBkMat);  
    73.     cvReleaseCapture(&pCapture);  
    74.     return 0;  
    75. }  
    效果图:

    转载请注明出处:http://blog.csdn.net/xiaowei_cqu/article/details/7610665
    实验代码及视频下载:http://download.csdn.net/detail/xiaowei_cqu/4335573



  • 相关阅读:
    bzoj2819: Nim
    bzoj4864: [BeiJing 2017 Wc]神秘物质
    【转】 随机梯度下降(Stochastic gradient descent)和 批量梯度下降(Batch gradient descent )的公式对比、实现对比
    【转】梯度下降算法原理
    梯度下降算法的一点认识(Ng第一课)
    快速理解webStroage
    Css选择器实例
    Canvas实例
    HTML5中的Canvas
    骰子效果实例
  • 原文地址:https://www.cnblogs.com/alan666/p/8312343.html
Copyright © 2011-2022 走看看