【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



原文地址:https://www.cnblogs.com/alan666/p/8312343.html