1原理

https://www.bilibili.com/video/av74302620/?spm_id_from=333.788.videocard.0

https://blog.csdn.net/fzp95/article/details/78385795?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-4&spm=1001.2101.3001.4242

相关和卷积操作》
https://blog.csdn.net/qq_17783559/article/details/82254996

1.1 相关性


其中 f∗表示 f的复共轭。correlation的直观解释就是衡量两个函数在某个时刻相似程度。

1.2 MOSSE 滤波器H公式推导

作者提出的滤波器叫做Minimum Output Sum of Squared Error filter(MOSSE)(误差最小平方和滤波器)。

MOSSE是一种从较少的训练图像中生成滤波器的算法。

1.2.1 结论

先放结论:
整个滤波器的模型公式:
分子是输入和期望输出之间的相关性,分母是输入的能谱。
其中gi表示响应输出,fi表示输入图像,对多组输入和对应的输出求均值,得到h,h表示滤波模板。

Q1: 对于框定的一个目标框,怎么得到多个训练样本输入?
A1: 可以通过任意旋转裁剪

Q2: 训练时候 对应的响应是什么?
A2: 一般来说,gi 可以是任何形状。在这种情况下,gi是由ground truth生成的,它在训练图像fi中有一个以目标为中心的紧凑的(σ = 2.0)二维高斯峰.

Q3:经过样本训练得到了H ,之后怎么用?
A3:利用得到相关性最大的,即响应最大的地方,作为下一次跟踪的目标位置。

ps

在实际跟踪的过程中我们要考虑到目标的外观变换等因素的影响,所以需要同时考虑目标的m个图像作为参考,对跟踪框(groundtruth)进行随机仿射变换,获取一系列的训练样本 fi,

而 gi则是由高斯函数产生,并且其峰值位置是在 fi的中心位置。

获得了一系列的训练样本和结果之后,就可以计算滤波器h的值。注意:这里的f,g,h的size大小都相同。从而提高滤波器模板的鲁棒性。

同时,作者为了让滤波器对与形变、光照等外界影响具有更好的鲁棒性,采取了如下的模板更新策略,作者将滤波器的模型公式分为分子和分母两个部分,每个部分都分别的进行更新:。

其中 At和 At−1分别表示的是当前帧和上一帧的分子。

1.2.2 推导(可以不管)

我们需要找到一个滤波器,使其在目标上的响应最大,则如下公式:

其中g表示响应输出,f表示输入图像,h表示滤波模板。

显然,我们要是想获得比较获得响应输出,只需确定滤波器模板h即可。上式的计算是进行卷积计算,这在计算机中的计算消耗时很大的,因此作者对上式进行快速傅里叶变换(FFT)这样卷积操作经过FFT后就变成了点乘操作,极大的减少了计算量。上式变成如下形式:


为了方便描述,将上式写成如下形式:

后面跟踪的任务就是找到 H∗了

因为上式的操作都是元素级别的,因此要想找到,只要使其中的每个元素的MOSSE都最小即可。因此上式可转换为如下形式:
(w和v是H中每个元素的索引)

要想得到最小的 H*wv,只需要对上式求偏导,并使偏导为0即可。即

即每个位置的值为:

结论

整个滤波器的模型公式:
分子是输入和期望输出之间的相关性,分母是输入的能谱。

ps

但是在实际跟踪的过程中我们要考虑到目标的外观变换等因素的影响,所以需要同时考虑目标的m个图像作为参考,对跟踪框(groundtruth)进行随机仿射变换,获取一系列的训练样本 fi,

而 gi则是由高斯函数产生,并且其峰值位置是在 fi的中心位置。

获得了一系列的训练样本和结果之后,就可以计算滤波器h的值。注意:这里的f,g,h的size大小都相同。从而提高滤波器模板的鲁棒性。

同时,作者为了让滤波器对与形变、光照等外界影响具有更好的鲁棒性,采取了如下的模板更新策略,作者将滤波器的模型公式分为分子和分母两个部分,每个部分都分别的进行更新:。

其中 At和 At−1分别表示的是当前帧和上一帧的分子。

2 具体计算过程

首先,它需要一组训练图像fiand训练输出gi。

2.1 输入目标区域

rect

%% 选择目标区域
% select target from first frame
im = imread(img_files(1,:));
f = figure('Name', 'Select object to track');
imshow(im);
rect = getrect;
close(f); clear f;
center = [rect(2)+rect(4)/2 rect(1)+rect(3)/2];

2.2 获得高斯核

%% 高斯核
% plot gaussian
sigma = 100;
gsize = size(im);%获取图像尺寸
[R,C] = ndgrid(1:gsize(1), 1:gsize(2));
%两个矩阵R和C,都是m行n列
g = gaussC(R,C, sigma, center);%通过R和C产生size等同于im的高斯滤波函数
g = mat2gray(g);
g = imcrop(g, rect);
G = fft2(g);    % 得到目标区域的高斯滤波核的傅里叶变换

2.3 计算 输入的fi

其中fi是框选的目标区域

img = imcrop(img, rect);

人为地连接图像fi的边界会引入一个影响相关输出的伪影。

解决方法:

首先,使用日志函数对像素值进行转换,这有助于低对比度的照明情况。像素值被归一化为平均值0.0和平均值1.0。

最后,将图像乘以一个余弦窗口,使边缘附近的像素值逐渐减少到零。这也有一个好处,它把重点放在了靠近目标中心的地方。
原因:由于傅里叶变换是周期性的,它不尊重图像的边界。非周期图像的相对边之间的巨大不连续将导致有噪声的傅里叶表示。

%将高斯滤波函数变换到频域
height = size(g,1);
width = size(g,2);
%imresize(img, [height width])将图片调整成滤波器的大小
fi = preprocess(imresize(img, [height width]));

preprocess.m处理函数

function img = preprocess(img)
[r,c] = size(img);
win = window2(r,c,@hann);
save win
eps = 1e-5;
img = log(double(img)+1);
img = (img-mean(img(:)))/(std(img(:))+eps);
img = img.*win;
end

2.4 计算初始的Hi(Ai,Bi)及生成多个训练模板

Ai = (G.*conj(fft2(fi)));%相关性
Bi = (fft2(fi).*conj(fft2(fi)));%fi能量谱N = 128;
for i = 1:Nfi = preprocess(rand_warp(img));Ai = Ai + (G.*conj(fft2(fi)));Bi = Bi + (fft2(fi).*conj(fft2(fi)));
end

2.5 利用初始Hi进行预测响应位置,并在线更新

%预测位置Hi = Ai./Bi;fi = imcrop(img, rect);            fi = preprocess(imresize(fi, [height width])); gi = uint8(255*mat2gray(ifft2(Hi.*fft2(fi))));maxval = max(gi(:))[P, Q] = find(gi == maxval);dx = mean(P)-height/2;dy = mean(Q)-width/2;rect = [rect(1)+dy rect(2)+dx width height];%更新滤波器fi = imcrop(img, rect); fi = preprocess(imresize(fi, [height width]));Ai = eta.*(G.*conj(fft2(fi))) + (1-eta).*Ai;Bi = eta.*(fft2(fi).*conj(fft2(fi))) + (1-eta).*Bi;

code

matlab

%get images from source directory
%% 获取图像
%此处仅仅用于得到图片序列所在地址
datadir = 'H:/code/1doctor_code/matlab_code/tracking/mosse-tracker-master/data/';
dataset = 'Surfer';
path = [datadir dataset];
img_path = [path '/img/'];
D = dir([img_path, '*.jpg']);%在img_path下的所有jpg后缀文件的地址放入D中seq_len = length(D(not([D.isdir])));%得到图片总数
if exist([img_path num2str(1, '%04i.jpg')], 'file')img_files = num2str((1:seq_len)', [img_path '%04i.jpg']);
elseerror('No image files found in the directory.');
end
%% 选择目标区域
% select target from first frame
im = imread(img_files(1,:));
f = figure('Name', 'Select object to track');
imshow(im);
rect = getrect;
close(f); clear f;
center = [rect(2)+rect(4)/2 rect(1)+rect(3)/2];
%% 高斯核
% plot gaussian
sigma = 100;
gsize = size(im);%获取图像尺寸
[R,C] = ndgrid(1:gsize(1), 1:gsize(2));
%两个矩阵R和C,都是m行n列
g = gaussC(R,C, sigma, center);%通过R和C产生size等同于im的高斯滤波函数
g = mat2gray(g);
g = imcrop(g, rect);
G = fft2(g);    % 得到目标区域的高斯滤波核的傅里叶变换
%% 随机裁剪原始目标区域,得到N个训练样本
%randomly warp original image to create training set
if (size(im,3) == 3) img = rgb2gray(im);
end
img = imcrop(img, rect);%将高斯滤波函数变换到频域
height = size(g,1);
width = size(g,2);
%imresize(img, [height width])将图片调整成滤波器的大小
fi = preprocess(imresize(img, [height width]));
Ai = (G.*conj(fft2(fi)));
Bi = (fft2(fi).*conj(fft2(fi)));N = 128;
for i = 1:Nfi = preprocess(rand_warp(img));Ai = Ai + (G.*conj(fft2(fi)));Bi = Bi + (fft2(fi).*conj(fft2(fi)));
end% MOSSE online training regimen
eta = 0.25;
fig = figure('Name', 'MOSSE');
t = figure;
mkdir(['results_' dataset]);
for i = 1:size(img_files, 1)img = imread(img_files(i,:));im = img;if (size(img,3) == 3)img = rgb2gray(img);%灰度图endif (i == 1)Ai = eta.*Ai;Bi = eta.*Bi;%似乎没有意义,在i=2的时候同时约了etaelse%预测位置Hi = Ai./Bi;fi = imcrop(img, rect);            fi = preprocess(imresize(fi, [height width])); gi = uint8(255*mat2gray(ifft2(Hi.*fft2(fi))));maxval = max(gi(:))[P, Q] = find(gi == maxval);dx = mean(P)-height/2;dy = mean(Q)-width/2;rect = [rect(1)+dy rect(2)+dx width height];%更新滤波器fi = imcrop(img, rect); fi = preprocess(imresize(fi, [height width]));Ai = eta.*(G.*conj(fft2(fi))) + (1-eta).*Ai;Bi = eta.*(fft2(fi).*conj(fft2(fi))) + (1-eta).*Bi;end% visualizationtext_str = ['Frame: ' num2str(i)];box_color = 'green';position=[1 1];result = insertText(im, position,text_str,'FontSize',15,'BoxColor',...box_color,'BoxOpacity',0.4,'TextColor','white');result = insertShape(result, 'Rectangle', rect, 'LineWidth', 3);imwrite(result, ['results_' dataset num2str(i, '/%04i.jpg')]);imshow(result);drawnow;rect
end

c

// This file ispart of the OpenCV project.
// It is subject to the license terms in the LICENSEfile found in the top-level directory
// of this distribution and athttp://opencv.org/license.html. //
//[1] David S. Bolme et al. "Visual Object Trackingusing Adaptive Correlation Filters"
//   http://www.cs.colostate.edu/~draper/papers/bolme_cvpr10.pdf
// //
// credits:
// Kun-Hsin Chen: for initial c++ code
// Cracki: for the idea of only converting the usedpatch to gray
// #include "opencv2/tracking.hpp" namespace cv {
namespace tracking { struct DummyModel :TrackerModel
{ virtual void modelUpdateImpl(){} virtual void modelEstimationImpl( const std::vector<Mat>& ){}
}; const double eps=0.00001;      // fornormalization
const double rate=0.2;         //learning rate
const double psrThreshold=5.7; //no detection, if PSR is smaller than this struct MosseImpl :TrackerMOSSE
{
protected: Point2d center;//center of the bounding box Size size;      //size ofthe bounding box Mat hanWin; Mat G;          //goal Mat H, A,B;    //state//  Element-wisedivision of complex numbers in src1 and src2 Mat divDFTs( const Mat &src1, const Mat &src2 ) const { Mat c1[2],c2[2],a1,a2,s1,s2,denom,re,im; // split into re and im per src cv::split(src1, c1); cv::split(src2, c2); // (Re2*Re2 + Im2*Im2) = denom //   denom is same forboth channels cv::multiply(c2[0], c2[0], s1); cv::multiply(c2[1], c2[1], s2); cv::add(s1,s2, denom); // (Re1*Re2 + Im1*Im1)/(Re2*Re2 + Im2*Im2) = Re cv::multiply(c1[0], c2[0], a1); cv::multiply(c1[1], c2[1], a2); cv::divide(a1+a2, denom, re, 1.0 ); // (Im1*Re2 - Re1*Im2)/(Re2*Re2 + Im2*Im2) = Im cv::multiply(c1[1], c2[0], a1); cv::multiply(c1[0], c2[1], a2); cv::divide(a1+a2, denom, im, -1.0); // Merge Re and Im back into a complex matrix Mat dst,chn[] = {re,im}; cv::merge(chn, 2, dst); return dst; } void preProcess( Mat &window) const { window.convertTo(window, CV_32F); log(window+ 1.0f, window); //normalize Scalarmean,StdDev; meanStdDev(window, mean, StdDev); window =(window-mean[0]) /(StdDev[0]+eps); //Gaussain weighting window =window.mul(hanWin); } double correlate( const Mat &image_sub, Point&delta_xy ) const//计算相对位移 { MatIMAGE_SUB, RESPONSE, response; // filter in dft space dft(image_sub, IMAGE_SUB, DFT_COMPLEX_OUTPUT); mulSpectrums(IMAGE_SUB, H, RESPONSE, 0, true ); idft(RESPONSE, response, DFT_SCALE|DFT_REAL_OUTPUT); // update center position double maxVal; Point maxLoc; minMaxLoc(response, 0, &maxVal, 0, &maxLoc); delta_xy.x= maxLoc.x - int(response.size().width/2); delta_xy.y= maxLoc.y - int(response.size().height/2); // normalize response Scalarmean,std; meanStdDev(response, mean, std); return (maxVal-mean[0]) / (std[0]+eps); // PSR } Mat randWarp( const Mat& a ) const { cv::RNGrng(8031965); // random rotation double C=0.1; double ang = rng.uniform(-C,C); double c=cos(ang), s=sin(ang); // affine warp matrix Mat_<float> W(2,3); W <<c + rng.uniform(-C,C), -s + rng.uniform(-C,C), 0, s +rng.uniform(-C,C),  c +rng.uniform(-C,C), 0;// random translation Mat_<float> center_warp(2, 1); center_warp << a.cols/2, a.rows/2; W.col(2) = center_warp - (W.colRange(0, 2))*center_warp; Mat warped;warpAffine(a, warped, W, a.size(), BORDER_REFLECT); return warped; } virtual bool initImpl( const Mat& image, const Rect2d& boundingBox ){ model =makePtr<DummyModel>(); Mat img; if (image.channels() == 1) img =image; else cvtColor(image, img, COLOR_BGR2GRAY); int w = getOptimalDFTSize(int(boundingBox.width)); int h = getOptimalDFTSize(int(boundingBox.height)); //Get the center position int x1 = int(floor((2*boundingBox.x+boundingBox.width-w)/2)); int y1 = int(floor((2*boundingBox.y+boundingBox.height-h)/2)); center.x =x1 + (w)/2; center.y =y1 + (h)/2; size.width= w; size.height= h; Mat window;getRectSubPix(img, size, center, window); createHanningWindow(hanWin, size, CV_32F); // goal Matg=Mat::zeros(size,CV_32F); g.at<float>(h/2, w/2) = 1;GaussianBlur(g, g, Size(-1,-1),2.0); double maxVal; minMaxLoc(g, 0,&maxVal); g = g /maxVal; dft(g, G,DFT_COMPLEX_OUTPUT); // initial A,B and H A =Mat::zeros(G.size(), G.type()); B =Mat::zeros(G.size(), G.type()); for(int i=0; i<8; i++) { Matwindow_warp = randWarp(window); preProcess(window_warp); MatWINDOW_WARP, A_i, B_i; dft(window_warp, WINDOW_WARP, DFT_COMPLEX_OUTPUT); mulSpectrums(G          ,WINDOW_WARP, A_i, 0, true); mulSpectrums(WINDOW_WARP, WINDOW_WARP, B_i, 0, true); A+=A_i;B+=B_i;} H =divDFTs(A,B); return true; } virtual bool updateImpl( const Mat& image,Rect2d& boundingBox ) { if (H.empty()) // not initialized return false; Matimage_sub; getRectSubPix(image, size, center, image_sub); if (image_sub.channels() != 1) cvtColor(image_sub, image_sub, COLOR_BGR2GRAY); preProcess(image_sub); Pointdelta_xy; double PSR =correlate(image_sub, delta_xy); if (PSR < psrThreshold) return false; //update location center.x +=delta_xy.x; center.y +=delta_xy.y; Matimg_sub_new; getRectSubPix(image, size, center, img_sub_new); if (img_sub_new.channels() !=1) cvtColor(img_sub_new, img_sub_new, COLOR_BGR2GRAY); preProcess(img_sub_new); // new state for A and B Mat F, A_new,B_new; dft(img_sub_new, F, DFT_COMPLEX_OUTPUT); mulSpectrums(G, F, A_new, 0, true ); mulSpectrums(F, F, B_new, 0, true ); // update A ,B, and H A = A*(1-rate) + A_new*rate; B = B*(1-rate) + B_new*rate; H =divDFTs(A, B); // return tracked rect double x=center.x, y=center.y; int w = size.width,h=size.height; boundingBox= Rect2d(Point2d(x-0.5*w,y-0.5*h), Point2d(x+0.5*w, y+0.5*h)); return true; } public: MosseImpl() {isInit = 0; } // dummy implementation. virtual void read( const FileNode& ){} virtual void write( FileStorage& ) const{} }; // MosseImpl } // tracking Ptr<TrackerMOSSE> TrackerMOSSE::create()
{ returnmakePtr<tracking::MosseImpl>();
} } // cv

【目标跟踪】|MOSSE原理及对应代码解释 matlab C相关推荐

  1. MATLAB应用实战系列(七十六)-【仿真应用】卡尔曼滤波在雷达目标跟踪中的应用仿真(附matlab代码)

    1 模型 目标跟踪问题的应用背景是雷达数据处理,即雷达在搜索到目标并记录目标的位置数据,对测量到的目标位置数据(称为点迹)进行处理,自动形成航迹,并对目标在下一时刻的位置进行预测.本文简要讨论了用Ka ...

  2. 【无人机】基于Matlab实现无人机轨迹规划目标跟踪附论文报告和代码

    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信.

  3. Tracking Learning Detection (TLD)目标跟踪算法原理详解~PPT版

  4. 目标跟踪之光流法---光流法简单介绍

    光流的概念是Gibson在1950年首先提出来的.它是空间运动物体在观察成像平面上的像素运动的瞬时速度,是利用图像序列中像素在时间域上的变化以及相邻帧之间的相关性来找到上一帧跟当前帧之间存在的对应关系 ...

  5. python-opencv打开Azure-Kincet DK相机显示RGB,深度图和点云图,并使用KCF实现单目标跟踪

    本项目使用python-opencv打开Azure-Kincet DK相机,并显示RGB,深度图和点云图和KCF目标跟踪算法 附上实现的代码地址与已经测试成功的系统 本文代码地址:open_azure ...

  6. 目标跟踪:CamShift算法

    1.前言 camshift利用目标的颜色直方图模型将图像转换为颜色概率分布图,初始化一个搜索窗的大小和位置,并根据上一帧得到的结果自适应调整搜索窗口的位置和大小,从而定位出当前图像中目标的中心位置. ...

  7. 目标跟踪算法的分类(二)

     原文: http://www.cnblogs.com/ronny/p/4256150.html 最近对运动目标检测与跟踪这一块的知识进行了一个整体性的回顾,又看了几篇综述性的论文,所以这篇博客算 ...

  8. SSD,NCC,Lucas-Kanade模板匹配,目标跟踪

    SSD,NCC,Lucas-Kanade模板匹配,目标跟踪 SSD 原理: 实现: 结果: NCC 原理: 实现: 结果: Lucas-Kanade 原理: 结果: SSD 原理: 误差平方和算法 数 ...

  9. 无人驾驶感知篇之目标跟踪(十四)

    刚跑步回来,趁着思路比较清晰,再更新一下.上一篇主要写了ECO目标跟踪算法,今天这篇主要写写DLT目标跟踪算法. 1.什么是DLT目标跟踪算法 DLT算法,英文deep learning tracke ...

  10. 无人驾驶感知篇之目标跟踪(十八)

    终于快把目标跟踪写完了,目标跟踪相对检测还是挺复杂的.今天把目标跟踪的最后一篇算法写完,DeepTracking目标跟踪算法,该算法也是深度学习跟踪算法比较难的一种算法. 1.什么是DeepTrack ...

最新文章

  1. visio 模板_盒图模板一键套用,便捷绘制精美盒图图表
  2. “北航Clubs” Beta版本开发目标
  3. 如何使用js动态显示或隐藏DIV
  4. 计算机应用基础教材6,全国2013年自考《计算机应用基础》教材大纲第六章
  5. 系统安全:Nessus Home版安装使用
  6. scada系统集成_专家 | 浅析地铁综合监控系统集成门禁系统
  7. JavaScript学习(十四)—元素节点关系和特殊节点
  8. 实现多国语言的Reporting Services项目
  9. matlab 怎么打开.p文件,matlab p文件肿么打开 或者 运行
  10. Nginx反向代理https配置解决方案
  11. php7 yar扩展,php扩展之Yar使用
  12. win10 运行debussy不能打开波形窗口问题
  13. 多目标优化算法:多目标黄金搜索优化算法MOGSO(提供MATLAB代码)
  14. OSChina 周六乱弹 —— 女友是啥子哟?生命的最大负载?
  15. 建模simulink - xpc自定义模块库
  16. 如果只定一个指标,研发的考核指标应该是什么?
  17. ROS_Kinetic_29 kamtoa simulation学习与示例分析(一)
  18. 显著性物体检测与分割
  19. Relation (mathematics)
  20. php 屏蔽curl访问,php curl指定ip,php curl请求忽略本地host文件,php curl请求跳过本地host文件...

热门文章

  1. d2j-dex2jar classes.dex报错
  2. android 4.4 生僻字,Android上显示生僻字的方法
  3. Oracle常用函数
  4. 如何管理软件测试环境
  5. BT6无线破解+局域网共享(附BT6下载地址)
  6. android开发下载文件损坏解决方法,Android中已下载的.apk文件已损坏
  7. 方舟生存 服务器修改器,【修改贴】关于单机版gg修改器的应用。
  8. 图片双面打印顺序混乱_为什么双面打印一面是正的一面是反的?
  9. mysql数据库面试题大全(持续更新)
  10. Apollo 6.0 QP(二次规划)算法解析