网上有写的很好的光场相机模拟程序,由于没有任何基础,所以以小白的思维理解。
首先附上GitHub网址:https://github.com/muzichao/Light-field-camera
此程序使用近轴光学成像原理,实现相机的程序模拟。
传统相机可简化为下图(a);
光场相机简化可以分为透镜+微透镜阵列。如下图(b)所示:
|
距透镜d的物体,在透镜后v处成像,若物体离透镜的距离远大于焦距,则适用于近轴光学。
第一部分代码
addpath(genpath('/image'));
addpath(genpath('/image2'));
addpath(genpath('/data'));
addpath(genpath('/dataRGB'));
addpath(genpath('/len_sub'));
clearall
上述函数括号中内容 表示路径
genpath(file)表示目标文件夹下的所有文件夹
addpath(genpath(file))将目标文件夹下所有文件夹都包括进调用函数的目录
这样表述,每个功能都能单独存放在一个子文件夹里,便于维护。matlab无分层概念,所以将其他子文件夹的数据添加到主程序目录须在程序前添加上述代码。
(参考https://blog.csdn.net/zhangyake1989/article/details/78580414)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%物体信息%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
[obj,obj1,d,d2,object_num,error]=len_object();
if error == 1
clearall
break;
elseif object_num==1
clear obj1
end
我们定位select_object()函数,在./len_sub文件夹中:
function [obj,obj2,d,d2,object_num,error]=select_object()
%2012 12 20 by lichao
%用于选择场景
%用法:[obj,obj1,d,d2,object_num,error]=select_object()
%obj 场景1
%obj2 场景2
%d 场景1距离
%d2 场景2距离
%object_num 场景数量
%error 结束选择
error=0;
obj=[];
obj2=[];
d=0;
d2=0;
object_num=menu('请选择物体个数:','一个物体','两个物体','结束');
if object_num ==1
object=menu('请选择成像面:','lena256','lena512','Baboon512','Peppers512','circle_card','lena101','一点','结束');
if object<=7
obj=select_obj(object);
d=250;%物距
else
error=1;
return;
end
elseif object_num==2
object2=menu('请选择成像面:','A和B','C和D','结束');
if object2<=2
[obj,obj2]=select_2obj(object2);
d=250;
d2=400;
else
error=1;
return;
end
elseif object_num==3
error=1;
return;
end
menu函数的作用是生成UI界面目录
m = menu(‘title’,‘n1’,‘n2’,…,‘nn’) 函数显示以字符串变量‘title’为标题的菜单,选项为字符串变量:‘n1’,…,返回所输入的值到m
上述函数是两个选择:首先选择物体个数,其次选择个数后选择成像面。
所以第一段函数的意思就是如果按了结束,就清除所有;如果物体数目一个,则清除obj1
第二部分代码
%%%%%%%%%%%%%%%%%相机参数信息%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%可调参数%%%%%%%%%%%%%%%%%%%%%%%%%%%
v=16;%像距,默认16
N_line=81;%对主透镜的离散化,每个点在主透镜有多少光线,默认81条
d_m=18;%物体是透镜的多少倍
error =ensure_par(v,N_line,d_m,object_num,d,d2);
if error ==1
clearall
dis('请重新调整参数!');
break;
end
fuction error =ensure_par(v,N_line,d_m,object_num,d,d2)
%用于确认参数信息是否准确
%error=ensure_par[v,N_line,d_m,object_num,d,d2]
%v 微透镜位置
%N_line 主透镜采样率
%d_m 场景放大倍数
%object_num 场景数
%d 场景1的距离
%d2 场景2的距离
error =0;
if nargin<=5
error=1;
disp('请输入足够的参数:')
return;
end
par_menu=menu('确认下列数据是否正确:',['微透镜距离:v=',num2str(v)],['场景个数:object_num=',num2str(object_num)],...
['场景1的距离:d=',num2str(d)],['场景2的距离:d2=',num2str(d2)],['主透镜采样率:N_line=',num2str(N_line)],['场景放大倍数:d_m=',num2str(d_m)],'否','是');
if par_menu<=7
error=1;
return;
else
disp(['可调参数(微透镜位置):v=',num2str(v)]);
disp(['可调参数(主透镜采样率):N_line=',num2str(N_line)]);
disp(['可调参数(场景放大倍数):d_m=',num2str(d_m)]);
disp(['可调参数(场景1距离):d=',num2str(d)]);
disp(['可调参数(场景2距离):d2=',num2str(d2)]);
end
ensure_par函数用来确认输入的参数信息是否准确仍然是程序用户UI界面,让用户判断是否是自己选择的参数。若不准确,退出,若准确,则进行下一步。
这样,第二段代码解说完毕了。
第三段代码
D=4; %直径
F=16; %焦距 f-num=4
lens_d=0.02; %微透镜直径
sen_N=20; %每个微透镜后传感器个数
lens_f=lens_d*F/D; %微透镜焦距
lens_v=lens_f+v; %传感器位置
sen_N_total=micr_N*sen_N; %传感器总个数
sen_d=lens_d/sen_N; %传感器直径
if mod(sen_N_total,2)==0
sen_N_total=sen_N_total+1;
end
im_max=zeros(3,1); %分别保存R,G,B的最大值,以便转换为uint8型,以节省内存
第三段代码是设置固定参数
D=4; %直径
F=16;%焦距 f-num=4
lens_d=0.02;%微透镜直径
sen_N=20;%每个微透镜后传感器个数
lens_f=lens_d*F/D;%微透镜焦距
lens_v=lens_f+v; %传感器位置
micr_N=ceil(D/lens_d);%微透镜个数
sen_N_total=micr_N*sen_N;%传感器总个数
sen_d=lens_d/sen_N;%传感器直径
if mod(sen_N_total,2)==0
sen_N_total=sen_N_total+1;
end
im_max=zeros(3,1);%分别保存R,G,B的最大值,以便转换为uint8型,以节省内存
第四段代码
tic
for k=1:3
if object_num==1
fprintf_RGB(k);%字符串打印
obje=obj(:,:,k);
im=LF_sim(obje,d,d_m,D,N_line,F,v,lens_d,lens_f,sen_N);
im_max(k)=max(max(max(max(im))));
elseif object_num==2
fprintf_RGB(k); %字符串打印
obje=obj(:,:,k);
im=LF_sim(obje,d,d_m,D,N_line,F,v,lens_d,lens_f,sen_N);
obje=obj1(:,:,k);
im=im+LF_sim(obje,d2,d_m,D,N_line,F,v,lens_d,lens_f,sen_N);
im_max(k)=max(max(max(max(im))));
end
save (sprintf('./dataRGB/im_d_%d_v_%d_Nline_%d_%d.mat',d,v,N_line,k),'im');
end
t=toc;
fprintf(['\n模拟光场传输时间为:t=',num2str(t),'s\n']);
第五段代码
%% 画出原始图像
figure
if object_num==1
imshow(uint8(obj),[]);title('obj——场景')
elseif object_num==2
subplot(1,2,1),imshow(uint8(obj),[]);title('obj——第一个场景');
subplot(1,2,2),imshow(uint8(obj1),[]);title('obj1——第二个场景');
end
fprintf('\n已画出场景图像!\n');
第六段代码
%% 画出传感器成像
clear im
im_RGB=reshape4to2_im(d,v,N_line,micr_N,sen_N,im_max);
figure
warning off all
imshow(im_RGB,[]);title('传感器图像im');
warning on all
imwrite(im_RGB,sprintf('./dataRGB/im_d_%d_v_%d_Nline_%d_RGB.jpg',d,v,N_line));%将微透镜图像保存为im_RGB.jpg
fprintf('\n已画出传感器图像!\n');
第七段代码
%% 原始数据求和重构后的图像
im_micr=sum_4D_im(d,v,N_line,micr_N);
max_im_micr=max(max(max(im_micr)));
im_micr=uint8(im_micr/max_im_micr*255);
figure
imshow(im_micr,[]);title('原始数据求和重构:');
fprintf('\n已画出原始数据重构图像!\n');
disp('The end!');