书接上文,上回书说到,使用Liu Ce的光流法后,获得的图像结果一闪一闪的,于是对图像进行优化:
首先把之前所得到的图片序列存放在三维数组中(新增部分)
p1=uint8(zeros(m-1,120,160)); p2=uint8(zeros(m-1,120,160)); %遮罩部分代码 同上一篇博客 %for i=1:m-1 p1(i,:,:)=img2; p2(i,:,:)=v2;
以下只取p2继续优化,p1步骤同。
读取三维矩阵中的每一张图像:
img=p2(i,:,:); img=reshape(img,[120,160]);
注意:p2(i,:,:)实际上为1*m*n的矩阵,不能直接作为图像,所以对他进行reshape成120*160的二维矩阵。
对当前图像进行边缘分割(使用sobel算子为例):
BW= edge(img,'sobel');
BW为边缘为1,其他为0的二值图像,接下来对BW的边缘所描述的内容进行填充:
由于本人比较懒,就直接逐行扫描,得到这一行的最开始的边界点和最后的边界点,如果距离小于某个阈值,则他们之间的像素置1。可尝试换用高级的填充算法。
[m n]=size(BW); for a=1:m start=0; endi=0; for b=1:n if BW(a,b)==1 start=b; break; end end for b=n:-1:1 if BW(a,b)==1 endi=b; break; end end if start~=0 &&endi~=0 && endi-start<=30 for b=start:endi BW(a,b)=1; end end end
之后遍历填充区域内所有的点,求这个点到边缘的最短距离。
采用八方向查找,即求出八个方向到边缘的长度,找出最小的距离,视为最短距离:
for a=1:m for b=1:n if BW(a,b)==1 r=mindis(BW,a,b,m,n);
求最短距离的函数:
function r=mindis(BW,x,y,m,n) disi=zeros(1,8);%存放八个方向的最短距离 dist=[0,-1;-1,-1;-1,0;-1,1;0,1;1,1;1,0;1,-1];%方向 左-上-右-下 for i=1:8%遍历八个方向 dx=x;%遍历点的横坐标 dy=y; while dx>0 && dx<=m && dy>0 && dy<=n && BW(dx,dy)==1 %如果遍历点没出图像的范围并且扫描点的像素值为1,循环,直至到图像边缘或者像素值为0 结束 if rem(i,2)==1 disi(i)=disi(i)+1;%水平/垂直方向+1 else disi(i)=disi(i)+sqrt(2);%斜方向+根2 end dx=dx+dist(i,1);%更迭 dy=dy+dist(i,2); end r=min(disi);%返回最短距离 end end
求出最短距离后,对该点的像素值进行平滑:
该点的像素值由本身像素值加上一帧和下一帧的相应位置范围内所有点的像素值与其颜色距离和物理距离得到,即:
,如果该像素所在的图片为第一帧/最后一帧,则只考虑本身和下一帧/上一帧即可。
sum1=0; sum2=0; for c=1:m for d=1:n if sqrt((a-c)^2+(b-d)^2)<=r sum1=sum1+p2(i+1,c,d)/log(double(abs(p2(i,a,b)-p2(i+1,c,d))*sqrt((a-c)^2+(b-d)^2))); end end end for c=1:m for d=1:n if sqrt((a-c)^2+(b-d)^2)<=r sum2=sum2+p2(i-1,c,d)/log(double(abs(p2(i,a,b)-p2(i-1,c,d))*sqrt((a-c)^2+(b-d)^2))); end end end p2n(i,a,b)=(p2(i,a,b)+sum1+sum2)/3;
sum1为下一帧之和,sum2为上一帧之和,p2n为新建的三维数组,用来存储更新后的图片。
最后,输出p2n中每一张图片即可,并用imadjust适当增加对比度。
for i=1:70 img=p2n(i,:,:); img=reshape(img,[120,160]); img=imadjust(img,[],[],1.2); imshow(img,[]); pause(0.1); end
最终结果:
完整代码:
test4.m:(和上一篇中的最后一个代码相同,Coarse2不列,唯一区别就是加了两个三维矩阵存储图像)
close all; clear all; clc; img_dir = dir('./monkeydog/*.bmp'); [m n]=size(img_dir); p1=uint8(zeros(m-1,120,160)); p2=uint8(zeros(m-1,120,160)); 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); p1(i,:,:)=img2; p2(i,:,:)=v2; pause(0.01) %imgname=strcat('C:\Users\71405\Desktop\回收站\计算机视觉\2018.6.12\output\img_',num2str(i),'.jpg'); %saveas(gcf,imgname); end save
save :保存变量空间matlab.mat
之后在别的.m中导入即可
test42.m:平滑
load matlab.mat p2n=p2;%存储平滑后的图像矩阵 for i=1:70 img=p2(i,:,:); img=reshape(img,[120,160]); %边缘分割 BW= edge(img,'sobel'); %区域填充 [m n]=size(BW); for a=1:m start=0; endi=0; for b=1:n if BW(a,b)==1 start=b; break; end end for b=n:-1:1 if BW(a,b)==1 endi=b; break; end end if start~=0 &&endi~=0 && endi-start<=30 for b=start:endi BW(a,b)=1; end end end %求这个区域内点到边缘的最短距离(八个方向到边缘最短距离) for a=1:m for b=1:n if BW(a,b)==1 r=mindis(BW,a,b,m,n); %当前点的像素值等于三分之一(本身加上一帧和下一帧的r内点的像素值/log(颜色距离*物理距离)之和) if i==1 %第一帧只和下一帧平滑 sum=0; for c=1:m for d=1:n if sqrt((a-c)^2+(b-d)^2)<=r sum=sum+p2(i+1,c,d)/log(double(abs(p2(i,a,b)-p2(i+1,c,d))*sqrt((a-c)^2+(b-d)^2))); end end end p2n(i,a,b)=(p2(i,a,b)+sum)/2; elseif i==70 %和上一帧下一帧平滑 sum=0; for c=1:m for d=1:n if sqrt((a-c)^2+(b-d)^2)<=r sum=sum+p2(i-1,c,d)/log(double(abs(p2(i,a,b)-p2(i-1,c,d))*sqrt((a-c)^2+(b-d)^2))); end end end p2n(i,a,b)=(p2(i,a,b)+sum)/2; else %最后一帧只和上一帧平滑 sum1=0; sum2=0; for c=1:m for d=1:n if sqrt((a-c)^2+(b-d)^2)<=r sum1=sum1+p2(i+1,c,d)/log(double(abs(p2(i,a,b)-p2(i+1,c,d))*sqrt((a-c)^2+(b-d)^2))); end end end for c=1:m for d=1:n if sqrt((a-c)^2+(b-d)^2)<=r sum2=sum2+p2(i-1,c,d)/log(double(abs(p2(i,a,b)-p2(i-1,c,d))*sqrt((a-c)^2+(b-d)^2))); end end end p2n(i,a,b)=(p2(i,a,b)+sum1+sum2)/3; end end end end end save function r=mindis(BW,x,y,m,n) disi=zeros(1,8);%存放八个方向的最短距离 dist=[0,-1;-1,-1;-1,0;-1,1;0,1;1,1;1,0;1,-1];%方向 左-上-右-下 for i=1:8 dx=x; dy=y; while dx>0 && dx<=m && dy>0 && dy<=n && BW(dx,dy)==1 if rem(i,2)==1 disi(i)=disi(i)+1; else disi(i)=disi(i)+sqrt(2); end dx=dx+dist(i,1); dy=dy+dist(i,2); end r=min(disi); end end
test43.m:显示图像
load matlab.mat for i=1:70 img=p2n(i,:,:); img=reshape(img,[120,160]); img=imadjust(img,[],[],1.2); imshow(img,[]); pause(0.1); imgname=strcat('C:\Users\71405\Desktop\回收站\计算机视觉\2018.6.12\outputend\img_',num2str(i),'.jpg'); saveas(gcf,imgname); end