本文共 3452 字,大约阅读时间需要 11 分钟。
本文使用多曝光对应区块内的熵值大小来分配不同大小的权重,最后线性合成为新区块,从而实现使得曝光合成图片具备最多的LDR细节,代替由于硬件或者软件限制而无法实现的HDR效果。
#include算法效果如下: 左上:block大小为2525个像素,熵值为15.1996 右上:block大小为2020个像素,熵值为15.1069 左下:block大小为100100个像素,熵值为15.3519 右上:block大小为250250个像素,熵值为15.5222#include using namespace cv;using namespace std;#define BLOCK 50//求熵 函数float entropy(Mat m){ float sum = 0; float histogram[3][256] = { 0};//3个通道,每个通道256个像素级别。 int one; int n = m.rows * m.cols; for (int k = 0; k < 3; k++) { for (int i = 0; i < m.rows; i++) { for (int j = 0; j < m.cols; j++) { one = int (m.at (i, j)[k]); histogram[k][one]++; } } } //开始计算图像熵 for (int i = 0; i < 3; i++) { for (int j = 0; j < 256; j++) { histogram[i][j] /= n; if (histogram[i][j] != 0)sum += (-histogram[i][j]) * log(histogram[i][j]); } } return sum;}//选取熵最大的图像块最大的权重输出Mat entropy_max(Mat a,Mat b,Mat c){ float ans_a = entropy(a),ans_b = entropy(b), ans_c = entropy(c); if ((ans_a > ans_b && ans_a > ans_c)) { if (ans_b>ans_c)return 0.6 * a + 0.3 * b + 0.1 * c; else return 0.6 * a + 0.3 * c + 0.1 * b; } if ((ans_b > ans_a && ans_b > ans_c)) { if (ans_a > ans_c)return 0.6 * b + 0.3 * a + 0.1 * c; else return 0.6 * b + 0.3 * c + 0.1 * a; } if ((ans_c > ans_b && ans_c > ans_a)) { if (ans_a > ans_b)return 0.6 * c + 0.3 * a + 0.1 * b; else return 0.6 * c + 0.3 * b + 0.1 * a; }}//融合函数Mat fusion(Mat src_OE,Mat src_UE, Mat src_ME,int block){ //创建一个Mat类型out_ROI Mat out_ROI_ue,out_ROI_oe, out_ROI_me; //输出暂存块。 out_ROI_ue = Mat(block, block, CV_8UC3); out_ROI_oe = Mat(block, block, CV_8UC3); out_ROI_me = Mat(block, block, CV_8UC3); Mat out_ROI;//计算出的熵比较高的那一块 out_ROI = Mat(block, block, CV_8UC3); Mat out;//创建对象 out = src_ME;//输出对象 //创建每次循环的处理区域work_ROI,并初始化坐标极其宽度高度 Rect work_ROI; work_ROI.x = 0;//矩形左上角横坐标 work_ROI.y = 0;//矩形左上角纵坐标 work_ROI.width = block;//矩形宽为block work_ROI.height = block;//矩形高为block //原图像ROI位置以及大小Rect类型储存 for (int j = 0; j < src_OE.cols / block; j++)//外层循环循环原图列数/block 次 { for (int i = 0; i < src_OE.rows / block; i++) //内层循环原图行数/block 次 { //rect_ROI坐标转换到下一个矩形区块。 work_ROI.x = block * i;//工作区域向后移动block个像素 work_ROI.y = block * j;//工作区域向后移动block个像素 //比较三张图的熵的最大值 out_ROI_oe = src_OE(work_ROI); out_ROI_ue = src_UE(work_ROI); out_ROI_me = src_ME(work_ROI); out_ROI = entropy_max(out_ROI_ue, out_ROI_oe,out_ROI_me);//把熵最大的这一块赋给out_ROI //把这一块填充到out的这一个部分里面 out_ROI.copyTo(out(work_ROI)); } } return out;}int main(){ Mat src_OE = imread("C:\\Users\\hl\\Desktop\\oe2.jpg", IMREAD_COLOR); Mat src_UE = imread("C:\\Users\\hl\\Desktop\\ue2.jpg", IMREAD_COLOR); Mat src_ME = imread("C:\\Users\\hl\\Desktop\\me2.jpg", IMREAD_COLOR); //Mat src = imread("C:\\Users\\hl\\Desktop\\CESHI2.jpg", IMREAD_COLOR); imshow("过曝光",src_OE); imshow("欠曝光",src_UE); imshow("正常曝光",src_ME); Mat oe, ue, me;// ceshi; cvtColor(src_OE, oe, COLOR_BGR2Lab); cvtColor(src_OE, ue, COLOR_BGR2Lab); cvtColor(src_OE, me, COLOR_BGR2Lab); //cvtColor(src, ceshi, COLOR_BGR2Lab); //熵最大融合 Mat out; out = fusion(src_OE, src_UE, src_ME,BLOCK); imshow("曝光融合后", out); //cvtColor(out, ceshi , COLOR_BGR2Lab); //观察总熵值 cout << "过曝总熵:" << entropy(oe) << endl; cout << "欠曝总熵:" << entropy(ue) << endl; cout << "正常曝光总熵:" << entropy(me) << endl; cout << "曝光合成总熵:" << entropy(out) << endl; //cout << "测试熵:" << entropy(ceshi) << endl; waitKey(); return 0;
虽说肉眼可见最多细节信息,但是这个引发的块状效应依然无法容忍,之后会持续更新对于该算法的改进。敬请期待。
转载地址:http://aamen.baihongyu.com/