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

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

    不同版本的mysql命令和配置不一样,以下是2个版本 修改配置文件 log-slow-queries=/alidata/mysql-log/mysql-slow.log long_query_time ...

  2. sql server 2005 Express 下载

    简体中文版: SQL Server 2005 Express Edition 简体中文版 链接页面: http://www.microsoft.com/downloads/details.aspx?d ...

  3. IOS 发布被拒 PLA 1.2问题 整个过程介绍 02 个人账户升级公司账户

    首先,根据上一篇文章得出结论: 1.个人账户,可以发布非营销的APP.例如:公司企业站.个人站 2.公司账户,可以发布营销的APP.例如:京东,天猫,带有盈利的APP 3.企业账户,是使用在公司内部的 ...

  4. Codeforces Round #371 (Div. 2) A ,B , C 水,水,trie树

    A. Meeting of Old Friends time limit per test 1 second memory limit per test 256 megabytes input sta ...

  5. poj 2115 C Looooops 扩展欧几里德

    C Looooops Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 23616   Accepted: 6517 Descr ...

  6. Android开源项目-Easypermissions

    Easypermissions简化了Android M的运行时权限的申请.结果处理.判断等步骤. 1 相关文档 官方文档: https://github.com/googlesamples/easyp ...

  7. 使用 docker 拉取镜像和创建容器-nginx

    本文主要分享通过从docker  hub上获取nginx镜像 1.首先查找nginx镜像 [root@node1 ~]# docker search nginx NAME DESCRIPTION ST ...

  8. if 条件判断 和 判断总结---shell脚本

    本文主要介绍了Shell脚本IF条件判断和判断条件总结,本文先是给出了IF条件判断的语法,然后给出了常用的判断条件总结,需要的朋友可以参考下. 前言: 无论什么编程语言都离不开条件判断.SHELL也不 ...

  9. 删除rime输入法

    mac: 首先将输入法从偏好设置-键盘-输入源中去除,添加系统的输入法. 然后执行命令: $ killall Squirrel $ sudo rm -Rf "/Library/Input M ...

  10. ItelliJ IDEA下载及获取注册码详解

    Idea安装很简单: 官网地址下载:https://www.jetbrains.com/idea/ 注册码获取:http://idea.lanyus.com/   进入此网址,点击“获得注册码”复制使 ...