1、什么是图像传感器?
图像传感器是将光信号转换为电信号的设备,图像传感器通过捕捉光子并将其转化为电子信号,从而生成数字图像。它是数码相机、摄像机、智能手机、无人机、自动驾驶汽车以及各种工业和医疗应用的核心组件。
2、图像传感器是如何工作的?
图像传感器的工作原理主要基于光电效应。光子通过镜头进入传感器,并被传感器中的光电二极管吸收,产生电子。电子被收集并转化为电信号,经过放大和处理,最终形成数字图像。
3、常见的图像传感器的种类
常见的图像传感器有CCD(Charge Coupled Device:电荷耦合元件)图像传感器, CMOS(Complementary Metal Oxide Semiconductor:互补金属氧化物半导体)图像传感器,3D ToF(Time of Flight,飞行时间)图像传感器和热敏图像传感器。
3.1 CCD图像传感器
CCD的结构就象一排排输送带上并排放满了小桶,光线就象雨滴撒入各个小桶,每个小桶就是一个像素。按下快门拍照的过程,就是按一定的顺序测量在一个短暂的时间间隔中,小桶中落进了多少“光滴”,然后逐个记录下来并放大为电信号。这个记录的过程式串行工作的,所以早期的CCD数码相机虽然成像质量好,但是集成度受限制,连拍速度没有CMOS传感器的数码相机快。
3.2 CMOS图像传感器
CMOS图像传感器的各个光电二极管都配备有放大器,因此可即时放大电流并一次性转换传输出去。所以具有速度快,功耗低的特点,早期的CMOS图像传感器存在噪点多、感光度低,画质相对差的问题,但伴随技术发展,现在的CMOS传感器可以拍出超越CCD图像传感器的高画质视频与静止图像,在智能手机、数码相机等众多领域,CMOS图像传感器成为了主流。
3.3 3D ToF图像传感器
3D ToF图像传感器是一种基于测量光从传感器发射至目标物体到其返回的时间,从而构建三维图像数据的传感器。这种传感器通过计算光脉冲的飞行时间来确定物体与传感器之间的距离,从而生成三维点云数据。
由于光速达到每秒约30万公里,如果直接测量光的反射时间,在进行细微的距离和图像检测的时候很难分辨出其飞行时间的差别。 所以一般来说ToF传感器会采用间接测量的方法,测量反射光相对于发射光的相位差来获取深度信息。传感器会发射调制过的红外光,并测量从不同距离的不同表面接收到的光的相位差。图中使用了两个接收检测器,第一个检测器的开关相位与发射光相同。会捕获一部分的反射光。而第二个检测接收器的开关相位与发射光相反,反射光也有另外一部分被其捕获,比较两个检测器捕获到的光子量的不同,就可以得到反射光相对于发射光的相位差,从而获得准确的距离信息。
ToF 传感器可以与 RGB 图像结合, 用算法组合 RGB 和深度图像,从而获得包含颜色和深度的场景和观察对象的 3D 信息,这在一些智能应用场景中具有重要作用,例如对汽车内乘客手势的识别。下图中的深度信息以颜色来表示,颜色越靠近红色,表明距离摄像头越近,越靠近蓝色,表明距离越远。
3.4 热敏式图像传感器
热敏式图像传感器(Thermal Image Sensor)也是红外传感器的一种,是利用红外辐射成像原理,通过检测物体发出的热辐射来生成图像的传感器。这种传感器不依赖可见光,而是依靠红外辐射,所以能够在完全黑暗的环境中工作。
由于它是非接触式测量, 可以显示红外热图像,而且可以对运动物体进行测温,它被广泛应用于人流比较密集的地方,如机场,车站的人群体温的检测。
4、图像传感器实验演示
我们来演示使用树莓派RP2040来读取显示图像传感器的数据。实验中使用的是一款CMOS的图像传感器模块,我们将一个小物品放到传感器的上方,可以看到,屏幕中出现了物品的清晰图像。
主控板卡:基于RP2040的带屏调试助手
以下是主程序中对于图像传感器数据的获取代码示例:
# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries
# SPDX-FileCopyrightText: Copyright (c) 2021 Jeff Epler for Adafruit Industries
#
# SPDX-License-Identifier: Unlicense
"""
Capture an image from the camera and display it on a supported LCD.
"""
import time
from displayio import (
Bitmap,
Group,
TileGrid,
FourWire,
release_displays,
ColorConverter,
Colorspace,
)
from adafruit_st7789 import ST7789
import board
import busio
import digitalio
import adafruit_ov2640
release_displays()
# Set up the display (You must customize this block for your display!)
spi = busio.SPI(clock=board.GP2, MOSI=board.GP3)
display_bus = FourWire(spi, command=board.GP1, chip_select=board.GP4, reset=board.GP0,
baudrate = 80_000_000,
polarity = 1,phase = 1)
display = ST7789(display_bus, width=240, height=240, rowstart=80,rotation=90)
display.auto_refresh = False
# Ensure the camera is shut down, so that it releases the SDA/SCL lines,
# then create the configuration I2C bus
# with digitalio.DigitalInOut(board.GP10) as reset:
# reset.switch_to_output(False)
# time.sleep(0.001)
bus = busio.I2C(scl=board.GP13, sda=board.GP12)
# Set up the camera (you must customize this for your board!)
cam = adafruit_ov2640.OV2640(
bus,
data_pins=[
board.GP15,
board.GP16,
board.GP17,
board.GP18,
board.GP19,
board.GP20,
board.GP21,
board.GP22,
], # [16] [org] etc
clock=board.GP14, # [15] [blk]
vsync=board.GP26, # [10] [brn]
href=board.GP27, # [27/o14] [red]
# mclk=board.GP20, # [16/o15]
# shutdown=None,
# reset=board.GP10,
) # [14]
width = display.width
height = display.height
cam.size = adafruit_ov2640.OV2640_SIZE_240X240
cam.colorspace = adafruit_ov2640.OV2640_COLOR_RGB
# cam.test_pattern = True
bitmap = Bitmap(cam.width, cam.height, 65536)
print(width, height, cam.width, cam.height)
if bitmap is None:
raise SystemExit("Could not allocate a bitmap")
g = Group(scale=1, x=(width - cam.width) // 2, y=(height - cam.height) // 2)
tg = TileGrid(
bitmap, pixel_shader=ColorConverter(input_colorspace=Colorspace.RGB565_SWAPPED)
)
g.append(tg)
display.root_group = g
display.auto_refresh = False
while True:
cam.capture(bitmap)
bitmap.dirty()
display.refresh(minimum_frames_per_second=0)