MeanShift(均值漂移)MATLAB程序详解

参考博客

  1. https://blog.csdn.net/jinshengtao/article/details/30258833
    本文介绍了基于MeanShift的目标跟踪算法。首先给出了简介,然后详细介绍了基于MeanShift的目标跟踪算法,之后给出了MeanShift的算法实现流程,最后实现了一个单目标跟踪的MeanShift算法程序【Matlab/C++两个版本】

    该程序应该是网上为数不多的MS程序,大多博客也都以此为基础进行了介绍与仿真。

    本文主要介绍MATLAB程序,C++结合OpenCV程序思路与M程序基本一致,如有需要,理解也没那么麻烦。

  2. https://blog.csdn.net/hololoed/article/details/7591880
    本文介绍了MeanShift的目标跟踪算法思路。具体程序与参考博客【1】相同。

MS算法思路

1.截取跟踪目标矩阵rect

2.求取跟踪目标的加权直方图hist1

3.读取视频序列中的一帧, 先随机取一块与rect等大的矩形,计算加权直方图hist2。

4.【计算两者比重函数】,如果后者差距过大, 更新新的矩阵中心Y,进行迭代(MeanShift是一种变步长可以迅速接近概率密度峰值的方法),直至一定条件后停止。

MS MATLAB程序

function [] = select()
close all;
clear all;
%%%%%%%%%%%%%%%%%%根据一幅目标全可见的图像圈定跟踪目标%%%%%%%%%%%%%%%%%%%%%%%
I=imread('result72.jpg');
figure(1);
imshow(I);


[temp,rect]=imcrop(I);
[a,b,c]=size(temp); 		%a:row,b:col


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%计算目标图像的权值矩阵%%%%%%%%%%%%%%%%%%%%%%%
y(1)=a/2;
y(2)=b/2;
tic_x=rect(1)+rect(3)/2;
tic_y=rect(2)+rect(4)/2;
m_wei=zeros(a,b);%权值矩阵
h=y(1)^2+y(2)^2 ;%带宽


for i=1:a
    for j=1:b
        dist=(i-y(1))^2+(j-y(2))^2;
        m_wei(i,j)=1-dist/h; %epanechnikov profile
    end
end
C=1/sum(sum(m_wei));%归一化系数


%计算目标权值直方图qu
%hist1=C*wei_hist(temp,m_wei,a,b);%target model
hist1=zeros(1,4096);
for i=1:a
    for j=1:b
        %rgb颜色空间量化为16*16*16 bins
        q_r=fix(double(temp(i,j,1))/16);  %fix为趋近0取整函数
        q_g=fix(double(temp(i,j,2))/16);
        q_b=fix(double(temp(i,j,3))/16);
        q_temp=q_r*256+q_g*16+q_b;            %设置每个像素点红色、绿色、蓝色分量所占比重
        hist1(q_temp+1)= hist1(q_temp+1)+m_wei(i,j);    %计算直方图统计中每个像素点占的权重
    end
end
hist1=hist1*C;
rect(3)=ceil(rect(3));
rect(4)=ceil(rect(4));




%%%%%%%%%%%%%%%%%%%%%%%%%读取序列图像
myfile=dir('D:\matlab7\work\mean shift\image\*.jpg');
lengthfile=length(myfile);


for l=1:lengthfile
    Im=imread(myfile(l).name);
    num=0;
    Y=[2,2];
    
    
    %%%%%%%mean shift迭代
    while((Y(1)^2+Y(2)^2>0.5)&num<20)   %迭代条件
        num=num+1;
        temp1=imcrop(Im,rect);
        %计算侯选区域直方图
        %hist2=C*wei_hist(temp1,m_wei,a,b);%target candidates pu
        hist2=zeros(1,4096);
        for i=1:a
            for j=1:b
                q_r=fix(double(temp1(i,j,1))/16);
                q_g=fix(double(temp1(i,j,2))/16);
                q_b=fix(double(temp1(i,j,3))/16);
                q_temp1(i,j)=q_r*256+q_g*16+q_b;
                hist2(q_temp1(i,j)+1)= hist2(q_temp1(i,j)+1)+m_wei(i,j);
            end
        end
        hist2=hist2*C;
        figure(2);
        subplot(1,2,1);
        plot(hist2);
        hold on;
        
        w=zeros(1,4096);
        for i=1:4096
            if(hist2(i)~=0) %不等于
                w(i)=sqrt(hist1(i)/hist2(i));
            else
                w(i)=0;
            end
        end
        
        
        
        %变量初始化
        sum_w=0;
        xw=[0,0];
        for i=1:a;
            for j=1:b
                sum_w=sum_w+w(uint32(q_temp1(i,j))+1);
                xw=xw+w(uint32(q_temp1(i,j))+1)*[i-y(1)-0.5,j-y(2)-0.5];
            end
        end
        Y=xw/sum_w;
        %中心点位置更新
        rect(1)=rect(1)+Y(2);
        rect(2)=rect(2)+Y(1);
    end
    
    
    %%%跟踪轨迹矩阵%%%
    tic_x=[tic_x;rect(1)+rect(3)/2];
    tic_y=[tic_y;rect(2)+rect(4)/2];
    
    v1=rect(1);
    v2=rect(2);
    v3=rect(3);
    v4=rect(4);
    %%%显示跟踪结果%%%
    subplot(1,2,2);
    imshow(uint8(Im));
    title('目标跟踪结果及其运动轨迹');
    hold on;
    plot([v1,v1+v3],[v2,v2],[v1,v1],[v2,v2+v4],[v1,v1+v3],[v2+v4,v2+v4],[v1+v3,v1+v3],[v2,v2+v4],'LineWidth',2,'Color','r');
    plot(tic_x,tic_y,'LineWidth',2,'Color','b');
end

MS M程序详解

1.根据一幅目标全可见的图像圈定跟踪目标

人为的选择视频中的一帧,选择好跟踪目标。

		[temp,rect]=imcrop(I);

打开与此图像关联的裁剪图像工具。指定用于存储裁剪图像的变量,存于temp。
返回值rect,返回所绘制的矩形的四个元素位置向量。
rect格式:【xmin ymin width height】

		[a,b,c]=size(temp); 

注:c不可省,否则可能会报错“索引超出矩阵维度”
如“q_r=fix(double(temp(i,j,1))/16);” ,MATLAB可能会认为temp只是二维,这一行可能就会报错。

2.计算目标图像的权值矩阵

1.计算
目标的中心:(tic_x,tic_y)
权值矩阵:m_wei【Epannechnikov核函数】
带宽:h【核函数窗口大小】
归一化系数:C
2.计算目标权值直方图qu

		q_temp=q_r*256+q_g*16+q_b;

注:这一句并没有看懂。为什么对RGB三通道进行上述操作???
大多MS都用HSV中的H(色调值)来计算。如需要,可通过rgb2hsv来实现,并不难。

		hist1(q_temp+1)= hist1(q_temp+1)+m_wei(i,j);

计算目标直方图统计中每个像素点占的权重
注:下标必须+1,否则,当q_temp为0时,系统会报错“下标索引必须为正整数类型或逻辑类型。”

3.读取视频序列图像

逐帧读取视频,并准备接下来的MS迭代

4.MeanShift迭代

设置迭代条件

	    while((Y(1)^2+Y(2)^2>0.5)&num<20)

如满足,则进行接下来的四个操作步骤:

1.计算侯选目标区域直方图(步骤与之前计算跟踪目标区域直方图一致)
2.绘制候选目标区域的直方图

		figure(2);
        subplot(1,2,1);
        plot(hist2);

3.计算当前区域内各点的权重值w(i)

		 w(i)=sqrt(hist1(i)/hist2(i));

4.计算偏移Y,并更新候选区域的中心

		sum_w=0;
    	xw=[0,0];
   		for i=1:a;
       	 	for j=1:b
            	sum_w=sum_w+w(uint32(q_temp1(i,j))+1);
           		xw=xw+w(uint32(q_temp1(i,j))+1)*[i-y(1)-0.5,j-y(2)-0.5];
        	end
   		end
    	Y=xw/sum_w;
    	rect(1)=rect(1)+Y(2);
    	rect(2)=rect(2)+Y(1);

5.跟踪结果显示

1.跟踪轨迹矩阵

		tic_x=[tic_x;rect(1)+rect(3)/2];
	    tic_y=[tic_y;rect(2)+rect(4)/2];

在第t帧时,得到从t-1帧到第t帧之间,候选区域的直线轨迹,并在程序的最后进行绘制

		plot(tic_x,tic_y,'LineWidth',2,'Color','b');

2.跟踪区域绘制
得到最新的rect区域

	    v1=rect(1);
	    v2=rect(2);
	    v3=rect(3);
	    v4=rect(4);

并绘制当前跟踪区域的边界

		plot([v1,v1+v3],[v2,v2],[v1,v1],[v2,v2+v4],[v1,v1+v3],[v2+v4,v2+v4],[v1+v3,v1+v3],[v2,v2+v4],'LineWidth',2,'Color','r');

致谢

菜鸡解读必有不妥之处,欢迎各位大神批评指正!
同时,再次感谢各个博客平台各位大神给出的思路及源码,感激不尽~

你可能感兴趣的:(本科毕设,Matlab)