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

代数运算中比较常用的是图像相加和相减。图像相加常用来求平均值去除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. 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. }

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

   

   

实践:图像二次曝光

曝光和去噪是一样的,也是对几幅图像求平均
[cpp] view
plain
 copy

  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函数计算两数组的差的绝对值
[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. 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://blog.csdn.net/xiaowei_cqu/article/details/7610665

实验代码及视频下载:http://download.csdn.net/detail/xiaowei_cqu/4335573


最新文章

  1. SAP 采购订单收货时报错:对于采购订单xxxx无收货可能
  2. 在VS中添加lib的简单方法
  3. [BZOJ1407][NOI2002]Savage(扩展欧几里德)
  4. AgularJS中Unknown provider: $routeProvider解决方案
  5. 导出excel乱码问题
  6. Nginx 笔记与总结(15)nginx 实现反向代理 ( nginx + apache 动静分离)
  7. getElementByClassName()不兼容的解决办法
  8. &lt;iOS&gt;other linker flags[转]
  9. VulToEs
  10. python登录csdn并自动评论下载资源脚本
  11. MySQL5.6 linux源码安装
  12. C# SqlConnection
  13. NorFlash
  14. PC机安装Qt以及QT交叉编译环境 分类: OpenCV ZedBoard shell ubuntu Eye_Detection 2014-11-08 18:57 246人阅读 评论(0) 收藏
  15. Java - 泛型 ( Generic )
  16. tarjan+缩点
  17. RPM安装gcc gcc-c++扩展
  18. openstack开发基础
  19. java程序调用xfire发布的webService服务(二)
  20. postman使用—chrome版

热门文章

  1. setup in xunit
  2. streambase一些疑难杂症
  3. 创建表空间及用户的SQL
  4. Javascript中的prototype和__proto__的联系区别
  5. org.apache.http.NoHttpResponseException: XX.XX.XX.XX:80 failed to respond
  6. 理解i++和++i
  7. 获得Version和Build版本号
  8. svn上传文件钩子
  9. Python - Package os
  10. nginx Win下实现简单的负载均衡(2)站点共享Session