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(图像为了方便展示做了加粗处理)
mode2
参考
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
完整代码