5、曝光补偿
5.1 原理
即使通过几何投影,图像之间可以做到很好的拼接,但如果不同图像之间有不同的曝光程度,那么拼接图像中的重叠部分也会出现明显的边缘,这样就使图像看起来十分不自然。因此,我们还需要对每幅图像进行曝光补偿,来使所有图像具有相同的曝光程度。
目前,常用的曝光补偿方法有增益补偿和分块补偿这两种方法。增益补偿就是为每幅图像赋予一个增益系数,使重叠部分的图像强度相等或相似。它可以利用误差函数来实现:
(83)
式中,gi和gj为图像i和图像j的增益系数,R(i,j)表示图像i和图像j的重叠部分,Ii(ui)表示图像i在重叠部分R(i,j)的强度平均值Iij:
(84)
式中,R、G和B分别表示彩色图像的红、绿和蓝分量的强度值,Nij表示重叠部分R(i,j)的像素数量。
很显然,当g=0时,式83所表示的误差函数为零,也就是最优解,这明显不是我们想要的值;另外为了提高鲁棒性,增益补偿误差函数的经验公式为:
(85)
式中,σN和σg分别表示误差和增益的标准差,σN=10(如果强度范围为0~255),σg=0.1。
式85是增益系数g的一个二次目标函数,该函数可以通过使其导数为0得到闭合形式的解。式85对gi的导数为:
(86)
使该导数为0,并展开成以g1,g2,……,gn为变量的等式:
(87)
e对所有的g求导,这样就建立起了n个如式87一样的线性方程。求解该方程组,则最终得到了n幅图像的n个增益系数g。
第二种曝光补偿方法是分块补偿,它的原理是把图像分割成大小相同的不同块,这样以块为单位进行增益补偿,即每一块都有一个增益系数。该方法的补偿精度更好,并且还可以缓解增益补偿算法的复杂性。块的尺寸大小的经验值为32×32。分块补偿的结果会使拼接图像呈现“块”的形态,因此还需要对每一块的增益系数进行平滑滤波处理,具体来说,对同一幅图像的所有块的增益系数应用分割线性滤波的方法,分割滤波的核为[1/4, 1/2, 1/4]。
5.2 源码
曝光补偿的基类:
class CV_EXPORTS ExposureCompensator
{
public:
virtual ~ExposureCompensator() {}
enum { NO, GAIN, GAIN_BLOCKS };
static Ptr<ExposureCompensator> createDefault(int type);
void feed(const std::vector<Point> &corners, const std::vector<Mat> &images,
const std::vector<Mat> &masks);
virtual void feed(const std::vector<Point> &corners, const std::vector<Mat> &images,
const std::vector<std::pair<Mat,uchar> > &masks) = 0;
virtual void apply(int index, Point corner, Mat &image, const Mat &mask) = 0;
};
ExposureCompensator类中的createDefault函数表示创建曝光补偿器:
Ptr<ExposureCompensator> ExposureCompensator::createDefault(int type)
//type表示曝光补偿的方法
//该函数返回具体曝光补偿方法的函数指针
{
if (type == NO) //表示不进行曝光补偿
return new NoExposureCompensator(); //指向NoExposureCompensator类
if (type == GAIN) //表示应用增益补偿方法进行曝光补偿
return new GainCompensator(); //指向GainCompensator类
if (type == GAIN_BLOCKS) //表示应该分块补偿方法进行曝光补偿
return new BlocksGainCompensator(); //指向BlocksGainCompensator类
//没有其他的曝光补偿算法
CV_Error(CV_StsBadArg, "unsupported exposure compensati