使用光流法进行视频显著性检测(Matlab)(上)

##由于作者比较菜就使用了别人的代码做了点改进和实验

原始视频(bmp序列):(猴子和狗进行了友好的握手之后,猴子对狗挥手道别,狗目送猴离去)

难点:1.画质差 2.镜头晃动 3.背景复杂

首先,使用的是https://www.cnblogs.com/tiandsp/archive/2012/07/16/2593883.html里使用的HSoptflow.m函数:

function [us,vs] = HSoptflow(Xrgb,n)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Author: Gregory Power gregory.power@wpafb.af.mil
% This MATLAB code shows a Motion Estimation map created by
% using a Horn and Schunck motion estimation technique on two
% consecutive frames.  Input requires.
%     Xrgb(h,w,d,N) where X is a frame sequence of a certain
%                height(h), width (w), depth (d=3 for color), 
%                and number of frames (N). 
%     n= is the starting frame number which is less than N 
%     V= the output variable which is a 2D velocity array
%
% Sample Call: V=HSoptflow(X,3);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
[h,w,d,N]=size(Xrgb);
if n>N-1
   error(1,'requested file greater than frame number required');
end; 
%get two image frames
if d==1
    Xn=double(Xrgb(:,:,1,n));
    Xnp1=double(Xrgb(:,:,1,n+1));
elseif d==3
    Xn=double(Xrgb(:,:,1,n)*0.299+Xrgb(:,:,2,n)*0.587+Xrgb(:,:,3,n)*0.114);
    Xnp1=double(Xrgb(:,:,1,n+1)*0.299+Xrgb(:,:,2,n+1)*0.587+Xrgb(:,:,3,n+1)*0.114);
else
    error(2,'not an RGB or Monochrome image file');
end;

%get image size and adjust for border
size(Xn);
hm5=h-5; wm5=w-5;
z=zeros(h,w); v1=z; v2=z;

%initialize
dsx2=v1; dsx1=v1; dst=v1;
alpha2=625;
imax=20;

%Calculate gradients
dst(5:hm5,5:wm5) = ( Xnp1(6:hm5+1,6:wm5+1)-Xn(6:hm5+1,6:wm5+1) + Xnp1(6:hm5+1,5:wm5)-Xn(6:hm5+1,5:wm5)+ Xnp1(5:hm5,6:wm5+1)-Xn(5:hm5,6:wm5+1) +Xnp1(5:hm5,5:wm5)-Xn(5:hm5,5:wm5))/4;
dsx2(5:hm5,5:wm5) = ( Xnp1(6:hm5+1,6:wm5+1)-Xnp1(5:hm5,6:wm5+1) + Xnp1(6:hm5+1,5:wm5)-Xnp1(5:hm5,5:wm5)+ Xn(6:hm5+1,6:wm5+1)-Xn(5:hm5,6:wm5+1) +Xn(6:hm5+1,5:wm5)-Xn(5:hm5,5:wm5))/4;
dsx1(5:hm5,5:wm5) = ( Xnp1(6:hm5+1,6:wm5+1)-Xnp1(6:hm5+1,5:wm5) + Xnp1(5:hm5,6:wm5+1)-Xnp1(5:hm5,5:wm5)+ Xn(6:hm5+1,6:wm5+1)-Xn(6:hm5+1,5:wm5) +Xn(5:hm5,6:wm5+1)-Xn(5:hm5,5:wm5))/4;

for i=1:imax
   delta=(dsx1.*v1+dsx2.*v2+dst)./(alpha2+dsx1.^2+dsx2.^2);
   v1=v1-dsx1.*delta;
   v2=v2-dsx2.*delta;
end
u=z; u(5:hm5,5:wm5)=v1(5:hm5,5:wm5);
v=z; v(5:hm5,5:wm5)=v2(5:hm5,5:wm5);

xskip=round(h/64);
[hs,ws]=size(u(1:xskip:h,1:xskip:w));
us=zeros(hs,ws); vs=us;

N=xskip^2;
for i=1:hs-1
  for j=1:ws-1
     hk=i*xskip-xskip+1;
     hl=i*xskip;
     wk=j*xskip-xskip+1;
     wl=j*xskip;
     us(i,j)=sum(sum(u(hk:hl,wk:wl)))/N;
     vs(i,j)=sum(sum(v(hk:hl,wk:wl)))/N;
  end
end

figure(1);
quiver(us,vs);
colormap('default');
axis ij;
axis tight;
axis equal;

运行结果如下:


实现代码:

close all;
clear all;
clc;
img_dir = dir('./monkeydog/*.bmp');
[m n]=size(img_dir);
raw=zeros(240,320,1,m);
for i=1:m
    name=strcat('./monkeydog/',img_dir(i).name);
    I=imread(name);
    raw(:,:,1,i)=rgb2gray(I);
end

for i=1:m-1
    V=HSoptflow(raw,i);
    imshow(V)
    imgname=strcat('C:\Users\71405\Desktop\回收站\计算机视觉\2018.6.12\output2\img_',num2str(i),'.jpg');
    saveas(gcf,imgname);#保存图片
end


很混乱,而且尺寸很小,不会处理,于是采用了第二种方法:

原文链接:https://blog.csdn.net/garfielder007/article/details/50441756

其中缺少的computeColor.m链接:http://www.codeforge.cn/read/215288/computeColor.m__html

function img = computeColor(u,v)
 
%   computeColor color codes flow field U, V
 
%   According to the c++ source code of Daniel Scharstein 
%   Contact: schar@middlebury.edu
 
%   Author: Deqing Sun, Department of Computer Science, Brown University
%   Contact: dqsun@cs.brown.edu
%   $Date: 2007-10-31 21:20:30 (Wed, 31 Oct 2006) $
 
% Copyright 2007, Deqing Sun.
%
%                         All Rights Reserved
%
% Permission to use, copy, modify, and distribute this software and its
% documentation for any purpose other than its incorporation into a
% commercial product is hereby granted without fee, provided that the
% above copyright notice appear in all copies and that both that
% copyright notice and this permission notice appear in supporting
% documentation, and that the name of the author and Brown University not be used in
% advertising or publicity pertaining to distribution of the software
% without specific, written prior permission.
%
% THE AUTHOR AND BROWN UNIVERSITY DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
% INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ANY
% PARTICULAR PURPOSE.  IN NO EVENT SHALL THE AUTHOR OR BROWN UNIVERSITY BE LIABLE FOR
% ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 
 
nanIdx = isnan(u) | isnan(v);
u(nanIdx) = 0;
v(nanIdx) = 0;
 
colorwheel = makeColorwheel();
ncols = size(colorwheel, 1);
 
rad = sqrt(u.^2+v.^2);          
 
a = atan2(-v, -u)/pi;
 
fk = (a+1) /2 * (ncols-1) + 1;  % -1~1 maped to 1~ncols
    
k0 = floor(fk);                 % 1, 2, ..., ncols
 
k1 = k0+1;
k1(k1==ncols+1) = 1;
 
f = fk - k0;
 
for i = 1:size(colorwheel,2)
    tmp = colorwheel(:,i);
    col0 = tmp(k0)/255;
    col1 = tmp(k1)/255;
    col = (1-f).*col0 + f.*col1;   
    
    idx = rad <= 1;   
    col(idx) = 1-rad(idx).*(1-col(idx));    % increase saturation with radius
     
    col(~idx) = col(~idx)*0.75;             % out of range
     
    img(:,:, i) = uint8(floor(255*col.*(1-nanIdx)));         
end;    
 
%%
function colorwheel = makeColorwheel()
 
%   color encoding scheme
 
%   adapted from the color circle idea described at
%   http://members.shaw.ca/quadibloc/other/colint.htm
 
 
RY = 15;
YG = 6;
GC = 4;
CB = 11;
BM = 13;
MR = 6;
 
ncols = RY + YG + GC + CB + BM + MR;
 
colorwheel = zeros(ncols, 3); % r g b
 
col = 0;
%RY
colorwheel(1:RY, 1) = 255;
colorwheel(1:RY, 2) = floor(255*(0:RY-1)/RY)';
col = col+RY;
 
%YG
colorwheel(col+(1:YG), 1) = 255 - floor(255*(0:YG-1)/YG)';
colorwheel(col+(1:YG), 2) = 255;
col = col+YG;
 
%GC
colorwheel(col+(1:GC), 2) = 255;
colorwheel(col+(1:GC), 3) = floor(255*(0:GC-1)/GC)';
col = col+GC;
 
%CB
colorwheel(col+(1:CB), 2) = 255 - floor(255*(0:CB-1)/CB)';
colorwheel(col+(1:CB), 3) = 255;
col = col+CB;
 
%BM
colorwheel(col+(1:BM), 3) = 255;
colorwheel(col+(1:BM), 1) = floor(255*(0:BM-1)/BM)';
col = col+BM;
 
%MR
colorwheel(col+(1:MR), 3) = 255 - floor(255*(0:MR-1)/MR)';
colorwheel(col+(1:MR), 1) = 255;

并使用了基于局部距离的图像显著性做遮罩,即图像显著性高的地方为1,显著性低的为0。对光流法所得的显著性做遮罩,只保留图像显著性为1的地方。

最后结果如下:


实现代码:

img_dir = dir('./monkeydog/*.bmp');

[m n]=size(img_dir);

for q=1:m
    name1=strcat('./monkeydog/',img_dir(q).name);
    name2=strcat('./monkeydog/',img_dir(q+1).name);
    Iref = imread(name1);
    Iinput = imread(name2);
    I=Iinput;
     
    
    %% 求后一帧的显著性
     [m n d]=size(I);
    Iq=imresize(uint8(I),[240,240*n/m]);
    Iref=imresize(uint8(Iref),[240,240*n/m]);
    Iinput=imresize(uint8(Iinput),[240,240*n/m]);
    mode=fspecial('gaussian', 1, 1);
    %IS=imfilter(Iq,mode,'replicate');  
    IS=Iq;
    [label,num]=superpixels(IS,300);
    BW = boundarymask(label);
     %imshow(imoverlay(IS,BW,'cyan'),'InitialMagnification',100);
     %figure
    [m n]=size(label);
    supmean=uint64(zeros(num,5)); 
    labelnum=zeros(num);

    for i=1:m
        for j=1:n
            supmean(label(i,j),1)=supmean(label(i,j),1)+i;
            supmean(label(i,j),2)=supmean(label(i,j),2)+j;
            supmean(label(i,j),3)=(supmean(label(i,j),3)+uint64(IS(i,j,1)));
            supmean(label(i,j),4)=(supmean(label(i,j),4)+uint64(IS(i,j,2)));
            supmean(label(i,j),5)=(supmean(label(i,j),5)+uint64(IS(i,j,3)));
            labelnum(label(i,j))=labelnum(label(i,j))+1;
        end
    end
    for i=1:num
        supmean(i,1)=uint16(supmean(i,1)./labelnum(i));
        supmean(i,2)=uint16(supmean(i,2)./labelnum(i));
        supmean(i,3)=uint16(supmean(i,3)./labelnum(i));
        supmean(i,4)=uint16(supmean(i,4)./labelnum(i));
        supmean(i,5)=uint16(supmean(i,5)./labelnum(i));
    end

    IM=zeros(m,n,3);
    for i=1:m
        for j=1:n
            IM(i,j,1)=uint8(supmean(label(i,j),3));
            IM(i,j,2)=uint8(supmean(label(i,j),4));
            IM(i,j,3)=uint8(supmean(label(i,j),5));
        end
    end
    supim=uint8(cat(3,IM(:,:,1),IM(:,:,2),IM(:,:,3)));
    %imshow(supim);


    %全局 
    supmean=double(supmean);
    dist_all=zeros(num,1);
    w0=0.0;
    for i=1:num
       for j=1:num
           if ((supmean(i,1)-supmean(j,1))^2+(supmean(i,2)-supmean(j,2))^2)<500
                dist_all(i)=dist_all(i)+(w0*(supmean(i,1)-supmean(j,1))^2+w0*(supmean(i,2)-supmean(j,2))^2+(supmean(i,3)-supmean(j,3))^2+(supmean(i,4)-supmean(j,4))^2+(supmean(i,5)-supmean(j,5))^2)^0.5;
           end
       end
    end
    %归一化
    dist_min=min(dist_all);
    dist_max=max(dist_all);
    for i=1:num
        dist_all(i)=(dist_all(i)-dist_min)*255/(dist_max-dist_min);
    end
    dist_all=uint8(dist_all);
    im_all=zeros(240,240*n/m);
    for i=1:m
        for j=1:n
            im_all(i,j)=dist_all(label(i,j));
        end
    end
    im_all=uint8(im_all);
    im_all_bw=im2bw(im_all,0.55);
    %im_all=im2bw(im_all,0.05);
    
    %% 光流法
    if size(Iref, 3) == 3
        Irefg = rgb2gray(Iref);
        Iinputg = rgb2gray(Iinput);
    else
        Irefg = Iref;
        Iinputg = Iinput;
    end
% 创建光流对象及类型转化对象
    opticalFlow = vision.OpticalFlow('ReferenceFrameDelay',1);
    converter = vision.ImageDataTypeConverter;
% 修改光流对象的配置
    opticalFlow.OutputValue = 'Horizontal and vertical components in complex form'; % 返回复数形式光流图
    opticalFlow.ReferenceFrameSource = 'Input port'; % 对比两张图片,而不是视频流
    if 1 % 使用的算法
        opticalFlow.Method = 'Lucas-Kanade';
        opticalFlow.NoiseReductionThreshold = 0.001; % 默认是0.0039
    else
        opticalFlow.Method = 'Horn-Schunck';
        opticalFlow.Smoothness = 0.5; % 默认是1
    end
% 调用光流对象计算两张图片的光流
    Iinputg_c = step(converter, Iinputg);
    Irefg_c = step(converter, Irefg);
    of = step(opticalFlow, Iinputg_c, Irefg_c);
    ofH = real(of);
    ofV = imag(of);
    
 [m n]=size(ofV);
    for j=1:m
        for k=1:n
            if abs(double(ofV(m,n)))<0.5
                ofV(m,n)=1;
            else
                ofV(m,n)=0;
            end
        end
    end
    %im_all=1-im_all;
% 将光流转化为彩色图显示
   % B=strel('disk',1);
    %ofV=imdilate(ofV,B);
    %ofV=imerode(ofV,B); 
    ofI = computeColor(ofH, ofV);
    ofI(:,:,1)=ofI(:,:,1).*uint8(im_all_bw);
    ofI(:,:,2)=ofI(:,:,2).*uint8(im_all_bw);
    ofI(:,:,3)=ofI(:,:,3).*uint8(im_all_bw);
    ofI=cat(3,ofI(:,:,1),ofI(:,:,2),ofI(:,:,3));
%显示结果
%     ofV=uint8(ofV);
%     ofV=ofV.*im_all;
    for qa=1:m
        for qb=1:n
            if ofI(qa,qb,1)+ofI(qa,qb,2)+ofI(qa,qb,3)==0
                ofI(qa,qb,1)=255;
                ofI(qa,qb,2)=255;
                ofI(qa,qb,3)=255;
            end
        end
    end
    subplot(121),imshow(I);
    subplot(122),
    imshow(ofI)
    pause(0.01);
    imgname=strcat('C:\Users\71405\Desktop\回收站\计算机视觉\2018.6.12\output3\img_',num2str(q),'.jpg');
    saveas(gcf,imgname);
end

效果也不太好,于是使用Liu Ce所撰写的代码:

原文链接:http://people.csail.mit.edu/celiu/OpticalFlow/

效果图:

(左:光流为距离显著做遮罩 右:距离显著由光流做遮罩)

效果还凑活,就是有的时候会丢失,导致结果一闪一闪的。

代码:

close all;
clear all;
clc;
img_dir = dir('./monkeydog/*.bmp');
[m n]=size(img_dir);
for i=1:m-1
    name1=strcat('./monkeydog/',img_dir(i).name);
    name2=strcat('./monkeydog/',img_dir(i+1).name);
    I1=imread(name1);
    I2=imread(name2);
    I1=imresize(I1,[120,160]);
    I2=imresize(I2,[120,160]);
    alpha = 0.012;
    ratio = 0.75;
    minWidth = 20;
    nOuterFPIterations = 7;
    nInnerFPIterations = 1;
    nSORIterations = 30;
    para = [alpha,ratio,minWidth,nOuterFPIterations,nInnerFPIterations,nSORIterations];
    [vx,vy,warpI2] = Coarse2FineTwoFrames(I1,I2,para);
    vx=vx-mean(mean(vx));%去中心化
    vy=vy-mean(mean(vy));
    v=sqrt(vx.^2+vy.^2);
    v1=v;
    [l,d]=size(v);

    %v=log(double(v));
    v=imadjust(v,[],[],1.1);%增加对比度 亮的更亮 暗的更暗
    maxi=max(max(v));
    mini=min(min(v));
    for k=1:l
        for o=1:d
            v(k,o)=(v(k,o)-mini)*255/(maxi-mini);%归一化到[0 255]
        end
    end
    v=uint8(v);
    img=suptype(I2);
    %方法一: v作为遮罩
    v1=im2bw(v,0.85);
    img3=filter2(fspecial('gaussian'),sample)
    img2=0.8*img.*uint8(v1)+0.2*img;
    %方法二:img作为遮罩
    img1=im2bw(img,0.65);
    v2=0.8*v.*uint8(img1)+0.2*img;
    
    
    img2=imadjust(img2,[],[],2);
    v2=imadjust(v2,[],[],2);
    subplot(121),imshow(img2);
    subplot(122),imshow(v2);
    pause(0.01)
    imgname=strcat('C:\Users\71405\Desktop\回收站\计算机视觉\2018.6.12\output\img_',num2str(i),'.jpg');
    saveas(gcf,imgname);
end

其中求显著性图像的代码为suptype.m

function img = suptype(I)
    [m n d]=size(I);
    %I=imresize(uint8(I),[120,120*n/m]);
    %mode=fspecial('gaussian', 1, 1);
    %IS=imfilter(I,mode,'replicate');  
    IS=I;
    [label,num]=superpixels(IS,300);
    BW = boundarymask(label);
     %imshow(imoverlay(IS,BW,'cyan'),'InitialMagnification',100);
     %figure
    [m n]=size(label);
    supmean=uint64(zeros(num,5)); 
    labelnum=zeros(num);

    for i=1:m
        for j=1:n
            supmean(label(i,j),1)=supmean(label(i,j),1)+i;
            supmean(label(i,j),2)=supmean(label(i,j),2)+j;
            supmean(label(i,j),3)=(supmean(label(i,j),3)+uint64(IS(i,j,1)));
            supmean(label(i,j),4)=(supmean(label(i,j),4)+uint64(IS(i,j,2)));
            supmean(label(i,j),5)=(supmean(label(i,j),5)+uint64(IS(i,j,3)));
            labelnum(label(i,j))=labelnum(label(i,j))+1;
        end
    end
    for i=1:num
        supmean(i,1)=uint16(supmean(i,1)./labelnum(i));
        supmean(i,2)=uint16(supmean(i,2)./labelnum(i));
        supmean(i,3)=uint16(supmean(i,3)./labelnum(i));
        supmean(i,4)=uint16(supmean(i,4)./labelnum(i));
        supmean(i,5)=uint16(supmean(i,5)./labelnum(i));
    end

    IM=zeros(m,n,3);
    for i=1:m
        for j=1:n
            IM(i,j,1)=uint8(supmean(label(i,j),3));
            IM(i,j,2)=uint8(supmean(label(i,j),4));
            IM(i,j,3)=uint8(supmean(label(i,j),5));
        end
    end
    supim=uint8(cat(3,IM(:,:,1),IM(:,:,2),IM(:,:,3)));
    %imshow(supim);


    %全局 
    supmean=double(supmean);
    dist_all=zeros(num,1);
    w0=0.0;
    for i=1:num
       for j=1:num
           if ((supmean(i,1)-supmean(j,1))^2+(supmean(i,2)-supmean(j,2))^2)<500
                dist_all(i)=dist_all(i)+(w0*(supmean(i,1)-supmean(j,1))^2+w0*(supmean(i,2)-supmean(j,2))^2+(supmean(i,3)-supmean(j,3))^2+(supmean(i,4)-supmean(j,4))^2+(supmean(i,5)-supmean(j,5))^2)^0.5;
           end
       end
    end
    %归一化
    dist_min=min(dist_all);
    dist_max=max(dist_all);
    for i=1:num
        dist_all(i)=(dist_all(i)-dist_min)*255/(dist_max-dist_min);
    end
    dist_all=uint8(dist_all);
    im_all=zeros(120,120*n/m);
    for i=1:m
        for j=1:n
            im_all(i,j)=dist_all(label(i,j));
        end
    end
    im_all=uint8(im_all);
    %im_all=im2bw(im_all,0.55);
    %im_all=uint8(im2bw(im_all,0.55)).*I(:,:,1);
    
    %显示图片 
    img=im_all;

并使用了该论文中的部分函数:


论文代码下载地址:http://people.csail.mit.edu/celiu/OpticalFlow/OpticalFlow.zip


最后使用ae伪造一个效果图(没错这其实是一个如何用ae伪造结果的博客):

第一步,导入bmp序列:


第二步:把序列导入合成,并点 效果->抠像->颜色差值键


第三步:选择效果控件中 视图->已校正遮罩 并使用预览图中的三个吸管(用第二个取背景  第三个取前景)求出最后效果如下:


多取几次,使猴子基本为黑,背景基本为白。

第四步:用矩形工具建立如下大小左右的遮罩。


第五步:根据猴子的移动设置对遮罩关键帧“跟踪”即可


简单做几个关键帧即可,使得猴子全身基本在框内就可以。最后直接渲染即可。

结果图:

(是不是比前边几个效果好太多 [/斜眼笑]  )

阅读更多
博主设置当前文章不允许评论。

没有更多推荐了,返回首页

关闭
关闭
关闭