You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

818 lines
25 KiB
C++

6 months ago
#ifdef _WIN32
#define _USE_MATH_DEFINES
#include <math.h>
#else
#include <cmath>
#endif
9 months ago
#include <iostream>
3 years ago
#include <opencv2/opencv.hpp> // all opencv header
#include "hdrplus/finish.h"
3 years ago
#include "hdrplus/utility.h"
6 months ago
#ifdef _WIN32
#include <stdint.h>
#endif
3 years ago
6 months ago
#ifdef __ANDROID__
#define DBG_OUTPUT_ROOT "/sdcard/com.xypower.mpapp/tmp/"
#else
#define DBG_OUTPUT_ROOT ""
#endif
3 years ago
// #include <type_traits>
3 years ago
namespace hdrplus
{
6 months ago
cv::Mat convert16bit2_8bit_(cv::Mat ans) {
if (ans.type() == CV_16UC3) {
cv::MatIterator_<cv::Vec3w> it, end;
for (it = ans.begin<cv::Vec3w>(), end = ans.end<cv::Vec3w>(); it != end; ++it)
{
// std::cout<<sizeof (*it)[0] <<std::endl;
(*it)[0] *= (255.0 / USHRT_MAX);
(*it)[1] *= (255.0 / USHRT_MAX);
(*it)[2] *= (255.0 / USHRT_MAX);
}
ans.convertTo(ans, CV_8UC3);
}
else if (ans.type() == CV_16UC1) {
uint16_t* ptr = (uint16_t*)ans.data;
int end = ans.rows*ans.cols;
for (int i = 0; i < end; i++) {
*(ptr + i) *= (255.0 / USHRT_MAX);
}
ans.convertTo(ans, CV_8UC1);
}
else {
std::cout << "Unsupported Data Type" << std::endl;
}
return ans;
}
cv::Mat convert8bit2_16bit_(cv::Mat ans) {
if (ans.type() == CV_8UC3) {
ans.convertTo(ans, CV_16UC3);
cv::MatIterator_<cv::Vec3w> it, end;
for (it = ans.begin<cv::Vec3w>(), end = ans.end<cv::Vec3w>(); it != end; ++it)
{
// std::cout<<sizeof (*it)[0] <<std::endl;
(*it)[0] *= (65535.0 / 255.0);
(*it)[1] *= (65535.0 / 255.0);
(*it)[2] *= (65535.0 / 255.0);
}
}
else if (ans.type() == CV_8UC1) {
ans.convertTo(ans, CV_16UC1);
uint16_t* ptr = (uint16_t*)ans.data;
int end = ans.rows*ans.cols;
for (int i = 0; i < end; i++) {
*(ptr + i) *= (65535.0 / 255.0);
}
}
else {
std::cout << "Unsupported Data Type" << std::endl;
}
return ans;
}
cv::Mat convert8bit2_12bit_(cv::Mat ans) {
// cv::Mat ans(I);
cv::MatIterator_<cv::Vec3w> it, end;
for (it = ans.begin<cv::Vec3w>(), end = ans.end<cv::Vec3w>(); it != end; ++it)
{
// std::cout<<sizeof (*it)[0] <<std::endl;
(*it)[0] *= (2048.0 / 255.0);
(*it)[1] *= (2048.0 / 255.0);
(*it)[2] *= (2048.0 / 255.0);
}
ans.convertTo(ans, CV_16UC3);
return ans;
}
uint16_t uGammaCompress_1pix(float x, float threshold, float gainMin, float gainMax, float exponent) {
// Normalize pixel val
x /= USHRT_MAX;
// check the val against the threshold
if (x <= threshold) {
x = gainMin * x;
}
else {
x = gainMax * pow(x, exponent) - gainMax + 1;
}
// clip
if (x < 0) {
x = 0;
}
else {
if (x > 1) {
x = 1;
}
}
x *= USHRT_MAX;
return (uint16_t)x;
}
uint16_t uGammaDecompress_1pix(float x, float threshold, float gainMin, float gainMax, float exponent) {
// Normalize pixel val
x /= 65535.0;
// check the val against the threshold
if (x <= threshold) {
x = x / gainMin;
}
else {
x = pow((x + gainMax - 1) / gainMax, exponent);
}
// clip
if (x < 0) {
x = 0;
}
else {
if (x > 1) {
x = 1;
}
}
x *= 65535;
return (uint16_t)x;
}
cv::Mat uGammaCompress_(cv::Mat m, float threshold, float gainMin, float gainMax, float exponent) {
if (m.type() == CV_16UC3) {
cv::MatIterator_<cv::Vec3w> it, end;
for (it = m.begin<cv::Vec3w>(), end = m.end<cv::Vec3w>(); it != end; ++it)
{
(*it)[0] = uGammaCompress_1pix((*it)[0], threshold, gainMin, gainMax, exponent);
(*it)[1] = uGammaCompress_1pix((*it)[1], threshold, gainMin, gainMax, exponent);
(*it)[2] = uGammaCompress_1pix((*it)[2], threshold, gainMin, gainMax, exponent);
}
}
else if (m.type() == CV_16UC1) {
uint16_t* ptr = (uint16_t*)m.data;
int end = m.rows*m.cols;
for (int i = 0; i < end; i++) {
*(ptr + i) = uGammaCompress_1pix(*(ptr + i), threshold, gainMin, gainMax, exponent);
}
}
else {
std::cout << "Unsupported Data Type" << std::endl;
}
return m;
}
cv::Mat uGammaDecompress_(cv::Mat m, float threshold, float gainMin, float gainMax, float exponent) {
if (m.type() == CV_16UC3) {
cv::MatIterator_<cv::Vec3w> it, end;
for (it = m.begin<cv::Vec3w>(), end = m.end<cv::Vec3w>(); it != end; ++it)
{
(*it)[0] = uGammaDecompress_1pix((*it)[0], threshold, gainMin, gainMax, exponent);
(*it)[1] = uGammaDecompress_1pix((*it)[1], threshold, gainMin, gainMax, exponent);
(*it)[2] = uGammaDecompress_1pix((*it)[2], threshold, gainMin, gainMax, exponent);
}
}
else if (m.type() == CV_16UC1) {
uint16_t* ptr = (uint16_t*)m.data;
int end = m.rows*m.cols;
for (int i = 0; i < end; i++) {
*(ptr + i) = uGammaDecompress_1pix(*(ptr + i), threshold, gainMin, gainMax, exponent);
}
}
else {
std::cout << "Unsupported Data Type" << std::endl;
}
return m;
}
cv::Mat gammasRGB(cv::Mat img, bool mode) {
if (mode) {// compress
return uGammaCompress_(img, 0.0031308, 12.92, 1.055, 1. / 2.4);
}
else { // decompress
return uGammaDecompress_(img, 0.04045, 12.92, 1.055, 2.4);
}
}
void copy_mat_16U_2(uint16_t* ptr_A, cv::Mat B)
6 months ago
{
6 months ago
// uint16_t* ptr_A = (uint16_t*)A.data;
uint16_t* ptr_B = (uint16_t*)B.data;
for (int r = 0; r < B.rows; r++) {
for (int c = 0; c < B.cols; c++) {
*(ptr_A + r * B.cols + c) = *(ptr_B + r * B.cols + c);
}
}
}
cv::Mat mean_(cv::Mat img) {
// initialize processedImg
int H = img.rows;
int W = img.cols;
cv::Mat processedImg = cv::Mat(H, W, CV_16UC1);
uint16_t* ptr = (uint16_t*)processedImg.data;
// traverse img
int idx = 0;
cv::MatIterator_<cv::Vec3w> it, end;
for (it = img.begin<cv::Vec3w>(), end = img.end<cv::Vec3w>(); it != end; ++it)
{
uint32_t tmp = (*it)[0] + (*it)[1] + (*it)[2];
uint16_t avg_val = tmp / 3;
*(ptr + idx) = avg_val;
idx++;
}
return processedImg;
}
double getMean(cv::Mat img) {
uint16_t* ptr = (uint16_t*)img.data;
int max_idx = img.rows*img.cols*img.channels();
double sum = 0;
for (int i = 0; i < max_idx; i++) {
sum += *(ptr + i);
}
sum /= max_idx;
sum /= USHRT_MAX;
return sum;
}
cv::Mat matMultiply_scalar(cv::Mat img, float gain) {
uint16_t* ptr = (uint16_t*)img.data;
int max_idx = img.rows*img.cols*img.channels();
for (int i = 0; i < max_idx; i++) {
double tmp = *(ptr + i)*gain;
if (tmp < 0) {
*(ptr + i) = 0;
}
else if (tmp > USHRT_MAX) {
*(ptr + i) = USHRT_MAX;
}
else {
*(ptr + i) = (uint16_t)tmp;
}
}
return img;
}
double getSaturated(cv::Mat img, double threshold) {
threshold *= USHRT_MAX;
double count = 0;
uint16_t* ptr = (uint16_t*)img.data;
int max_idx = img.rows*img.cols*img.channels();
for (int i = 0; i < max_idx; i++) {
if (*(ptr + i) > threshold) {
count++;
}
}
return count / (double)max_idx;
}
cv::Mat meanGain_(cv::Mat img, int gain) {
if (img.channels() != 3) {
std::cout << "unsupport img type in meanGain_()" << std::endl;
return cv::Mat();
}
else { // RGB img
int H = img.rows;
int W = img.cols;
cv::Mat processedImg = cv::Mat(H, W, CV_16UC1);
uint16_t* ptr = (uint16_t*)processedImg.data;
int idx = 0;
cv::MatIterator_<cv::Vec3w> it, end;
for (it = img.begin<cv::Vec3w>(), end = img.end<cv::Vec3w>(); it != end; ++it)
{
double sum = 0;
// R
double tmp = (*it)[0] * gain;
if (tmp < 0) tmp = 0;
if (tmp > USHRT_MAX) tmp = USHRT_MAX;
sum += tmp;
// G
tmp = (*it)[1] * gain;
if (tmp < 0) tmp = 0;
if (tmp > USHRT_MAX) tmp = USHRT_MAX;
sum += tmp;
// B
tmp = (*it)[2] * gain;
if (tmp < 0) tmp = 0;
if (tmp > USHRT_MAX) tmp = USHRT_MAX;
sum += tmp;
// put into processedImg
uint16_t avg_val = sum / 3;
*(ptr + idx) = avg_val;
idx++;
}
return processedImg;
}
}
cv::Mat applyScaling_(cv::Mat mergedImage, cv::Mat shortGray, cv::Mat fusedGray) {
cv::Mat result = mergedImage.clone();
uint16_t* ptr_shortg = (uint16_t*)shortGray.data;
uint16_t* ptr_fusedg = (uint16_t*)fusedGray.data;
int count = 0;
cv::MatIterator_<cv::Vec3w> it, end;
for (it = result.begin<cv::Vec3w>(), end = result.end<cv::Vec3w>(); it != end; ++it)
{
double s = 1;
if (*(ptr_shortg + count) != 0) {
s = *(ptr_fusedg + count);
s /= *(ptr_shortg + count);
}
for (int c = 0; c < mergedImage.channels(); c++) {
double tmp = (*it)[c] * s;
if (tmp < 0) {
(*it)[c] = 0;
}
else if (tmp > USHRT_MAX) {
(*it)[c] = USHRT_MAX;
}
else {
(*it)[c] = tmp;
}
}
}
return result;
}
void localToneMap(cv::Mat& mergedImage, Options options, cv::Mat& shortg,
cv::Mat& longg, cv::Mat& fusedg, int& gain) {
std::cout << "HDR Tone Mapping..." << std::endl;
// # Work with grayscale images
cv::Mat shortGray = rgb_2_gray<uint16_t, uint16_t, CV_16U>(mergedImage); //mean_(mergedImage);
std::cout << "--- Compute grayscale image" << std::endl;
// compute gain
gain = 0;
if (options.ltmGain == -1) {
double dsFactor = 25;
int down_height = round(shortGray.rows / dsFactor);
int down_width = round(shortGray.cols / dsFactor);
cv::Mat shortS;
cv::resize(shortGray, shortS, cv::Size(down_height, down_width), cv::INTER_LINEAR);
shortS = shortS.reshape(1, 1);
bool bestGain = false;
double compression = 1.0;
double saturated = 0.0;
cv::Mat shortSg = gammasRGB(shortS.clone(), true);
double sSMean = getMean(shortSg);
while ((compression < 1.9 && saturated < .95) || ((!bestGain) && (compression < 6) && (gain < 30) && (saturated < 0.33))) {
gain += 2;
cv::Mat longSg = gammasRGB(shortS.clone()*gain, true);
double lSMean = getMean(longSg);
compression = lSMean / sSMean;
bestGain = lSMean > (1 - sSMean) / 2; // only works if burst underexposed
saturated = getSaturated(longSg, 0.95);
if (options.verbose == 4) {
}
}
}
else {
if (options.ltmGain > 0) {
gain = options.ltmGain;
}
}
std::cout << "--- Compute gain" << std::endl;
// create a synthetic long exposure
cv::Mat longGray = meanGain_(mergedImage.clone(), gain);
std::cout << "--- Synthetic long expo" << std::endl;
// apply gamma correction to both
longg = gammasRGB(longGray.clone(), true);
shortg = gammasRGB(shortGray.clone(), true);
std::cout << "--- Apply Gamma correction" << std::endl;
// perform tone mapping by exposure fusion in grayscale
cv::Ptr<cv::MergeMertens> mergeMertens = cv::createMergeMertens();
std::cout << "--- Create Mertens" << std::endl;
// hack: cv2 mergeMertens expects inputs between 0 and 255
// but the result is scaled between 0 and 1 (some values can actually be greater than 1!)
std::vector<cv::Mat> src_expos;
src_expos.push_back(convert16bit2_8bit_(shortg.clone()));
src_expos.push_back(convert16bit2_8bit_(longg.clone()));
mergeMertens->process(src_expos, fusedg);
fusedg = fusedg * USHRT_MAX;
fusedg.convertTo(fusedg, CV_16UC1);
std::cout << "--- Apply Mertens" << std::endl;
// undo gamma correction
cv::Mat fusedGray = gammasRGB(fusedg.clone(), false);
// cv::imwrite("fusedg_degamma.png", fusedGray);
std::cout << "--- Un-apply Gamma correction" << std::endl;
// scale each RGB channel of the short exposure accordingly
mergedImage = applyScaling_(mergedImage, shortGray, fusedGray);
std::cout << "--- Scale channels" << std::endl;
}
uint16_t enhanceContrast_1pix(uint16_t pix_val, double gain) {
double x = pix_val;
x /= USHRT_MAX;
x = x - gain * sin(2 * M_PI*x);
if (x < 0) {
x = 0;
}
else if (x > 1) {
x = 1;
}
uint16_t result = x * USHRT_MAX;
return result;
}
cv::Mat enhanceContrast(cv::Mat image, Options options) {
if (options.gtmContrast >= 0 && options.gtmContrast <= 1) {
uint16_t* ptr = (uint16_t*)image.data;
int end = image.rows*image.cols*image.channels();
for (int idx = 0; idx < end; idx++) {
*(ptr + idx) = enhanceContrast_1pix(*(ptr + idx), options.gtmContrast);
}
}
else {
std::cout << "GTM ignored, expected a contrast enhancement ratio between 0 and 1" << std::endl;
}
return image;
}
cv::Mat distL1_(cv::Mat X, cv::Mat Y) {
int end_x = X.rows*X.cols*X.channels();
int end_y = Y.rows*Y.cols*Y.channels();
cv::Mat result = cv::Mat(X.rows, X.cols, X.type());
if (end_x == end_y) {
uint16_t* ptr_x = (uint16_t*)X.data;
uint16_t* ptr_y = (uint16_t*)Y.data;
uint16_t* ptr_r = (uint16_t*)result.data;
for (int i = 0; i < end_x; i++) {
if (*(ptr_x + i) < *(ptr_y + i)) {
*(ptr_r + i) = *(ptr_y + i) - *(ptr_x + i);
}
else {
*(ptr_r + i) = *(ptr_x + i) - *(ptr_y + i);
}
}
}
else {
std::cout << "Mat size not match. distL1_ failed!" << std::endl;
}
return result;
}
cv::Mat sharpenTriple_(cv::Mat image,
cv::Mat blur0, cv::Mat low0, float th0, float k0,
cv::Mat blur1, cv::Mat low1, float th1, float k1,
cv::Mat blur2, cv::Mat low2, float th2, float k2) {
// create result mat
cv::Mat result = cv::Mat(image.rows, image.cols, image.type());
// initialize iteraters
uint16_t* ptr_r = (uint16_t*)result.data;
uint16_t* ptr_img = (uint16_t*)image.data;
uint16_t* ptr_blur0 = (uint16_t*)blur0.data;
uint16_t* ptr_low0 = (uint16_t*)low0.data;
uint16_t* ptr_blur1 = (uint16_t*)blur1.data;
uint16_t* ptr_low1 = (uint16_t*)low1.data;
uint16_t* ptr_blur2 = (uint16_t*)blur2.data;
uint16_t* ptr_low2 = (uint16_t*)low2.data;
int n_channels = image.channels();
int end = image.rows*image.cols*n_channels;
// traverse Image
for (int idx = 0; idx < end; idx++) {
double r, r0, r1, r2;
double x = *(ptr_img + idx);
double l0 = *(ptr_low0 + idx) / (double)USHRT_MAX;
double l1 = *(ptr_low1 + idx) / (double)USHRT_MAX;
double l2 = *(ptr_low2 + idx) / (double)USHRT_MAX;
double b0 = *(ptr_blur0 + idx);
double b1 = *(ptr_blur1 + idx);
double b2 = *(ptr_blur2 + idx);
r0 = l0 < th0 ? x : x + k0 * (x - b0);
r1 = l1 < th1 ? x : x + k1 * (x - b1);
r2 = l2 < th2 ? x : x + k2 * (x - b2);
r = (r0 + r1 + r2) / 3.0;
if (r < 0) r = 0;
if (r > USHRT_MAX) r = USHRT_MAX;
*(ptr_r + idx) = (uint16_t)r;
}
return result;
}
cv::Mat sharpenTriple(cv::Mat image, Tuning tuning, Options options) {
// sharpen the image using unsharp masking
std::vector<float> amounts = tuning.sharpenAmount;
std::vector<float> sigmas = tuning.sharpenSigma;
std::vector<float> thresholds = tuning.sharpenThreshold;
// Compute all Gaussian blur
cv::Mat blur0, blur1, blur2;
cv::GaussianBlur(image, blur0, cv::Size(0, 0), sigmas[0]);
cv::GaussianBlur(image, blur1, cv::Size(0, 0), sigmas[1]);
cv::GaussianBlur(image, blur2, cv::Size(0, 0), sigmas[2]);
std::cout << " --- gaussian blur" << std::endl;
// cv::imwrite("blur2.png", blur2);
// Compute all low contrast images
cv::Mat low0 = distL1_(blur0, image);
cv::Mat low1 = distL1_(blur1, image);
cv::Mat low2 = distL1_(blur2, image);
std::cout << " --- low contrast" << std::endl;
// cv::imwrite("low2.png", low2);
// Compute the triple sharpen
cv::Mat sharpImage = sharpenTriple_(image,
blur0, low0, thresholds[0], amounts[0],
blur1, low1, thresholds[1], amounts[1],
blur2, low2, thresholds[2], amounts[2]);
std::cout << " --- sharpen" << std::endl;
return sharpImage;
}
void copy_mat_16U_3(uint16_t* ptr_A, cv::Mat B) {
// uint16_t* ptr_A = (uint16_t*)A.data;
uint16_t* ptr_B = (uint16_t*)B.data;
int H = B.rows;
int W = B.cols;
int end = H * W;
for (int i = 0; i < end; i++) {
*(ptr_A + i) = *(ptr_B + i);
}
}
// void copy_mat_16U_3(uint16_t* ptr_A, cv::Mat B){
// // uint16_t* ptr_A = (uint16_t*)A.data;
// uint16_t* ptr_B = (uint16_t*)B.data;
// for(int r = 0; r < B.rows; r++) {
// for(int c = 0; c < B.cols; c++) {
// *(ptr_A+r*B.cols+c) = *(ptr_B+r*B.cols+c);
// }
// }
// }
cv::Mat processMergedMat(cv::Mat mergedImg, int opencv_type) {
cv::Mat m;
6 months ago
#if 0
6 months ago
uint16_t* ptr = (uint16_t*)mergedImg.data;
for (int r = 0; r < mergedImg.rows; r++) {
std::vector<int> dvals;
for (int c = 0; c < mergedImg.cols; c++) {
dvals.push_back(*(ptr + r * mergedImg.cols + c));
}
cv::Mat mline(dvals, true);
cv::transpose(mline, mline);
m.push_back(mline);
}
6 months ago
#endif
6 months ago
int ch = CV_MAT_CN(opencv_type);
m = mergedImg.clone();
m = m.reshape(ch);
m.convertTo(m, opencv_type);
return m;
}
void show20_20(cv::Mat m) {
uint16_t* ptr = (uint16_t*)m.data;
for (int i = 0; i < 20; i++) {
for (int j = 0; j < 20; j++) {
std::cout << *(ptr + i * m.cols + j) << ", ";
}
std::cout << std::endl;
}
}
void writeCSV(std::string filename, cv::Mat m)
{
std::ofstream myfile;
myfile.open(filename.c_str());
myfile << cv::format(m, cv::Formatter::FMT_CSV) << std::endl;
myfile.close();
}
void finish::process(const hdrplus::burst& burst_images, cv::Mat& finalOutputImage) {
// copy mergedBayer to rawReference
std::cout << "finish pipeline start ..." << std::endl;
// save merged Image value
9 months ago
#ifndef HDRPLUS_NO_DETAILED_OUTPUT
6 months ago
writeCSV(DBG_OUTPUT_ROOT "merged.csv", burst_images.merged_bayer_image);
9 months ago
#endif
6 months ago
this->refIdx = burst_images.reference_image_idx;
// this->burstPath = burstPath;
// std::cout<<"processMerged:"<<std::endl;
// show20_20(mergedB);
6 months ago
9 months ago
#ifndef HDRPLUS_NO_DETAILED_OUTPUT
6 months ago
this->mergedBayer = loadFromCSV(DBG_OUTPUT_ROOT "merged.csv", CV_16UC1);
// this->mergedBayer = processMergedMat(mergedB,CV_16UC1);//loadFromCSV("merged.csv", CV_16UC1);
// std::cout<<"processMerged:"<<std::endl;
// show20_20(this->mergedBayer);
// this->mergedBayer = loadFromCSV(DBG_OUTPUT_ROOT "merged.csv", CV_16UC1);
// this->mergedBayer = processMergedMat(burst_images.merged_bayer_image, CV_16UC1);
9 months ago
#else
6 months ago
// this->mergedBayer = loadFromCSV(DBG_OUTPUT_ROOT "merged.csv", CV_16UC1);
this->mergedBayer = processMergedMat(burst_images.merged_bayer_image, CV_16UC1);
9 months ago
// std::cout<<"processMerged:"<<std::endl;
#endif
6 months ago
// std::cout<<"csv:"<<std::endl;
// show20_20(this->mergedBayer);
// load_rawPathList(burstPath);
3 years ago
3 years ago
// read in ref img
6 months ago
// bayer_image* ref = new bayer_image(rawPathList[refIdx]);
bayer_image* ref = new bayer_image(burst_images.bayer_images[burst_images.reference_image_idx]);
cv::Mat processedRefImage = postprocess(ref->libraw_processor, params.rawpyArgs);
3 years ago
6 months ago
std::cout << "size ref: " << processedRefImage.rows << "*" << processedRefImage.cols << std::endl;
6 months ago
// write reference image
9 months ago
#ifndef HDRPLUS_NO_DETAILED_OUTPUT
6 months ago
if (params.flags["writeReferenceImage"]) {
std::cout << "writing reference img ..." << std::endl;
cv::Mat outputImg = convert16bit2_8bit_(processedRefImage.clone());
cv::cvtColor(outputImg, outputImg, cv::COLOR_RGB2BGR);
// cv::imshow("test",processedImage);
cv::imwrite(DBG_OUTPUT_ROOT "processedRef.jpg", outputImg);
// cv::waitKey(0);
}
9 months ago
#endif
3 years ago
6 months ago
// write gamma reference
9 months ago
#ifndef HDRPLUS_NO_DETAILED_OUTPUT
6 months ago
if (params.flags["writeGammaReference"]) {
std::cout << "writing Gamma reference img ..." << std::endl;
cv::Mat outputImg = gammasRGB(processedRefImage.clone(), true);
outputImg = convert16bit2_8bit_(outputImg);
cv::cvtColor(outputImg, outputImg, cv::COLOR_RGB2BGR);
cv::imwrite(DBG_OUTPUT_ROOT "processedRefGamma.jpg", outputImg);
}
9 months ago
#endif
3 years ago
6 months ago
// get the bayer_image of the merged image
// bayer_image* mergedImg = new bayer_image(rawPathList[refIdx]);
bayer_image* mergedImg = new bayer_image(burst_images.bayer_images[this->refIdx]);
mergedImg->libraw_processor->imgdata.rawdata.raw_image = (uint16_t*)this->mergedBayer.data;
// copy_mat_16U_3(mergedImg->libraw_processor->imgdata.rawdata.raw_image,this->mergedBayer);
cv::Mat processedMerge = postprocess(mergedImg->libraw_processor, params.rawpyArgs);
3 years ago
6 months ago
// write merged image
9 months ago
#ifndef HDRPLUS_NO_DETAILED_OUTPUT
6 months ago
if (params.flags["writeMergedImage"]) {
std::cout << "writing Merged img ..." << std::endl;
cv::Mat outputImg = convert16bit2_8bit_(processedMerge.clone());
cv::cvtColor(outputImg, outputImg, cv::COLOR_RGB2BGR);
cv::imwrite(DBG_OUTPUT_ROOT "mergedImg.jpg", outputImg);
}
9 months ago
#endif
3 years ago
6 months ago
// write gamma merged image
9 months ago
#ifndef HDRPLUS_NO_DETAILED_OUTPUT
6 months ago
if (params.flags["writeMergedImage"]) {
std::cout << "writing Gamma Merged img ..." << std::endl;
cv::Mat outputImg = gammasRGB(processedMerge.clone(), true);
outputImg = convert16bit2_8bit_(outputImg);
cv::cvtColor(outputImg, outputImg, cv::COLOR_RGB2BGR);
cv::imwrite(DBG_OUTPUT_ROOT "mergedImgGamma.jpg", outputImg);
}
9 months ago
#endif
3 years ago
6 months ago
// step 5. HDR tone mapping
// processedImage, gain, shortExposure, longExposure, fusedExposure = localToneMap(burstPath, processedImage, options)
int gain;
if (params.options.ltmGain) {
cv::Mat shortExposure, longExposure, fusedExposure;
localToneMap(processedMerge, params.options, shortExposure, longExposure, fusedExposure, gain);
std::cout << "gain=" << gain << std::endl;
9 months ago
#ifndef HDRPLUS_NO_DETAILED_OUTPUT
6 months ago
if (params.flags["writeShortExposure"]) {
std::cout << "writing ShortExposure img ..." << std::endl;
cv::Mat outputImg = convert16bit2_8bit_(shortExposure);
cv::imwrite(DBG_OUTPUT_ROOT "shortg.jpg", outputImg);
}
9 months ago
#endif
#ifndef HDRPLUS_NO_DETAILED_OUTPUT
6 months ago
if (params.flags["writeLongExposure"]) {
std::cout << "writing LongExposure img ..." << std::endl;
cv::Mat outputImg = convert16bit2_8bit_(longExposure);
cv::imwrite(DBG_OUTPUT_ROOT "longg.jpg", outputImg);
}
9 months ago
#endif
#ifndef HDRPLUS_NO_DETAILED_OUTPUT
6 months ago
if (params.flags["writeFusedExposure"]) {
std::cout << "writing FusedExposure img ..." << std::endl;
cv::Mat outputImg = convert16bit2_8bit_(fusedExposure);
cv::imwrite(DBG_OUTPUT_ROOT "fusedg.jpg", outputImg);
}
9 months ago
#endif
#ifndef HDRPLUS_NO_DETAILED_OUTPUT
6 months ago
if (params.flags["writeLTMImage"]) {
std::cout << "writing LTMImage ..." << std::endl;
cv::Mat outputImg = convert16bit2_8bit_(processedMerge.clone());
cv::cvtColor(outputImg, outputImg, cv::COLOR_RGB2BGR);
cv::imwrite(DBG_OUTPUT_ROOT "ltmGain.jpg", outputImg);
}
9 months ago
#endif
#ifndef HDRPLUS_NO_DETAILED_OUTPUT
6 months ago
if (params.flags["writeLTMGamma"]) {
std::cout << "writing LTMImage Gamma ..." << std::endl;
cv::Mat outputImg = gammasRGB(processedMerge.clone(), true);
outputImg = convert16bit2_8bit_(outputImg);
cv::cvtColor(outputImg, outputImg, cv::COLOR_RGB2BGR);
cv::imwrite(DBG_OUTPUT_ROOT "ltmGain_gamma.jpg", outputImg);
}
9 months ago
#endif
6 months ago
}
3 years ago
6 months ago
// step 6 GTM: contrast enhancement / global tone mapping
if (params.options.gtmContrast) {
processedMerge = enhanceContrast(processedMerge, params.options);
std::cout << "STEP 6 -- Apply GTM" << std::endl;
}
3 years ago
6 months ago
// apply the final sRGB gamma curve
processedMerge = gammasRGB(processedMerge.clone(), true);
std::cout << "-- Apply Gamma" << std::endl;
3 years ago
9 months ago
#ifndef HDRPLUS_NO_DETAILED_OUTPUT
6 months ago
if (params.flags["writeGTMImage"]) {
std::cout << "writing GTMImage ..." << std::endl;
cv::Mat outputImg = convert16bit2_8bit_(processedMerge.clone());
cv::cvtColor(outputImg, outputImg, cv::COLOR_RGB2BGR);
9 months ago
6 months ago
cv::imwrite(DBG_OUTPUT_ROOT "GTM_gamma.jpg", outputImg);
}
9 months ago
#endif
3 years ago
6 months ago
// Step 7: sharpen
9 months ago
finalOutputImage = sharpenTriple(processedMerge.clone(), params.tuning, params.options);
6 months ago
cv::Mat& processedImage = finalOutputImage;
9 months ago
#ifndef HDRPLUS_NO_DETAILED_OUTPUT
6 months ago
if (params.flags["writeFinalImage"]) {
std::cout << "writing FinalImage ..." << std::endl;
cv::Mat outputImg = convert16bit2_8bit_(processedImage.clone());
cv::cvtColor(outputImg, outputImg, cv::COLOR_RGB2BGR);
9 months ago
6 months ago
cv::imwrite(DBG_OUTPUT_ROOT "FinalImage.jpg", outputImg);
}
9 months ago
#endif
6 months ago
// write final ref
9 months ago
#ifndef HDRPLUS_NO_DETAILED_OUTPUT
6 months ago
if (params.flags["writeReferenceFinal"]) {
std::cout << "writing Final Ref Image ..." << std::endl;
if (params.options.ltmGain) {
params.options.ltmGain = gain;
}
cv::Mat shortExposureRef, longExposureRef, fusedExposureRef;
localToneMap(processedRefImage, params.options, shortExposureRef, longExposureRef, fusedExposureRef, gain);
if (params.options.gtmContrast) { // contrast enhancement / global tone mapping
processedRefImage = enhanceContrast(processedRefImage, params.options);
}
processedRefImage = gammasRGB(processedRefImage.clone(), true);
// sharpen
processedRefImage = sharpenTriple(processedRefImage.clone(), params.tuning, params.options);
cv::Mat outputImg = convert16bit2_8bit_(processedRefImage.clone());
cv::cvtColor(outputImg, outputImg, cv::COLOR_RGB2BGR);
cv::imwrite(DBG_OUTPUT_ROOT "FinalReference.jpg", outputImg);
}
9 months ago
#endif
6 months ago
// End of finishing
}
void finish::copy_mat_16U(cv::Mat& A, cv::Mat B) {
uint16_t* ptr_A = (uint16_t*)A.data;
uint16_t* ptr_B = (uint16_t*)B.data;
for (int r = 0; r < A.rows; r++) {
for (int c = 0; c < A.cols; c++) {
*(ptr_A + r * A.cols + c) = *(ptr_B + r * B.cols + c);
}
}
}
void finish::copy_rawImg2libraw(std::shared_ptr<LibRaw>& libraw_ptr, cv::Mat B) {
uint16_t* ptr_A = (uint16_t*)libraw_ptr->imgdata.rawdata.raw_image;
uint16_t* ptr_B = (uint16_t*)B.data;
for (int r = 0; r < B.rows; r++) {
for (int c = 0; c < B.cols; c++) {
*(ptr_A + r * B.cols + c) = *(ptr_B + r * B.cols + c);
}
}
}
3 years ago
} // namespace hdrplus