Matlab 简单图像特效 Comet效果


思路

希望参考matlab里的内置comet()函数实现一个图像的动态效果

参考图片如下

这里写图片描述
1.将图像二值化并提取边缘。

2.生成底图(形成特效的颜色)。
在这个动态效果中,每一个被激活的点在那一瞬间被赋予底图对应点的颜色。在之后每一轮对RGB图层乘以k(k<1)形成不断变暗的效果。

3.用mode1&2两种方式搜索最左侧点。

在mode1中,当一个点(一段垂直的线)左侧没有相邻的白点时,判断这个点(线的中点)为左侧点。
在mode2中,当一个点(一段垂直的线)是某个联通的环中x坐标最小的时,判断这个点(线的中点)为左侧点。

4.依次激活最左侧点。
每个被激活的点会去激活与它相邻的点以及在它左侧的左侧点。

5.生成gif效果图。

最后形成一定的延时。


实现

理论知识

OTSU算法

当取最佳阈值时,背景应该与前景差别最大,OTSU以类间方差为衡量标准。

数学形态学运算

轮廓提取:对于二值图像,当一个非零的点连接至少一个零点的时候它是轮廓点。(或者可以通过膨胀/腐蚀之后与原图取差。这里相对比较灵活,如果没有经过去噪处理可以考虑通过填充孤立的黑点/去除孤立的白点来进一步处理图像)

自带函数

预处理

%%pretreatment 预处理
I=imread(in);
I=rgb2gray(I); %transform RGB to Gray 将RGB转为灰度
thresh = graythresh(I);     %自动确定二值化阈值
I2 = im2bw(I,thresh);       %对图像二值化
BW2 = bwperim(I2);     %查找边缘

编写函数

查找左侧点

findleft(findleft2):用mode1(mode2)查找最左侧点

function [ T ] = findleft2( BW2 )
%FINDLEFT1 查找最左侧点
%二值图像BW2 返回行为2的矩阵T 每一列代表一个点

        M_dim=size(BW2);
        %%查找最左侧点
        T=[];
        temp=[];        
        for i=4:M_dim(2)-4
            index=0;
            for j=4:M_dim(1)-4  %%search the i th column
                if (BW2(j,i)==1)
                    if 4==i
                        T=[T,[j,i]'];%%add point (j,i)
                        temp=[temp,[j,i]'];
                    else
                        index=index+1;
                        if (BW2(j-1,i)+BW2(j+1,i)+BW2(j-1,i-1)+BW2(j,i-1)+BW2(j+1,i-1))==0 %if there are no point on the rleft
                            T=[T,[j,i]'];%%add point (j,i)
                            temp=[temp,[j,i]'];
                        end
                    end
                else
                    if index~=0 %处理一列黑色的情况
                        t=0;
                        for k=j-index:j-1
                            if BW2(k-1,i-1)+BW2(k,i-1)+BW2(k+1,i-1)~=0
                                t=1;
                            end
                        end
                        if t==0
                            T=[T,[round(j-index/2),i]'];%存储中点
                            temp=[temp,[round(j-index/2),i]'];
                        end
                    end
                    index=0;
                end
                %%以下是和findleft不同的地方
                while temp~=0 % delete all the pixel related 删除所有和起始点有关的点
                    temp_size=size(temp);
                    for ti=1: temp_size(2)
                        x=temp(1,1);
                        y=temp(2,1);
                        BW2(x,y)=0;
                        temp=[temp,findNext(BW2,y,x)];
                        temp(:,1)=[];
                    end
                end
            end
        end
end

function [ T ] = findNext( BW2,i,j )
%FINDNEXT 找到右侧的点
%   二值图像 BW2 坐标(i,j)
T=[];
M_dim=size(BW2);
if (j>4&&i>4&& i<M_dim(2)-4 && j<M_dim(2)-4)%不考虑最周围的点(提取边缘后最周围有一圈白线)
if(BW2(j-1,i)==1)
      T=[T,[j-1,i]'];
end
if(BW2(j+1,i)==1)
      T=[T,[j+1,i]'];
end
if(BW2(j-1,i+1)==1)
      T=[T,[j-1,i+1]'];
end
if(BW2(j,i+1)==1)
      T=[T,[j,i+1]'];
end
if(BW2(j+1,i+1)==1)
      T=[T,[j+1,i+1]'];
end
if(BW2(j-1,i-1)==1)
      T=[T,[j-1,i-1]'];
end
if(BW2(j,i-1)==1)
      T=[T,[j,i-1]'];
end
if(BW2(j+1,i-1)==1)
      T=[T,[j+1,i-1]'];
end
end
end

生成底图

createPicture:生成颜色底图(也可以导入图片等)

function [I1] = createPicture(I2)
%CREATEPICTURE the size of created picture is same as I2
M_dim=size(I2);
R1=zeros(M_dim(1),M_dim(2));
G1=zeros(M_dim(1),M_dim(2));
B1=zeros(M_dim(1),M_dim(2));
for i=4:M_dim(2)-4
    for j=4:M_dim(1)-4
        R1(j,i)=25*sin(j*pi/50)+225;
        G1(j,i)=25*sin(j*pi/50)+225;
        B1(j,i)=255;
    end
end
I1=cat(3,R1,G1,B1);
I1=uint8(I1);
end

底图

形成特效

create:根据左侧点、轮廓、底图生成残影效果

function [  ] = create(BW2, T, I1, out)
%CREATE 生成特效
%  T 起始点
%  I1 background matrix
% out name of output gif
I=zeros(size(I1));
imshow(I1);
I=uint8(I);
burn =[];
count=1;
pic=1;
while T~=0
    burn=[burn,[T(1,1),T(2,1)]'];
    T(:,1)=[];
    while burn~=0
        while max(burn(2,:))>min(T(2,:))
            burn=[burn,[T(1,1),T(2,1)]'];
            T(:,1)=[];
        end
        burn_size=size(burn);
        for i=1:burn_size(2)
            x=burn(1,1);
            y=burn(2,1);
            I(x,y,:)=I1(x,y,:);
            BW2(x,y)=0;
            burn=[burn,findNext(BW2,y,x)];
            burn(:,1)=[];
        end

        I=round(I.*0.98);
        count=count+1;
        imshow(I);
        hold on;

        %make the gif file
        frame=getframe;
        im=frame2im(frame);%制作gif文件,图像必须是index索引图像
        [Im,map]=rgb2ind(im,256);
        if pic==1;
            imwrite(Im,map,out,'gif','Loopcount',inf,...
                'DelayTime',0.02);%loopcount只是在i==1的时候才有用
        else
            imwrite(Im,map,out,'gif','WriteMode','append',...
                'DelayTime',0.02);%DelayTime用于设置gif文件的播放快慢
        end
        pic=pic+1;
    end
end
for j=1:10 %delay 描绘结束后延时
    I=round(I.*0.98);

    imshow(I);
    hold on;
    frame=getframe;
    im=frame2im(frame);%制作gif文件,图像必须是index索引图像
    [Im,map]=rgb2ind(im,256);
    imwrite(Im,map,out,'gif','WriteMode','append',...
        'DelayTime',0.02);%DelayTime用于设置gif文件的播放快慢
end

end

效果图

mode1(图像为了方便展示做了加粗处理)
mode 1

mode2
mode 2


参考

OTSU算法
http://blog.csdn.net/abcjennifer/article/details/6671288
数学形态学描述
http://blog.jobbole.com/84220/
数学形态学 matlab内置函数描述
http://blog.sina.com.cn/s/blog_4d648afc01018upt.html
matlab生成动画
http://www.cnblogs.com/bacazy/archive/2012/12/15/2819172.html


完整代码

https://github.com/birdy-C/Image_Effect.git

posted @ 2017-01-29 22:24  BirdyC  阅读(600)  评论(0编辑  收藏  举报