光场1.0——非聚焦型光场相机

本文概要

本文讲主要从光场硬件结构设计以及软件处理方式的层面来介绍一下光场的相关内容,关于光场的优势和具体应用点并不在本文的主要范围内。

光场1.0

1. 结构原理说明

首先来介绍一下光场相机,那么什么是光场相机呢,光场相机经历了两代的发展,首先我们来介绍一下一代光场相机的主要结构及内容,以下简称“光场1.0”。接下来,让我们回到2005年2月,重温以下光场相机刚被发明出来的那篇论文——Light Field Photography with a Hand-held Plenoptic Camera ,该论文第一次提出了光场相机的概念,该论文提到的相机概念示意图如下图所示:

 该相机由三部分组成:主镜头、微透镜阵列和对应的CCD(即上图中的Photosensor)。其中MLA(microlens array)放置在主透镜的成像面上(注意是成像面,不是焦平面,这也是很多初学者经常混淆的一个概念),CCD放置在对应的MLA的焦平面上。相机的这种布置有哪些优点呢?它又是如何做到可以记录光线的方向信息的呢?为了便于说明,我在图上添加了一些标记便于后续说明:1,2,3表示三条从物面发出的光线;4表示如果把ccd挪到mla的位置三条光线相交的像素点,5,6,7表示ccd在当前位置上面的三个像素点。

我们从上图可以看出:物面的Subject在Main lens的后面呈的是一个实像,假如我们把CCD放在对应的MLA的位置,那么上图中的subject发出的三条光线是不是就交互在了对应的ccd的一个像素4上,这样子通过这个像素4就无法分辨到底是三条光线的哪一条了,也就是一句常说的:传统相机成像是积分成像,可以说是三条光线的信息积分相加最终才是该点的像素的采集到的信息。

如果是把ccd后移到焦距位置,那么会有什么样的效果呢,5,6,7三个像素点分别代表交互在实像面位置的三条光线1,2,3的信息,这样子是不是就还原出了交互在4点的不同方向的光线信息,这就是一种在二维平面捕获光线的三维信息的方法。

但是难道不会出现8那个位置的光线也打到4对应的子透镜后面的像素区域造成混乱么,当然会啦,但是如果控制好对应的数值孔径匹配就行,该论文也提到了这一点内容如下图所示:

 主透镜有对应的通光口径,只要保证主透镜的通光孔径正确就可以实现上图的数值孔径匹配的效果,即每个宏像素(指的是上图的每一个小圆形的大的像素块)之间既不重叠,又刚好相切。数值孔径匹配的规则为:

\frac{D}{L}=\frac{d}{f}

其中:D为主透镜的通光孔径(再直白点叫主透镜的直径),L表示主透镜和MLA的距离(又叫做像距,因为MLA放在主透镜的像面位置。!!!此处千万注意,L不一定是焦距,很多人经常犯得一个错误!!!),d为mla的小透镜的直径,f为小透镜的焦距。

2. 算法处理

接下来我将给大家介绍一下一些图像预处理和五维光场函数处理相关的内容。我们先来找一个光场相机捕获的原始图像吧,这里我们可以访问斯坦福大学的光场相机拍摄的数据集,数据集链接:斯坦福光场数据集主页链接

Step1:

 Step2:

Step3:

 单击可以下载对应的Raw Data,文件比较大,打开后可以看到利用上述的结构拍摄到的原始光场图像(下左),放大后可以看到每一个对应的宏像素(下右)。

 接下来我将告诉大家如何处理这个原始光场图像,提取出对应的五维光场函数。首先我们要确定一下对应的图像参数:7574*5264的图像。接下来先放代码,然后具体讲解代码的含义(个人水平有限,代码仅供参考),此处仅提供部分核心代码。

main.py

def test_StanfordLF():'''加载并处理斯坦福大学的光场数据集'''lytroRawImagePath = 'flowers_plants_14_eslf.png'if os.path.exists(lytroRawImagePath) is False:print('start to download light field png...')toolsImageProcess.request_download('http://lightfields.stanford.edu/images/flowers_plants/raw/flowers_plants_1_eslf.png','', lytroRawImagePath)print('png download successfully. ')print('start to load Stanford Lytro Light Field Archive image {}'.format(lytroRawImagePath))t = time.time()       # load time about 20sLF = toolsImageProcess.LFReadRawImage(lytroRawImagePath)print("Stanford Lytro Light Field Archive image load successfully, time cost: {}s".format(time.time() - t))toolsImageProcess.LFSaveAllSubViewImages(LF, "SubView Images", "")

toolsImageProcess.py

'''
根据对应的子孔径图像重构光场原始图片
参数:LF 五维光场函数
返回值:LF_Raw 原始的光场采集图像
'''
def LFReadRawImage(imgPath, width=None, height=None):if os.path.exists(imgPath) is False:return NoneLF_Raw = np.array(Image.open(imgPath))imgShape = LF_Raw.shapeif width is None or height is None:maxCD = maxCommonDivisor(imgShape[0], imgShape[1])uRange = int(imgShape[0] / maxCD)vRange = int(imgShape[1] / maxCD)else:maxCD = imgShape[0]/widthif maxCD == imgShape[1]/height:uRange = widthvRange = heightmaxCD = int(maxCD)else:print("data check faild, process finished. ")return NoneLF = np.zeros((maxCD, maxCD, uRange, vRange, imgShape[2]))print("light field data dimension: LF({},{},{},{},{})".format(maxCD, maxCD, uRange, vRange,imgShape[2]))totalSubViewCount = maxCD*maxCDstart = time.time()  # 下载开始时间for x in range(maxCD):for y in range(maxCD):print('\rloading process: {:.2f}%'.format((x * maxCD + y)*100/totalSubViewCount), end=' ')for u in range(uRange):for v in range(vRange):LF[x, y, u, v, :] = LF_Raw[u*maxCD+x, v*maxCD+y, :]print('\rloading process: 100.00%')print('the 4D light field load successfully, time cost: %.2fs' % (time.time() - start))  #输出下载用时时间return LF.astype(np.uint8)
def LFSaveAllSubViewImages(LF, dir, dir_name):# 首先判断 LF 数据类型,如果是 float 类型需要预处理LFShape = LF.shapetotalSubViewCount = LFShape[0]*LFShape[1]path_save = os.path.join(dir, dir_name)if dir != "" and os.path.exists(dir) is False:os.mkdir(dir)if os.path.exists(path_save) is False:os.mkdir(path_save)for i in range(LFShape[0]):for j in range(LFShape[1]):img = LF[i, j, :, :, :]# plt.subplot(LFShape[2], LFShape[3], i*LFShape[2]+j+1)# plt.imshow(img)cv2.imwrite(os.path.join(path_save, "{}_{:0>2d}_{:0>2d}.png".format(dir_name, i, j)), img)print('\rprocess progress: {}/{} image'.format(i*LFShape[1]+j+1, totalSubViewCount), end=' ')print('\nall sub view images has been saved to {} successfully. '.format(path_save))
'''
参数:url: 下载的链接path: 下载的文件存放路径filename: 下载的文件名# 可以可视化的动态显示下载进度,便于使用
'''
def request_download(url, path, filename):if path!='' and (not os.path.exists(path)):  # 看是否有该文件夹,没有则创建文件夹os.mkdir(path)start = time.time() #下载开始时间response = requests.get(url, stream=True) #stream=True必须写上size = 0    #初始化已下载大小chunk_size = 1024  # 每次下载的数据大小content_size = int(response.headers['content-length'])  # 下载文件总大小try:if response.status_code == 200:   #判断是否响应成功print('Start download,[File size]:{size:.2f} MB'.format(size = content_size / chunk_size /1024))   #开始下载,显示下载文件大小filepath = os.path.join(path, filename)with open(filepath, 'wb') as file:   #显示进度条for data in response.iter_content(chunk_size = chunk_size):file.write(data)size +=len(data)print('\r'+'[下载进度]:%s%.2f%%' % ('>'*int(size*50/ content_size), float(size / content_size * 100)) ,end=' ')end = time.time()   #下载结束时间print('\nDownload completed!,times: %.2f秒' % (end - start))  #输出下载用时时间except:print('download error! ')

部分代码的逻辑说明:

LFReadRawImage:

由于所有宏像素的长宽是相等的(圆形和方形的光阑必相等,其他形状目前没见过,不太可能),所以首先是如果不清楚图像解码的光场的LF(x,y,u,v)参数会首先计算图像长宽的最大公约数,以最大公约数作为对应的u和v的值,上述斯坦福大学的光场数据格式为LF(14,14,376,541,4)。

正常的运行结果(控制台输出):

start to download light field png...
Start download,[File size]:178.75 MB
[下载进度]:>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>100.00% 
Download completed!,times: 60.19秒
png download successfully. 
start to load Stanford Lytro Light Field Archive image flowers_plants_14_eslf.png
light field data dimension: LF(14,14,376,541,4)
loading process: 100.00%
the 4D light field load successfully, time cost: 32.53s
Stanford Lytro Light Field Archive image load successfully, time cost: 35.881481885910034s
process progress: 196/196 image 
all sub view images has been saved to SubView Images\ successfully. 

结果输出的多视角图像效果(采用gif录制了一下不同图像之间连续变化的效果): 

现在已经拿到了五维光场函数,后续的许多操作例如EPI和重聚焦等操作就可以通过对LF操作来实现,本文讨论重心不在光场1.0,因此此内容此处不做过多赘述。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/14999.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SPEC CPU 2006 在 CentOS 5.0 x86_64 古老系统测试

下载镜像 CentOS 2 3 4 5 6 等历史老版本下载地址 国内镜像地址_hkNaruto的博客-CSDN博客 下载CentOS 5.0 1-7 ISO文件 注意:尝试过下载DVD版本,速度太慢了。还是通过国内镜像下载这几个iso快。 安装虚拟机 VirtualBox 挂载第一个iso,启动…

突破数据边界,开启探索之旅!隐语开源Meetup一周年专场7月22日上海见

小伙伴们,📢「隐语开源一周年 Meetup 」即将来袭!🎉在一周年 Meetup 上,不仅会对隐语 1.0 版本进行详解,还有新鲜出炉的隐语 MVP 部署体验包,让你秒变高手!更有机会与隐私计算行业的…

DAY37:贪心算法(四)跳跃游戏+跳跃游戏Ⅱ

文章目录 55.跳跃游戏思路完整版总结 45.跳跃游戏Ⅱ思路完整版为什么next覆盖到了终点可以直接break,不用加上最后一步逻辑梳理 总结 55.跳跃游戏 给定一个非负整数数组 nums ,你最初位于数组的 第一个下标 。 数组中的每个元素代表你在该位置可以跳跃…

【LeetCode周赛】2022上半年题目精选集——贪心

文章目录 2136. 全部开花的最早一天(贪心)⭐⭐⭐⭐⭐思路代码语法解析:Integer[] id IntStream.range(0, plantTime.length).boxed().toArray(Integer[]::new); 2141. 同时运行 N 台电脑的最长时间(贪心)⭐⭐⭐⭐⭐解…

【大数据实战电商推荐系统】概述版

文章目录 第1章 项目体系框架设计(说明书)第2章 工具环境搭建(说明书)第3章 项目创建并初始化业务数据3.1 IDEA创建Maven项目(略)3.2 数据加载准备(说明书)3.3 数据初始化到MongoDB …

Flink DataStream之Connect合并流

新建类 package test01;import org.apache.flink.configuration.Configuration; import org.apache.flink.streaming.api.datastream.ConnectedStreams; import org.apache.flink.streaming.api.datastream.DataStreamSource; import org.apache.flink.streaming.api.datastre…

UE4 如何设置玩家Character的两个位置和角度之间的切换

问题:玩家Character的角度不能直接去设置其中的Camera角度,因为Camera的角度是由鼠标X/Y移动增量决定的,同时把Camera的角度传给PlayController中的PlayCameraManneger,PlayCameraManneger是所有Pawn类型的Camera视口总管&#xf…

数据库练习

数据库练习 建立三张表,以及表中的联系 由于学生表中存在外键,所以我们需要先创建课程表和班级表 课程表 mysql> create table course(-> course_id int primary key auto_increment comment 课程编号,-> course_name varchar(10) not null…

SpringCloud Alibaba 面试题 微服务相关

Spring Cloud Alibaba 介绍 Spring Cloud Alibaba 与微服务架构是一种分布式架构,它将复杂的应用系统拆分成若干可独立部署、可重复使用的微服务,以实现模块化,可靠性,可部署性的服务架构。 Spring Cloud Alibaba 集成了阿里巴巴…

MySQL数据库对象与数据备份和还原详解

目录 一、视图 1. 什么是视图 2. 视图与数据表的区别 3. 视图的优点 4. 创建视图 二、索引 1. 什么是索引 2. 为什么要使用索引 3. 索引优缺点 4. 何时不使用索引 5. 索引何时失效 6. 索引分类 6.1 普通索引 6.2 唯一索引 6.3 主键索引 6.4 组合索引 三、数据的…

【深度学习】AIGC ,ControlNet 论文,原理,训练,部署,实战,教程(三)

文章目录 源码资源下载Python环境试玩controlnet训练数据准备选一个Stable diffusion模型开始训练 第一篇:https://qq742971636.blog.csdn.net/article/details/131531168 源码资源下载 目前 ControlNet 1.1 还在建设,本文这里使用源码 https://github…

MyBatis 与 Hibernate 有哪些不同?

ORM框架的选择与适用场景 MyBatis和Hibernate都是Java领域中流行的面向关系型数据库的ORM(对象关系映射)框架。它们的共同目标是简化开发人员操作数据库的工作,提供便捷的持久化操作。然而,两者在设计理念和适用场景上有所不同。…