【硬核摄影2.0】用线性CCD器件制作扫描相机 您所在的位置:网站首页 全自动线性ccd扫描仪如何使用 【硬核摄影2.0】用线性CCD器件制作扫描相机

【硬核摄影2.0】用线性CCD器件制作扫描相机

2024-03-02 20:57| 来源: 网络整理| 查看: 265

本文参考资料:[1] (Strongly Recommend!) Fundamentals and Experiments of Line Scan Camera: http://www.elm-chan.org/works/lcam/report.html[2] 线阵 CCD 的使用方法(以 TCD1304 为例): https://zzi.io/?p=1091

工程地址:https://github.com/divertingPan/Line_Scan_Camera

原文地址:https://divertingpan.github.io/post/line_scan_camera

前言 Overview

这篇是接续【硬核摄影】给火车拍个全身照和光流法应用——自适应检测视频火车速度的内容。但是实则整个工程和前作关系又不是那么密切,只能算是精神续作。

实际上,这篇2.0的内容是之前做软件层面的视频扫描代码的精神鼻祖。这个扫描相机的原项目[1]是2011年左右设计的,老潘在大概2018年看到的这个并且尝试复现(失败),但一直对这个项目留有念想。因为已经大致了解了原理,所以就用视频录像做了这个相机的模拟版。结果在2021年的时候突然得知,国内PCB厂商居然开始免费打样,于是老潘决定重启这个项目,告别繁杂的飞线,拆解原来的洞洞板,直接上PCB。

老潘在原来的设计基础上做了一些小改动。本篇主要是为了记录复现过程中趟过的无数大小坑,以及对本项目的改进的一些指南。

本项目完全开源在github上,包括电路,PCB,硬件代码,各种资料等。

老潘不是专业搞硬件开发的,所以肯定很多地方说不明白,希望各位能给予指导或者纠正。

一些效果展示:

这个是手持平移扫过桌上的静物,因为手抖所以会有变形。

这是架在路边拍摄,因为光圈开到最大,对焦在中央车道,近景就会失焦模糊。

一个完整的扫描结果,没有调整长宽比例的原始图像。

火车虽迟但到,可惜这个相机想要准确取景对焦十分考验手感,导致出片率不高。

线性 vs 二维

这种一维相机也能拍照的原理在前面篇章里已经介绍了,如果理解了线性扫描的原理,这个相机的原理是一模一样的。只是利用线性的CCD直接从拍摄(或者说录制视频)这个地方就已经做好了固定位置-连续取帧-逐帧拼接成图这么个过程。

这时候会有人问:既然能用录像机直接录像之后用软件拼图,那毫无必要用线性CCD来做这个?这时候我们应该考虑一下两种方法的优劣,来选择到底用哪种方法。

线性CCD器件的分辨率可以轻松做到10000×n,即CCD的单帧覆盖像素可以做到很高,这点在当前的二维传感器上很难实现(即使强如GFX 100可以做到最长边11648×8736分辨率,但是成本爆炸,而且还会带来第二点问题) 线性CCD只有1维的数据,在高速采集中对外围电路要求更低(GFX 100和一个线性CCD,同时设计每秒1000帧的采样速度,难度差异显而易见)。有人会说:二维器件的采样率限制可以利用二维平面弥补(即,11648×8736×1帧,采集图像范围等同于11648×1×8736帧),但是前文已经实验证明,利用视频的窄窗来模拟线性扫描的前提是,开窗的尺寸不能太大,否则会出现透视效应。因此,二维CMOS或者CCD器件会有大量数据浪费。 承接上条,利用线性CCD可以节约存储空间和IO开销。 使用CCD的缺点是,由于存在采样率上限,因此速度超过帧速率上限的物体会发生形变,且丢失的帧细节无法弥补,通过二维器件的录像和后处理,可以利用窄窗弥补。(这里的速度-帧率-窗尺寸关系在前作也有推导,线性CCD设定窗宽度固定为1即可) 尽管如此,窄窗仍然会带来以下问题,且很难通过简单的后期手法修正: 开窗的窗宽度和目标运动速度紧密相关,并且分正负。 带有透视的物体,无法统一开窗宽度。 对于变速的物体,对开窗宽度非常敏感。 物体受到固定位置的光影反射会产生条纹干扰。

如图所示:

而以上问题在窗宽度等于1像素,即直接使用线性CCD捕捉图像时,可以消除这些缺陷。例如下图所示,拍摄的汽车是属于双向车道的,被白色横线挡住的大卡车是自右向左行驶的,白线前面的车是自左向右行驶的。但是由于每帧像素宽度为1,因此帧排列顺序不会出现上图问题1的效应,只会影响到物体的镜像翻转与否(注意卡车上的字)。

至于物体发生的拉伸形变,可以通过ps缩放简单修正。将运动速度慢而造成影像拉长的物体可以压回正常尺寸,没有信息损失;而运动过快造成的影像缩短,仅使用插值法拉回原本比例则会带来信息损失。

传感器简介 基本原理

整个项目最重要的部分就是传感器了,这里使用的是TCD32D线性单色传感器,具有1024个像素单元,最高捕捉速度可以达到每秒大约2000帧。其实目前的科技已经有最多一万个像元,可以达到更高的分辨率,还支持RGB彩色模式,不过这些东西的原理基本都相通。想要TCD132D输出东西,首先需要给它一些信号,如图所示:

这里SH是控制CCD采集光信号,控制积累由光强度转化成的电信号(即积分)所用的时间长度,遇到一个SH下降沿就使得CCD开始把目前积累的电信号往外搬运。因此可以发现,帧率越大,给每个像元的积分时间就越短,相当于感光度变低。在此同时,\phiϕCCD控制搬运的节奏,这个信号变一次,就让下一个像素的信号出来,直到走完所有的像元。但是这上面并不是所有像元都能捕捉到光信号,只有中间部分的1024个可以,其他的只会打酱油。\phiϕM是总时钟,根据图里的比例可以看到,\phiϕCCD变一次,就要对应\phiϕM变4次,就是说\phiϕM的频率需要是\phiϕCCD的4倍。

而这个传感器能接受的这些信号的频率范围如下表前三行所示。可以看到\phiϕM的频率确实是\phiϕCCD的4倍。而\phiϕCCD每变一次就会输出一个数据,即一个\phiϕCCD周期会有2个数据输出,所以数据速率是\phiϕCCD的两倍。一帧有1024个数据,每秒2M个数据即每秒2k个帧,所以这个传感器的极速就是每秒2千帧左右。

这个TCD132D输出的是模拟信号(一个连续区间的电压值),所以需要一个ADC来把电压值转化到0-255之间的数码值。这也就是说,我们需要一个能够支持每秒转化2M个数据的ADC才行。ADC1173可以达到15MHz。而驱动他的方法也很简单,使用一个时钟,在每次时钟下降沿的时候就会把当前的数据采集转化。

Arduino相关实验

老潘早些时候用arduino尝试着去驱动TCD132D以及ADC1173,奈何没有示波器,没法查看输出信号是不是符合期望值,arduino mega上面又不带DMC,数据来不及依次捕捉下来。而且对于如何同步列与列之间的数据,我也没什么头绪。这里示范一下使用arduino+ADC1173来把这个CCD当做光线传感器使用的一个例子吧(无奈)。

好在mega上面有很多定时器可以使用,这些定时器被我拿来当做各个时钟了。配置定时器又涉及到了寄存器操作,我的浅见是寄存器就是一堆功能按钮,按下他就会产生相应的功能,这些功能排列组合出来就成了神奇或者诡异的运行姿态。。。使用对应的寄存器的方法就是通过设置某个变量的名字(一般用到的单片机都会把每个寄存器做好名称和底层地址的对应文件给大家)等于一个二进制的数字,这个二进制数字的每一位都对应了这个寄存器里的一个按钮,1就是按下,0就是不按。通过纷杂迷人眼的来回切换这些按钮,这个机器就运转起来了。

但是一般来说,直接设置某个寄存器就等于某一个数字可能不太妥当。因为有时候我们只想改变这里面好几个按钮中的一个按钮,不想动其他的按钮,如果每次都这样手动的一次设置一大排按钮的状态,容易搞错。所以有些时候可以利用逻辑符号来指定对某一个按钮做操作。

// 让DDRB的第0位和第1位变成1 这里|是按位或 DDRB |= (00000001 | 00000010); // 让ADCSRA的ADPS0:2变成0 这里的&是按位与 ADCSRA &= ~((1


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有