光流法介绍

2023-11-06

光流场法的基本思想:在空间中,运动可以用运动场描述,而在一个图像平面上,物体的运动往往是通过图像序列中不同图像灰度分布的不同体现的,从而,空间中的运动场转移到图像上就表示为光流场(Optical Flow Field)。光流场反映了图像上每一点灰度的变化趋势,可看成是带有灰度的像素点在图像平面上运动而产生的瞬时速度场,也是一种对真实运动场的近似估计。

在比较理想的情况下,它能够检测独立运动的对象,不需要预先知道场景的任何信息,可以很精确地计算出运动物体的速度,并且可用于摄像机运动的情况。但光流法存在下面的缺点:有时即使没有发生运动,在外部照明发生变化时,也可以观测到光流;另外,在缺乏足够的灰度等级变化的区域,实际运动也往往观测不到。三维物体的运动投影到二维图像的亮度变化,本身由于部分信息的丢失而使光流法存在孔径问题和遮挡问题,用光流法估算二维运动场是不确定的,需要附加的假设模型来模拟二维运动场的结构;在准确分割时,光流法还需要利用颜色、灰度、边缘等空域特征来提高分割精度;同时由于光流法采用迭代的方法,计算复杂耗时,如果没有特殊的硬件支持,很难应用于视频序列的实时检测。

推导光流方程过程:

假设E(x,y,t)为(x,y)点在时刻t的灰度(照度)。设t+dt时刻该点运动到(x+dx,y+dy)点,他的照度为E(x+dx,y+dy,t+dt)。我们认为,由于对应同一个点,所以

E(x,y,t) = E(x+dx,y+dy,t+dt)   —— 光流约束方程

将上式右边做泰勒展开,并令dt->0,则得到:Exu+Eyv+Et = 0,其中:

Ex = dE/dx   Ey = dE/dy   Et = dE/dt   u = dx/dt   v = dy/dt

上面的Ex,Ey,Et的计算都很简单,用离散的差分代替导数就可以了。光流法的主要任务就是通过求解光流约束方程求出u,v。但是由于只有一个方程,所以这是个病态问题。所以人们提出了各种其他的约束方程以联立求解。但是由于我们用于摄像机固定的这一特定情况,所以问题可以大大简化。

摄像机固定的情形

在摄像机固定的情形下,运动物体的检测其实就是分离前景和背景的问题。我们知道对于背景,理想情况下,其光流应当为0,只有前景才有光流。所以我们并不要求通过求解光流约束方程求出u,v。我么只要求出亮度梯度方向的速率就可以了,即求出sqrt(u*u+v*v)。

而由光流约束方程可以很容易求到梯度方向的光流速率为 V = abs(Et/sqrt(Ex*Ex+Ey*Ey))。这样我们设定一个阈值T。

V(x,y) > T 则(x,y)是前景 ,反之是背景

C++实现

在实现摄像机固定情况的光流法时,需要有两帧连续的图像,下面的算法针对RGB24格式的图像计算光流:

void calculate(unsigned char* buf)
{
  int Ex,Ey,Et;
  int gray1,gray2;
  int u;
  int i,j;
  memset(opticalflow,0,width*height*sizeof(int));
  memset(output,255,size);
  for(i=2;i   for(j=2;j    gray1 = int(((int)(buf[(i*width+j)*3]) +(int)(buf[(i*width+j)*3+1]) +(int)(buf[(i*width+j)*3+2]))*1.0/3);

//this postion the continual pix add together and get the mean
    gray2 = int(((int)(prevframe[(i*width+j)*3]) +(int)(prevframe[(i*width+j)*3+1])+(int)(prevframe[(i*width+j)*3+2]))*1.0/3);

//last pic do the same processing


    Et = gray1 - gray2;  //Et means that the difference between the two pic at the same point

//next point in the horizontal direction


    gray2 = int(((int)(buf[(i*width+j+1)*3]) +(int)(buf[(i*width+j+1)*3+1])+(int)(buf[(i*width+j+1)*3+2]))*1.0/3);

    Ex = gray2 - gray1; //x direction (next point )  the difference in the current pic


    gray2 = int(((int)(buf[((i+1)*width+j)*3])+(int)(buf[((i+1)*width+j)*3+1])+(int)(buf[((i+1)*width+j)*3+2]))*1.0/3);
    Ey = gray2 - gray1;  //y direction (next point ) the difference in the current pic


    Ex = ((int)(Ex/10))*10; //int
    Ey = ((int)(Ey/10))*10;
    Et = ((int)(Et/10))*10;
    u = (int)((Et*10.0)/(sqrt((Ex*Ex+Ey*Ey)*1.0))+0.1);// opticalflow mean that
    opticalflow[i*width+j] = u;
    if(abs(u)>10){
     output[(i*width+j)*3] = 0;
     output[(i*width+j)*3+1] = 0;
     output[(i*width+j)*3+2] = 0;
    }
   }
  }
  memcpy(prevframe,buf,size);
}

//

/另一个代码

/

/

WW_RETURN HumanMotion::ImgOpticalFlow(IplImage *pre_grey,IplImage *grey)
/*************************************************
  Function:
  Description:  光流法计算运动速度与方向     
  Date:   2006-6-14
  Author:  
  Input:                       
  Output:        
  Return:        
  Others:         
*************************************************/
{

IplImage *velx = cvCreateImage( cvSize(grey->width ,grey->height),IPL_DEPTH_32F, 1 );
IplImage *vely = cvCreateImage( cvSize(grey->width ,grey->height),IPL_DEPTH_32F, 1 );

velx->origin =  vely->origin = grey->origin;
CvSize winSize = cvSize(5,5);
cvCalcOpticalFlowLK( prev_grey, grey, winSize, velx, vely );
cvAbsDiff( grey,prev_grey, abs_img );
cvThreshold( abs_img, abs_img, 29, 255, CV_THRESH_BINARY);

CvScalar xc,yc;
for(int y =0 ;yheight; y++)
  for(int x =0;xwidth;x++ )
  {
   xc = cvGetAt(velx,y,x);
   yc = cvGetAt(vely,y,x);

   float x_shift= (float)xc.val[0];
   float y_shift= (float)yc.val[0];
   const int winsize=5;  //计算光流的窗口大小

   if((x%(winsize*2)==0) && (y%(winsize*2)==0) )
   {

    if(x_shift!=0 || y_shift!=0)
    {
     if(x>winsize && y>winsize && x <(velx->width-winsize) && y<(velx->height-winsize) )
     {

      cvSetImageROI( velx, cvRect( x-winsize, y-winsize, 2*winsize, 2*winsize));
      CvScalar total_x = cvSum(velx);
      float xx = (float)total_x.val[0];
      cvResetImageROI(velx);

      cvSetImageROI( vely, cvRect( x-winsize, y-winsize, 2*winsize, 2*winsize));
      CvScalar total_y = cvSum(vely);
      float yy = (float)total_y.val[0];
      cvResetImageROI(vely);
      cvSetImageROI( abs_img, cvRect( x-winsize, y-winsize, 2*winsize, 2*winsize));
      CvScalar total_speed = cvSum(abs_img);
      float ss = (float)total_speed.val[0]/(4*winsize*winsize)/255;
      cvResetImageROI(abs_img);

      const double ZERO = 0.000001;
      const double pi = 3.1415926;
      double alpha_angle;

      if(xx-ZERO)
       alpha_angle = pi/2;
      else
       alpha_angle = abs(atan(yy/xx));
      if(xx<0 && yy>0) alpha_angle = pi - alpha_angle ;
      if(xx<0 && yy<0) alpha_angle = pi + alpha_angle ;
      if(xx>0 && yy<0) alpha_angle = 2*pi - alpha_angle ;

      CvScalar line_color;
      float scale_factor = ss*100;
      line_color = CV_RGB(255,0,0);
      CvPoint pt1,pt2;
      pt1.x = x;
      pt1.y = y;
      pt2.x = static_cast(x + scale_factor*cos(alpha_angle));
      pt2.y = static_cast(y + scale_factor*sin(alpha_angle));

      cvLine( image, pt1, pt2 , line_color, 1, CV_AA, 0 );
      CvPoint p;
      p.x = (int) (pt2.x + 6 * cos(alpha_angle - pi / 4*3));
      p.y = (int) (pt2.y + 6 * sin(alpha_angle - pi / 4*3));
      cvLine( image, p, pt2, line_color, 1, CV_AA, 0 );
      p.x = (int) (pt2.x + 6 * cos(alpha_angle + pi / 4*3));
      p.y = (int) (pt2.y + 6 * sin(alpha_angle + pi / 4*3));
      cvLine( image, p, pt2, line_color, 1, CV_AA, 0 );

      /*
      line_color = CV_RGB(255,255,0);
      pt1.x = x-winsize;
      pt1.y = y-winsize;
      pt2.x = x+winsize;
      pt2.y = y+winsize;
      cvRectangle(image, pt1,pt2,line_color,1,CV_AA,0);
      */

     }
    }
   }
  }

cvShowImage( "Contour", abs_img);
cvShowImage( "Contour2", vely);

cvReleaseImage(&velx);
cvReleaseImage(&vely);
cvWaitKey(20);
return WW_OK;

}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

光流法介绍 的相关文章

  • 创建图像列表框?

    如何在 Winforms 应用程序上创建一个 ListBox 控件 该控件以有序的方式包含图像 就像它包含文本一样 I d like the images to appear like this 也许我什至不需要使用列表框 也许有更好的控制
  • 图像缩放会导致 Firefox/Internet Explorer 质量较差,但 Chrome 不会

    See http jsfiddle net aJ333 1 http jsfiddle net aJ333 1 在 Chrome 中 然后在 Firefox 或 Internet Explorer 中 图像最初是 120 像素 我缩小到 2
  • 当我使用 ctx.drawImage() 在画布中放置另一个图像时,无法将画布另存为图像

    我正在尝试制作绘图应用程序 您可以在画布上绘制一些内容 并通过单击 保存 按钮将结果保存为服务器上的图像 您还可以放置另一张图像作为绘图的背景 问题是 当我使用 ctx drawImage 将图像放入画布时 我无法将画布保存为图像 因为什么
  • Fabric JS ClipPath:裁剪后如何使图像适合画布?

    我使用 FabricJS 和 ClipPath 属性实现了图像裁剪 问题是如何使裁剪后的图像适合画布 我希望裁剪后的图像填充画布区域 但不知道是否可以使用 Fabric js 来完成 因此 我希望用户单击 裁剪 按钮后图像的选定部分适合画布
  • 如何获取javafx imageView中显示图像的宽度/高度?

    我需要获取 imegView 中显示图像的宽度 高度 并将其与 imageView getImage getWidth getHeight 中的原始图像大小进行比较 并在用户从应用程序 GUI 中调整其大小时监听更改 I get this
  • 带有多个嵌入图像的 VB.NET 电子邮件

    请有人给我一些关于如何发送包含多个嵌入图像的电子邮件的指示 我可以发送一封基本电子邮件 也可以使用 AlternateView 发送一封带有单个嵌入图像的电子邮件 在 bodyText 中作为 XElement 我有 img src 然后我
  • 在 NoSQL 存储中存储图像

    我们的应用程序将通过 HTTP 提供大量缩略图大小的小图像 大小约为 6 12KB 我被要求调查使用 NoSQL 数据存储是否是一个可行的数据存储解决方案 理想情况下 我们希望我们的数据存储是容错且分布式的 在 NoSQL 存储中存储 bl
  • 寻找 jQuery 效果来逐渐显示隐藏的 DIV/图像

    可能我错过了一些明显的东西 但我无法弄清楚如何慢慢地显示隐藏的图像 DIV 以便它从上到下显示 如果你看一下这个 jsfiddle 你会看到我试图在 jQuery 中使用 show 来显示的图像 http jsfiddle net nick
  • 如何在android sdk中从图库中获取图像并将其显示到屏幕上

    我想知道如何从图库中获取预先保存的图像 然后将其显示到屏幕上 任何教程 有用的链接和信息将不胜感激 如果您希望我进一步解释任何内容 请询问 Intent photoPickerIntent new Intent Intent ACTION
  • 图像增强 - 从书写中清除给定图像

    我需要清理这张照片 删除 清理我 的字样并使其变亮 作为图像处理课程作业的一部分 我可能会使用 matlab 函数 ginput 来查找图像中的特定点 当然 在脚本中您应该对所需的坐标进行硬编码 您可以使用 conv2 fft2 ifft2
  • Python - 查找图像中对象的中心

    我有一个具有白色背景和非白色对象的图像文件 我想使用 python Pillow 找到对象的中心 我在 C 中发现了类似的问题 但没有可接受的答案 如何找到物体的中心 https stackoverflow com questions 12
  • 在 WPF 中显示 Drawing.Image

    我有一个 System Drawing Image 的实例 如何在我的 WPF 应用程序中显示这一点 我尝试过img Source但这不起作用 我有同样的问题并通过结合多个答案来解决它 System Drawing Bitmap bmp I
  • 使用 Zebra 打印机打印时图像模糊且模糊

    我编写了一个库 它根据一些用户输入创建位图图像 然后使用斑马打印机打印该位图 我遇到的问题是斑马打印机打印的图像上的所有内容都非常微弱和模糊 但如果我将位图打印到激光打印机 它看起来完全正常 有人以前遇到过这个问题吗 如果是的话 他们是如何
  • 使用 JavaScript 将图像上传到 Web 服务

    我需要从 javascript 将图像上传到网络服务 我必须发送一个 json 字符串和一个文件 图像 在java中我们有MultipartEntity 我在java中有以下代码 HttpPost post new HttpPost aWe
  • 用 C# 在图像上写入文本

    我有以下问题 我想在位图图像中制作一些图形 例如债券形式 我可以在图像中写入文字但我会在不同的位置写更多的文字 Bitmap a new Bitmap path picture bmp using Graphics g Graphics F
  • PHP - 从图像创建一张图像

    我有 n 张图像 想用 php 代码创建一张 我使用 imagecopymerge 但无法成功 请举一些例子 Code numberOfImages 3 x 940 y 420 background imagecreatetruecolor
  • java.sql.SQLException:在结果集开始之前[重复]

    这个问题在这里已经有答案了 我已尝试使用以下代码来检索存储在数据库中的图像 我创建了一个名为image db包含一个名为的表image details 该表有两个字段 id and image path两者都是类型mediumblob 我在
  • 将 UIImage 放入 UIButton 的简单方法

    我的 iPhone 应用程序中有一个 UIButton 我将其大小设置为 100x100 我有一个 400x200 的图像 我希望在按钮中显示它 按钮仍然需要保持在 100x100 并且我希望图像缩小以适应 但是 保持正确的纵横比 我想这就
  • 如何在 Python 中将图像分割成多个部分

    我正在尝试使用 PIL 将一张照片分成多块 def crop Path input height width i k x y page im Image open input imgwidth im size 0 imgheight im
  • GKE 出现错误:ImagePullBackOff 和错误:ErrImagePull 错误

    当 kubectl 应用 yaml 将自定义构建的 docker 映像部署到 GCP 中的集群 编辑掉敏感信息 时 我收到以下错误 已尝试以下但没有运气 手动部署镜像 检查以确保防火墙规则允许 443 并且没有任何东西阻止它 尝试将容器注册

随机推荐

  • ChatGPT的 6 个强势升级:重点是超强的文件上传和分析功能也来啦!

    发布会核心概览 前日凌晨 OpenAI在社交平台上宣布了一系列新功能 旨在提升用户体验 这6 个新功能包括 提示示例 回答建议 GPT 4默认选择 可分析上传多个文件 保持登录状态和键盘快捷键 其中 可分析上传多个文件的功能非常强大 结合最
  • Leecode392.判断子序列

    题目描述 给定字符串 s 和 t 判断 s 是否为 t 的子序列 字符串的一个子序列是原始字符串删除一些 也可以不删除 字符而不改变剩余字符相对位置形成的新字符串 例如 ace 是 abcde 的一个子序列 而 aec 不是 进阶 如果有大
  • MicroPython——将固件烧写到STM32开发板上

    博主是在 win10环境下 将MicroPython固件烧录到stm32F407开发板上 因为博主想学一波STM32F407 有python基础 但c语言基础一般 觉得学库函数觉得太过复杂 且以后方向可能不太搞嵌入式硬件 所以就用Mirco
  • Eclipse 快捷健

    查询 F3 全局 打开声明 Ctrl G 工作区中的声明 Ctrl shift G 查看变量或方法在工作区的引用 Ctrl Alt H Call Hierarchy 查找出该工程所有调用了该成员变量或方法 Ctrl H 打开搜索对话框 Ct
  • PyQt5 界面预览工具

    简介 一款为了预览PyQt5设计的UI界面而开发的工具 使用时需要结合PyCharm同时使用 下载 PyQt5界面预览工具 参数说明 使用配置 启动PyCharm 找到File gt Settings 打开 找到Tools gt Exter
  • [Java基础]Java中boolean类型到底占用多少个字节?

    1 时间 2017 07 03 07 37 06 YuanMxy 2 问题描述 今天在复习java基础的时候发现一小问题 Java中boolean类型到底占用多少个字节 3 问题解答 1 什么是boolean类型 根据官方文档的描述 htt
  • 在aps.net开发时,改变页面对应的js代码后,重新加载页面后js代码没有加载为最新版本?

    例如页面引用js文件的代码为 在开发人员修改完js代码后 发现重新加载页面时新的js代码不会生效 这是因为页面在向js发出请求时 浏览器发现js文件名和参数没有变化 所以默认 加载了缓存中存在的js代码 可以这样解决这个问题 将页面引用js
  • idea重写接口没有@override_乐字节Java继承|方法重写、super和final关键字

    大家好 乐字节的小乐又来了 上一篇是 乐字节Java JavaBean 继承与权限修饰 也是属于Java继承的 今天继续Java继承 一 方法的重写 父类不满足子类的要求 按需改写 注意 方法签名必须相同 在子类中可以根据需要对从基类中继承
  • 如何进行云主机迁移?看这一篇文章就够了!

    欢迎大家前往腾讯云 社区 获取更多腾讯海量技术实践干货哦 本文由腾讯云计算产品团队发表于云 社区专栏 主机迁移概述 在云计算时代 不管是从IDC上云还是多云直接的迁移 都已经是常见的事宜 而在上云 迁移的方案中 也是有多种的方式能够将主机迁
  • 【颜纠日记】win10开启高性能超频模式,你不知道的N种方法。

    颜纠日记 1 启用游戏模式 Win10 中调整游戏性能最简单的方法 就是启用游戏模式 开启游戏模式 可以通过停止 Windows 更新和一些应用程序的后台活动 来提高游戏帧数 如果不确定是否开启了游戏模式 可以转到 Win I 游戏 游戏模
  • 3D游戏(2)——离散仿真引擎基础

    文章目录 1 简答题 解释 游戏对象 GameObjects 和 资源 Assets 的区别与联系 下载几个游戏案例 分别总结资源 对象组织的结构 指资源的目录组织结构与游戏对象树的层次结构 编写一个代码 使用 debug 语句来验证 Mo
  • Android:WebView加载url网页显示不完整解决办法

    WebView基本用法 如果想要在APP里面加载url网页 或者html代码 首先我们会想到WebView 它的基本用法如下 webview layout xml
  • 基于redis实现延时队列(一)

    背景 最近项目中需要对一条数据 在半小时候更改其状态 类似于提交商城订单半小时后未支付的订单需要更改为超时状态 当然这个解决方案有很多 最好的解决方案是用MQ的死信队列 但由于项目中没有引入MQ 故本文采用的是基于redis与定时器实现该需
  • docker error creating overlay mount to invalid argument 解决方法

    问题原因 由于docker的不同版本在centos上产生的mount问题 1 2 x没有出现这个问题 当使用yum install时 安装的最新版本 1 3 x 会导致overlay2的错误 核心解决方案 etc sysconfig doc
  • Spring Security Oauth2 认证(获取token/刷新token)流程(password模式)

    https blog csdn net bluuusea article details 80284458 1 本文介绍的认证流程范围 本文主要对从用户发起获取token的请求 oauth token 到请求结束返回token中间经过的几个
  • easypoi导出word换行处理

    内容包含换行符 n 导出word时换行符失效 会将换行符 n识别为空格 模板 导出结果 maven
  • Android获取当前时间与星期几 .

    public class DataString private static String mYear private static String mMonth private static String mDay private stat
  • js 判断数组元素是否存在重复项

    方法一 定义测试的数组 1个没有重复元素 1个有重复元素 var arr1 new Array 111 333 222 444 var arr2 new Array aa cc bb dd bb function checkSameElem
  • Java实现一个简单的图书管理系统(内有源码)

    简介 哈喽哈喽大家好啊 之前作者也是讲了Java不少的知识点了 为了巩固之前的知识点再为了让我们深入Java面向对象这一基本特性 就让我们完成一个图书管理系统的小项目吧 项目简介 通过管理员和普通用户的两种操作界面 利用其中的方法以及对象之
  • 光流法介绍

    光流场法的基本思想 在空间中 运动可以用运动场描述 而在一个图像平面上 物体的运动往往是通过图像序列中不同图像灰度分布的不同体现的 从而 空间中的运动场转移到图像上就表示为光流场 Optical Flow Field 光流场反映了图像上每一