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

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


【OpenCV】图像代数运算:平均值去噪,减去背景的更多相关文章

  1. opencv图像的基本操作3

    1.获取像素并修改 读取一副图像,根据像素的行和列的坐标获取它的像素值,对于RGB图像而言,返回RGB的值,对于灰度图则返回灰度值 import cv2 import numpy img = cv2. ...

  2. OpenCV图像金字塔:高斯金字塔、拉普拉斯金字塔与图片尺寸缩放

    这篇已经写得很好,真心给作者点个赞.题目都是直接转过来的,直接去看吧. Reference Link : http://blog.csdn.net/poem_qianmo/article/detail ...

  3. 【OpenCV新手教程之十三】OpenCV图像金字塔:高斯金字塔、拉普拉斯金字塔与图片尺寸缩放

    本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/26157633 作者:毛星云(浅墨) ...

  4. 学习 opencv---(12)OpenCV 图像金字塔:高斯金字塔,拉普拉斯金字塔与图片尺寸缩放

    在这篇文章里,我们一起学习下 图像金字塔 的一些基本概念,如何使用OpenCV函数pyrUp和pyrDown 对图像进行向上和向下采样,以及了解专门用于缩放图像尺寸的resize函数的用法.此博文一共 ...

  5. opencv——图像遍历以及像素操作

    摘要 我们在图像处理时经常会用到遍历图像像素点的方式,在OpenCV中一般有四种图像遍历的方式,在这里我们通过像素变换的点操作来实现对图像亮度和对比度的调整. 补充: 图像变换可以看成 像素变换--点 ...

  6. <学习opencv>图像和大型阵列类型

    OPenCV /*=========================================================================*/ // 图像和大型阵列类型 /* ...

  7. Opencv 图像叠加 添加水印

    Opencv 图像叠加 添加水印 C++: void Mat::copyTo(OutputArray m) const C++: void Mat::copyTo(OutputArray m, Inp ...

  8. opencv图像读取-imread

    前言 图像的读取和保存一定要注意imread函数的各个参数及其意义,尽量不要使用默认参数,否则就像数据格式出现错误(here)一样,很难查找错误原因的: re: 1.opencv图像的读取与保存; 完

  9. [OpenCV Qt教程] 在Qt图形界面中显示OpenCV图像的OpenGL Widget(第二部分)

    本文译自:http://www.robot-home.it/blog/en/software/tutorial-opencv-qt-opengl-widget-per-visualizzare-imm ...

随机推荐

  1. Nginx的访问日志配置信息详解

    Nginx的访问日志可以让我们知晓用户的地址,网站的那些部分最受欢迎,以及用户浏览时间等.Nginx会把每个用户的访问日志记录到指定的日志文件中. Nginx主要有两个参数来控制 log_format ...

  2. poj2442优先队列

    感谢 http://hi.baidu.com/%C0%B6%C9%ABarch/blog/item/f9d343f49cd92e53d7887d73.html 的博主! 思路: 我们要找到n个smal ...

  3. Spring中操作Hibernate的几种方式

    1.直接操作模版方式HQL: //通过spring的模版方式来操作Hibernate的HQL语句 return this.getHibernateTemplate().find("from ...

  4. MapReduce-排序(全部排序、辅助排序)

    排序 排序是MapReduce的核心技术. 1.准备 示例:按照气温字段对天气数据集排序.由于气温字段是有符号的整数,所以不能将该字段视为Text对象并以字典顺序排序.反之,用顺序文件存储数据,其In ...

  5. MYSQL进阶学习笔记一:MySQL编码设定,会话变量和全局变量!(视频序号:进阶_1-3)

    知识点一:MySQL编码设定(1-2) 服务器编码设定: 查看MySQL服务器端的编码格式: SHOW VARIABLES LIKE ‘char%’; 设定编码格式: SET NAMES ‘utf8’ ...

  6. JavaScrip 原生多文件上传及预览 兼容多浏览器

    JavaScrip 原生多文件上传及预览 兼容多浏览器 html代码块 <div class="container"> <label>请选择一个图像文件:& ...

  7. java对象流(一)

    注意:字节数组流是可以不用关闭的(字符数组流要不要关闭暂时不清楚). 对象流的读数据和写数据方法分别是writeObject(Object o)和readObject(Object o). Objec ...

  8. cpu和gpu的区别和联系是什么

    cpu和gpu的区别和联系是什么 一.总结 一句话总结:CPU:复杂任务,核少,做串行,计算能力只是CPU很小的一部分,处理复杂逻辑: GPU:简单任务,核多,做并行(大吞吐量),做显卡的图象单元计算 ...

  9. GEF入门实例_总结_03_显示菜单和工具栏

    一.前言 本文承接上一节: GEF入门实例_总结_02_新建初始RCP空项目 这一节,我们来给我们的插件加上菜单. 二.基础知识 1.action bar.menubar.coolbar   含义 a ...

  10. redis_学习_02_redis 可视化工具 Redis Desktop Manager

    二.参考资料 1.Redis可视化工具Redis Desktop Manager使用 2.超好用的Redis管理及监控工具,使用后可大大提高你的工作效率!