在通常的摄像头中,不同的resolution对应不同的帧率。想要提高帧率就要考虑是否需要缩小视野(FOV)。
若不希望视野缩小,就需要减少resolution。
常用的减少resolution的两种方式是下采样:Skipping and Binning。
Skipping
通过选取视野中的像素点,抽取指定像素点来降低分辨率。在Skipping模式中,并不会对所有行列的像素点进行采样,这样才能获取非原始分辨率的图像(降低的分辨率图像)。行列数据是成对读取的。
Binning
Binning是将相邻像元(相同颜色)感应的电荷加在一起,以一个像素的模式读出。在环境光照低的情况下,提高摄像头表现力。需要配合Skipping一起使用。
想更加了解可以看连接:https://zhuanlan.zhihu.com/p/583948933
下面我们使用Python模拟实现上述两种算法。
首先,由于CMOS的两种降采样在raw域去做的,所以我们现将jpg转为灰度形式保存图片,我们这里采用1920*1080分辨率的图像来模拟。
转灰度并且保存
# -*-coding:utf-8-*-
import cv2
image=cv2.imread('test.jpeg')
image=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
cv2.imwrite('gray.jpeg',image)
Binning实现
def binning(path):
bayer = cv2.imread(path, cv2.IMREAD_GRAYSCALE).astype(np.float32)
print('img', bayer.shape)
Nimg = np.zeros((bayer.shape[0] // 2, bayer.shape[1] // 2, 1))
print('Nimg', Nimg.shape)
for i in range(Nimg.shape[0]):#540
for j in range(Nimg.shape[1]): #960
if i % 2 == 0 and j % 2 == 0:
Nimg[i, j] = (bayer[i * 2, j * 2] + bayer[i * 2, j * 2 + 2] + bayer[i * 2 + 2, j * 2]
+ bayer[i * 2 + 2, j * 2 + 2]) / 4.
elif i % 2 == 0 and j % 2 == 1:
Nimg[i, j] = (bayer[i * 2, j * 2 - 1] + bayer[i * 2, j * 2 + 1] + bayer[i * 2 + 1, j * 2 - 1] + bayer[
i * 2 + 1, j * 2 + 1]) / 4.
elif i % 2 == 1 and j % 2 == 0:
Nimg[i, j] = (bayer[i * 2 - 1, j * 2] + bayer[i * 2 - 1, j * 2 + 2] + bayer[i * 2 - 1, j * 2] + bayer[
i * 2 + 1, j * 2 + 2]) / 4.
elif i % 2 == 1 and j % 2 == 1:
Nimg[i, j] = (bayer[i * 2 - 1, j * 2 - 1] + bayer[i * 2 - 1, j * 2 + 1] + bayer[
i * 2 - 1, j * 2 - 1] + bayer[i * 2 + 1, j * 2 + 1]) / 4.
else:
print("Bining ERROR!")
cv2.imwrite('binning.jpg', Nimg)
print('Bining Done!')
Skipping实现
def skiping(path):
img = cv2.imread(path, cv2.IMREAD_GRAYSCALE).astype(np.float32)
Nimg = np.zeros((img.shape[0] // 2, img.shape[1] // 2, 1))
for i in range(Nimg.shape[0]): # 540
for j in range(Nimg.shape[1]): # 960
for k in range(Nimg.shape[2]):
if i % 2 == 0 and j % 2 == 0:
Nimg[i, j] = img[i * 2, j * 2]
elif i % 2 == 0 and j % 2 == 1:
Nimg[i, j] = img[i * 2, j * 2 - 1]
elif i % 2 == 1 and j % 2 == 0:
Nimg[i, j] = img[i * 2 - 1, j * 2]
elif i % 2 == 1 and j % 2 == 1:
Nimg[i, j] = img[i * 2 - 1, j * 2 - 1]
else:
print(i, j)
print("ERROR")
cv2.imwrite('skiping.jpg', Nimg)
print('skiping Done!')
整体代码如下:
# -*-coding:utf-8-*-
import cv2
import numpy as np
def binning(path):
bayer = cv2.imread(path, cv2.IMREAD_GRAYSCALE).astype(np.float32)
print('img', bayer.shape)
Nimg = np.zeros((bayer.shape[0] // 2, bayer.shape[1] // 2, 1))
print('Nimg', Nimg.shape)
for i in range(Nimg.shape[0]):
for j in range(Nimg.shape[1]): # 960
if i % 2 == 0 and j % 2 == 0:
Nimg[i, j] = (bayer[i * 2, j * 2] + bayer[i * 2, j * 2 + 2] + bayer[i * 2 + 2, j * 2]
+ bayer[i * 2 + 2, j * 2 + 2]) / 4.
elif i % 2 == 0 and j % 2 == 1:
Nimg[i, j] = (bayer[i * 2, j * 2 - 1] + bayer[i * 2, j * 2 + 1] + bayer[i * 2 + 1, j * 2 - 1] + bayer[
i * 2 + 1, j * 2 + 1]) / 4.
elif i % 2 == 1 and j % 2 == 0:
Nimg[i, j] = (bayer[i * 2 - 1, j * 2] + bayer[i * 2 - 1, j * 2 + 2] + bayer[i * 2 - 1, j * 2] + bayer[
i * 2 + 1, j * 2 + 2]) / 4.
elif i % 2 == 1 and j % 2 == 1:
Nimg[i, j] = (bayer[i * 2 - 1, j * 2 - 1] + bayer[i * 2 - 1, j * 2 + 1] + bayer[
i * 2 - 1, j * 2 - 1] + bayer[i * 2 + 1, j * 2 + 1]) / 4.
else:
print("Bining ERROR!")
cv2.imwrite('binning.jpg', Nimg)
print('Bining Done!')
def skiping(path):
img = cv2.imread(path, cv2.IMREAD_GRAYSCALE).astype(np.float32)
Nimg = np.zeros((img.shape[0] // 2, img.shape[1] // 2, 1))
for i in range(Nimg.shape[0]): # 540
for j in range(Nimg.shape[1]): # 960
for k in range(Nimg.shape[2]):
if i % 2 == 0 and j % 2 == 0:
Nimg[i, j] = img[i * 2, j * 2]
elif i % 2 == 0 and j % 2 == 1:
Nimg[i, j] = img[i * 2, j * 2 - 1]
elif i % 2 == 1 and j % 2 == 0:
Nimg[i, j] = img[i * 2 - 1, j * 2]
elif i % 2 == 1 and j % 2 == 1:
Nimg[i, j] = img[i * 2 - 1, j * 2 - 1]
else:
print(i, j)
print("ERROR")
cv2.imwrite('skiping.jpg', Nimg)
print('skiping Done!')
def test(path):
binning(path)
skiping(path)
if __name__ == "__main__":
test('gray.jpeg')
原图19201080:
灰度图19201080:
以下两种是两种降采样结果,分辨率是1920/2,1080/2,从肉眼看并无明显区别。