光流运动检测

本方案适用于手持设备拍摄连续多帧拍摄,  使用光流检测场景运动信息.
1. 由于设备或者手抖动, 产生画面的整体偏移--需要先对齐不同的帧.
2. 为了计算性能, 将原始输入图, resize到较小尺寸(此处采用320x200).
3. 从大图直接resize到小图容易产生明显的摩尔纹, 此处采用三级下采样, 有效避免摩尔纹的干扰.

主要流程

  1. 预测多帧图像的相对清晰度
    通过sobel算子,计算不同帧的图像平均梯度值sobelValue, 代表相对清晰度.sobelValue最大的作为Reference, 并根据sobelValue利用统计分析, 标出不可用的BlurImg.

  2. 光流对齐
    Reference下采样到目标Size(OPT_W, OPT_H).
    遍历其他帧(除了Ref img和Blur img), 同样下采样到Size(OPT_W, OPT_H). 进行光流对齐

 //Read Reference frame from pBuffers[refIdx], and resize to target Sizecv::Mat smallRef, resize1, resize2;cv::Mat inputRef(cropheight, cropwidth, CV_8UC1, (uint8_t*)pBuffers[refIdx]);cv::resize(inputRef, resize1, cv::Size(OPT_W*4, OPT_H*4), cv::INTER_CUBIC);cv::resize(resize1, resize2, cv::Size(OPT_W*2, OPT_H*2), cv::INTER_CUBIC);cv::resize(resize2, smallRef, cv::Size(OPT_W, OPT_H), cv::INTER_CUBIC);//Buffers for storing aligned small imageuint8_t* pSmallBuffers[7];for(int k=0;k<burstImgNum;k++) {pSmallBuffers[k] = (uint8_t*)malloc(OPT_W*OPT_H);if(!pSmallBuffers[k] )return;}//Align the smallNoise to the smallRef, and store it in the alignSmall.for(int imgId = 0; imgId < burstImgNum; imgId++) {if(imgId == refIdx || imgIsBlur[imgId] == true) continue;cv::Mat smallNoise;cv::Mat inputNoise(cropheight, cropwidth, CV_8UC1, (uint8_t*)pBuffers[imgId]);cv::Mat alignSmall(OPT_H, OPT_W, CV_8UC1, (uint8_t*)pSmallBuffers[imgId]);cv::resize(inputNoise, resize1, cv::Size(OPT_W*4, OPT_H*4), cv::INTER_CUBIC);cv::resize(resize1, resize2, cv::Size(OPT_W*2, OPT_H*2), cv::INTER_CUBIC);cv::resize(resize2, smallNoise, cv::Size(OPT_W, OPT_H), cv::INTER_CUBIC);alignWithDenseOpticalFlow(smallNoise, smallRef, alignSmall);}
 光流对齐部分代码alignWithDenseOpticalFlow
void alignWithDenseOpticalFlow(cv::Mat& imMov, cv::Mat& imRef, cv::Mat& imAli)
{Mat matFlow; //cv::Mat visFlow(cv::Size(imRef.cols, imRef.rows),CV_8UC1);//Get matFlow from openCV api.calcOpticalFlowFarneback(imRef, imMov, matFlow, 0.5, 3, 15, 3, 5, 1.2, 0);//Sample 100 points uniformly from the middle part of the optical matFlow.std::vector<float> sort_x;std::vector<float> sort_y;for(int y=30; y<150; y+=12){for(int x=40; x<280; x+=24){sort_x.push_back(matFlow.at<cv::Vec2f>(y, x)[0]);sort_y.push_back(matFlow.at<cv::Vec2f>(y, x)[1]);//visFlow.at<uchar>(y, x) = 255;}}//Sort the sampling points, select the middle 20 points, calculate the average value, use it as the offset vector of the whole image.std::sort(sort_x.begin(), sort_x.end());std::sort(sort_y.begin(), sort_y.end());float sum_x = 0.0, sum_y = 0.0;for(int i=40; i<60; i++){sum_x += sort_x.at(i);sum_y += sort_y.at(i);}sum_x /= 20.0;sum_y /= 20.0;//Map imMov to imAli according to the offset vector.Mat map(matFlow.size(), CV_32FC2);for (int y = 0; y < map.rows; ++y){for (int x = 0; x < map.cols; ++x){map.at<Point2f>(y, x) = Point2f(x + sum_x, y + sum_y);}}Mat mapping[2];split(map, mapping);remap(imMov, imAli, mapping[0], mapping[1], INTER_CUBIC);//INTER_LINEAR// static int save_id = 0;// std::string save_name = "/sdcard/sr/sr_results/vismat_" + std::to_string(save_id) + ".jpg";// cv::imwrite(save_name, visFlow);// save_id++;
}
  1. 光流运动场检测.
    使用opencv api --calcOpticalFlowFarneback计算稠密光流(高频场景有噪声, 感觉稀疏光流可以一试, 后话了, 先交作业…),
    由于上面的alignment, 引起图像的平移, 边缘应舍弃, 对光流图裁掉边缘.
    根据光流场, 计算每个像素位置的光流强度并缩放到可视化的范围.
    统计光流强度, 通过阈值判断运动场景.
int getMotionPixels(cv::Mat& iRefFrame, cv::Mat& iCurrFrame, float optThresh)
{int iCount = 0;cv::Mat matFlow;//Get matFlow from openCV api.calcOpticalFlowFarneback(iRefFrame, iCurrFrame, matFlow, 0.5, 3, 15, 3, 5, 1.2, 0);//Crop matFlow 0.1 edgesmatFlow = matFlow(Rect(iRefFrame.cols*0.1, iRefFrame.rows*0.1,  iRefFrame.cols*0.8, iRefFrame.rows*0.8));//cv::Mat visFlow(cv::Size(matFlow.cols, matFlow.rows),CV_8UC1);for (int i = 0; i < matFlow.rows; i++){for (int j = 0; j < matFlow.cols; j++){float tmp0 = matFlow.at<cv::Vec2f>(i, j)[0];float tmp1 = matFlow.at<cv::Vec2f>(i, j)[1];float fImp = sqrt(tmp0 * tmp0 + tmp1 * tmp1);//unsigned char elem = (uchar)(fImp * 51);//visFlow.at<uchar>(i, j) = elem < 255 ? elem : 255;if( fImp*51 > optThresh) iCount++;}}// static int save_id = 0;// std::string save_name = "/sdcard/sr/sr_results/smallFlow_" + std::to_string(save_id) + ".jpg";// cv::imwrite(save_name, visFlow);// save_id++;std::cout<< "***********************Motion pixels     >       "<< optThresh << " iCount: "<< iCount << endl;return iCount;
}

效果对比

1, 输入图4k原图, 连续4帧

2. 对齐之前

3, 去掉摩尔纹, 对齐后

  1. 高频场景存在得问题. 感觉可以结合稀疏光流试试

  1. 静态场景光流图

  1. 动态场景, 光流图

连续多帧图像光流对齐和光流运动检测相关推荐

  1. python opencv光流跟踪,opencv-python 光流

    目标: 了解光流的概念及 Lucas-Kanade 光流法. 使用cv.calcOpticalFlowPyrLK()函数来跟踪视频中的特征点. 光流 由于目标对象或者摄像机的移动造成的图像对象在连续两 ...

  2. 基于RGB-D图像的视觉里程计连续尺度空间直接图像对齐 (ICRA 2021)

    点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 作者丨paopaoslam 来源丨泡泡机器人SLAM 标题:Continuous Scale-Spac ...

  3. 经典光流估计算法和光流对齐方法

    LK光流(稀疏光流) 传统稠密光流算法: Farneback算法 2003 - Gunner Farneback - Two-Frame Motion Estimation Based on Poly ...

  4. 【MATLAB】读取连续帧图像raw文件(代码分享)

    创作时间:2020-01-01 读取连续帧图像raw文件. matlab代码如下: %图像基本信息: %512行,640列,像素深度16bit,帧数不确定.%step1:获得图像的帧数L col=64 ...

  5. 稀疏光流和稠密光流,OpenCV实现

    # 参考:光流Optical Flow介绍与OpenCV实现_zouxy09的专栏-CSDN博客_opencv 光流 # 参考:光流(Optical Flow)算法原理及示例 # 参考:机器学习进阶- ...

  6. OpenCV视频分析与对象跟踪C++(二)光流对象跟踪-稀疏光流、稠密光流

    移动对象跟踪三要素:图像表示(跟踪的对象要在图像中出现)外光模型,移动模型. 稀疏光流跟踪,KTL void calcOpticalFlowPyrLK( // 稀疏光流跟踪,KLTInputArray ...

  7. 稀疏光流python_opencv python 光流法

    光流法 光流是由对象或相机的移动引起的两个连续帧之间的图像对象的明显运动的模式.它是2D矢量场,其中每个矢量是位移矢量,表示从第一帧到第二帧的点的移动. 上图表示的是一个球在连续的5帧图像中的运动,箭 ...

  8. 【slam十四讲第二版】【课本例题代码向】【第七讲~视觉里程计Ⅱ】【使用LK光流(cv)】【高斯牛顿法实现单层光流和多层光流】【实现单层直接法和多层直接法】

    [slam十四讲第二版][课本例题代码向][第七讲~视觉里程计Ⅱ][使用LK光流(cv)][高斯牛顿法实现单层光流和多层光流][实现单层直接法和多层直接法] 0 前言 1 使用LK光流(cv) 1.1 ...

  9. 光流(五)--HS光流及稠密光流

    转自: http://baike.baidu.com/link?url=AXK--povXLrhU6bRTJPsz4lLzva_fNDP0tLglwKtzi9tu-T8gkIi4ffhHWSSTgQG ...

  10. Python: 用open3D库,连续多帧显示点云(查看localization pose的好坏)

    连续多帧显示点云,需要 点云文件 和 定位信息(IMU惯导信息),我这里是从bag包里面自己解析出来的定位信息,因为是自己写的节点,所以直接从代码里面跑出来的,不是ros官方定义的,所以没有用官方给出 ...

最新文章

  1. 动力节点Java培训告诉你Java线程的多功能用法
  2. MySQL - 践行索引优化
  3. P4091-[HEOI2016/TJOI2016]求和【斯特林数,NTT】
  4. php model层怎么写逻辑,目前用php框架的话,大家会把逻辑写到model中吗?
  5. javascript中Date对象及方法
  6. NoHttp使用简析——Android网络请求框架(二)
  7. echarts单个实例包含多个grid,标题分别居中
  8. 内网访问已经启动的vue项目
  9. html网页转换swf格式,swf格式转换器 轻松将swf转mp4(swf转avi)视频格式
  10. python组合数据类型实验报告_Python程序设计实验七:组合数据类型
  11. cad沿线插入块 lisp_AutoCAD导出块名和块插入点列表(AutoLISP源码)——好用的AutoCAD块统计工具...
  12. 如何更好的把平时的工作记录下来?这款便签可以高效记录工作日志
  13. matlab hist函数的使用
  14. 淘宝闲鱼京东等电商api的简单调用
  15. Python将英文标点替换成空格
  16. 安卓开发Material Design ToolBar的DrawerLayout 学习经验
  17. Linux开机启动、bashrc、定时任务
  18. Navicat Premium 使用技巧
  19. CSS——标签选择器,类选择器
  20. 5G标准——独立组网(SA)和非独立组网(NSA)

热门文章

  1. 主引导记录 - 维基百科,自由的百科全书
  2. List,Map和Pojo互转,一行代码解决。多种实现
  3. 基于Leaflet 的Web地图客户端应用程序开发框架
  4. PayPal提现到美国账户收35美元怎么办?最新3种解决办法!
  5. 关于复数i本质的探讨
  6. web漏洞扫描器原理_每周一喂丨用于渗透测试的10种漏洞扫描工具
  7. Python练习题——快乐数字
  8. 微信小程序--Todos案例
  9. JN5169 基于 JN-AN-1217 组网点灯
  10. 用python在大麦网抢票_大麦网自动抢票工具