【ISP图像处理】流程概述及经典算法(附python代码)

本文介绍了ISP整体流程,其在相机成像中起关键作用,决定成像质量。还分模块介绍了坏点矫正、黑电平补偿、去噪等功能及对应算法,如均值滤波、灰度世界白平衡算法等,并给出部分算法的Python实现代码,为ISP图像处理提供了全面的技术参考。
该文章已生成可运行项目,

一、ISP整体流程概述

        相机成像的完整链路中,首先,通过设备的光学镜片将光聚焦到传感器上,将光信号转为电信号,然后,通过核心的ISP模块对接收的电信号处理输出可视图像信号,再对图像进行存储和显示。其中,ISP主要功能有噪声去除、坏点去除、去马赛克、白平衡、自动曝光控制等,依赖于ISP模块处理后才能在不同的光学条件下都能较好的还原现场细节,可以说ISP技术在很大程度上决定了摄像机的成像质量。

       一般而言,ISP包含以下子模块:从 sensor 端过来的图像是拜尔图像,经过坏点矫正(dead pixel, DPC),黑电平补偿(black level compensation, BLC),去噪(denoise),镜头矫正(lens shading correction,LSC),白平衡(auto white balance, awb),去马赛克(demosaic),色彩校正(color correction matrix,CCM),HDR/Tone Mapping,gamma矫正,边缘增强(edge enhance,EE)色彩空间变化(color space manipulation, CSM)等输出 YUV( 或者 RGB) 格式的数据, 再通过 I/O 接口传输到 CPU 中处理。

       当然对于一个优秀的ISP处理器,肯定不仅仅局限与上述模块,还会包含其他功能,例如HDR/Tone Mapping等,但本博客聚焦于这些主要模块,其他模块读者可以自行查阅资料进行了解。

二、分模块介绍及对应算法(含代码)

1. 坏点矫正

从传感器制造的角度来看,由于制造过程的不确定性,如粉尘、制造故障、曝光不完全等,一个图像传感器可能会有一定数量的缺陷像素。

一般来讲,坏点分为三类:第一类是死点,即一直表现为最暗值的点;第二类是亮点,即一直表现为最亮值的点:第三类是漂移点,就是变化规律与周围像素明显不同的像素点。由于图像传感器中CFA的应用,每个像素只能得到一种颜色信息,缺失的两种颜色信息需要从周围像素中得到。如果图像中存在坏点的话,那么坏点会随着颜色插补的过程往外扩散,直到影响整幅图像。因此必须在颜色插补之前进行坏点的消除。

坏点校正功能分为两个步骤:首先检测有缺陷的像素,然后是用插值值替换缺陷。

检测是否存在换点通常是通过判断中心点P0和周围像素点之间的插值是否超大于某个预定义好的阈值thres来确定。若为坏点,有两种方式:

一种是计算领域像素均值作为坏点P0的值,即P0 = (P2 + P4 + P5 + P7) / 4

另一种是基于梯度的滤波,首先计算相邻像素在不同方向上的梯度:

dh = |2P0 - P4 - P5|,  dv = |2P0 - P2 - P7|

ddr = |2P0 - P3 - P6|,  ddl = |2P0 - P1 - P8|

计算得到不同方向梯度后,选择最小梯度方向的邻域像素求均值进行插值:

两种方法实现代码如下:

import numpy as np
import cv2

def dpc_mean(img, thres=30):
    img_pad = np.pad(img, (2, 2), 'reflect')
    raw_h, raw_w = img.shape

    dpc_img = np.empty((raw_h, raw_w), np.uint16) 

    # change uint16 to int_, still exists overflow warning  in the following abs calculation
    for x in range(img_pad.shape[0] - 4):
        for y in range(img_pad.shape[1] - 4):

            p0 = img_pad[x + 2, y + 2].astype(int)
            p1 = img_pad[x, y].astype(int)
            p2 = img_pad[x, y + 2].astype(int)
            p3 = img_pad[x, y + 4].astype(int)
            p4 = img_pad[x + 2, y].astype(int)
            p5 = img_pad[x + 2, y + 4].astype(int)
            p6 = img_pad[x + 4, y].astype(int)
            p7 = img_pad[x + 4, y + 2].astype(int)
            p8 = img_pad[x + 4, y + 4].astype(int)

            if (abs(p1 - p0) > thres) and (abs(p2 - p0) > thres) and (abs(p3 - p0) > thres) \
                    and (abs(p4 - p0) > thres) and (abs(p5 - p0) > thres) and (abs(p6 - p0) > thres) \
                    and (abs(p7 - p0) > thres) and (abs(p8 - p0) > thres):
                p0 = (p2 + p4 + p5 + p7) / 4

            dpc_img[x, y] = p0.astype('uint16')
    img = dpc_img
    img = np.clip(img, 0, 1024).astype(np.float32)
    re
本文章已经生成可运行项目
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值