计算机视觉
图像处理

【OpenCV】图像代数运算:平均值去噪,减去背景

文章目录

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

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

图像相加

Opencv中提供了相加的函数
  1. void cvAcc(
  2.            const CvArr* image,//输入图像
  3.            CvArr* sum,  //累积图像 
  4.            const CvArr* mask=NULL//可选的运算
  5.  );

我们还需要用到一个线性变换转换函数来对相加的结果求平均

  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的一段幸运团的视频做实验,截取视频的某几个连续帧求平均值:
  1. int main()
  2. {
  3.     CvCapture* capture=cvCaptureFromFile(“media.avi”);
  4.     IplImage* frame=  NULL;
  5.     IplImage * imgsum =NULL;
  6.     int start=301;
  7.     int end=304;
  8.     cvSetCaptureProperty(capture, CV_CAP_PROP_POS_FRAMES, start);
  9.     int count = start;
  10.     while( cvGrabFrame(capture) && count <= end )
  11.     {
  12.         frame = cvRetrieveFrame(capture);// 获取当前帧
  13.         if(imgsum==NULL){
  14.             imgsum=cvCreateImage(cvGetSize(frame),IPL_DEPTH_32F,3);
  15.             cvZero(imgsum);
  16.         }
  17.         cvAcc(frame,imgsum);
  18.         char testname[100];
  19.         sprintf(testname,“%s%d%s”,“image”,count,“.jpg”);
  20.         cvShowImage(testname,frame);
  21.         cvSaveImage(testname,frame);
  22.         count++;
  23.     }
  24.     IplImage * imgavg = cvCreateImage(cvGetSize(frame),IPL_DEPTH_8U,3);
  25.     cvConvertScale(imgsum,imgavg,1.0/4.0);
  26.     cvShowImage(“imageavg”,imgavg);
  27.     cvSaveImage(“imageavg_4.jpg”,imgavg);
  28.     cvWaitKey(0);
  29.     cvReleaseCapture(&capture);
  30.     return 0;
  31. }

以下从左到右分别是连续两帧、四帧、八帧、十六帧求均值的结果:

   
   

实践:图像二次曝光

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

下图是对同学街舞截图的“二次曝光”效果:

图像相减

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

实践:减去背景

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

效果图:

实验代码及视频下载:http://pan.baidu.com/s/1nvSZG7n

转载注明来源:CV视觉网 » 【OpenCV】图像代数运算:平均值去噪,减去背景

分享到:更多 ()
扫描二维码,给作者 打赏
pay_weixinpay_weixin

请选择你看完该文章的感受:

0不错 1超赞 0无聊 0扯淡 0不解 0路过

评论 5

评论前必须登录!