volume = {9},
publisher = {Walter de Gruyter}
}
-@inproceedings{DD02,
- author = {Durand, Fr{\'e}do and Dorsey, Julie},
- title = {Fast bilateral filtering for the display of high-dynamic-range images},
- booktitle = {ACM Transactions on Graphics (TOG)},
- year = {2002},
- pages = {257--266},
- volume = {21},
- number = {3},
- publisher = {ACM},
- url = {https://www.researchgate.net/profile/Julie_Dorsey/publication/220184746_Fast_Bilateral_Filtering_for_the_Display_of_High_-_dynamic_-_range_Images/links/54566b000cf26d5090a95f96/Fast-Bilateral-Filtering-for-the-Display-of-High-dynamic-range-Images.pdf}
-}
@inproceedings{DM03,
author = {Drago, Fr{\'e}d{\'e}ric and Myszkowski, Karol and Annen, Thomas and Chiba, Norishige},
title = {Adaptive logarithmic mapping for displaying high contrast scenes},
@code{.py}
# Tonemap HDR image
-tonemap1 = cv.createTonemapDurand(gamma=2.2)
+tonemap1 = cv.createTonemap(gamma=2.2)
res_debevec = tonemap1.process(hdr_debevec.copy())
-tonemap2 = cv.createTonemapDurand(gamma=1.3)
-res_robertson = tonemap2.process(hdr_robertson.copy())
@endcode
### 4. Merge exposures using Mertens fusion
Exercises
---------
-1. Try all tonemap algorithms: cv::TonemapDrago, cv::TonemapDurand, cv::TonemapMantiuk and cv::TonemapReinhard
+1. Try all tonemap algorithms: cv::TonemapDrago, cv::TonemapMantiuk and cv::TonemapReinhard
2. Try changing the parameters in the HDR calibration and tonemap methods.
formats, so we save it to Radiance image (.hdr). Also all HDR imaging functions return results in
[0, 1] range so we should multiply result by 255.
-You can try other tonemap algorithms: cv::TonemapDrago, cv::TonemapDurand, cv::TonemapMantiuk and cv::TonemapReinhard
+You can try other tonemap algorithms: cv::TonemapDrago, cv::TonemapMantiuk and cv::TonemapReinhard
You can also adjust the parameters in the HDR calibration and tonemap methods for your own photos.
Results
*/
CV_EXPORTS_W Ptr<TonemapDrago> createTonemapDrago(float gamma = 1.0f, float saturation = 1.0f, float bias = 0.85f);
-/** @brief This algorithm decomposes image into two layers: base layer and detail layer using bilateral filter
-and compresses contrast of the base layer thus preserving all the details.
-
-This implementation uses regular bilateral filter from opencv.
-
-Saturation enhancement is possible as in ocvTonemapDrago.
-
-For more information see @cite DD02 .
- */
-class CV_EXPORTS_W TonemapDurand : public Tonemap
-{
-public:
-
- CV_WRAP virtual float getSaturation() const = 0;
- CV_WRAP virtual void setSaturation(float saturation) = 0;
-
- CV_WRAP virtual float getContrast() const = 0;
- CV_WRAP virtual void setContrast(float contrast) = 0;
-
- CV_WRAP virtual float getSigmaSpace() const = 0;
- CV_WRAP virtual void setSigmaSpace(float sigma_space) = 0;
-
- CV_WRAP virtual float getSigmaColor() const = 0;
- CV_WRAP virtual void setSigmaColor(float sigma_color) = 0;
-};
-
-/** @brief Creates TonemapDurand object
-
-@param gamma gamma value for gamma correction. See createTonemap
-@param contrast resulting contrast on logarithmic scale, i. e. log(max / min), where max and min
-are maximum and minimum luminance values of the resulting image.
-@param saturation saturation enhancement value. See createTonemapDrago
-@param sigma_space bilateral filter sigma in color space
-@param sigma_color bilateral filter sigma in coordinate space
- */
-CV_EXPORTS_W Ptr<TonemapDurand>
-createTonemapDurand(float gamma = 1.0f, float contrast = 4.0f, float saturation = 1.0f, float sigma_space = 2.0f, float sigma_color = 2.0f);
/** @brief This is a global tonemapping operator that models human visual system.
return makePtr<TonemapDragoImpl>(gamma, saturation, bias);
}
-class TonemapDurandImpl CV_FINAL : public TonemapDurand
-{
-public:
- TonemapDurandImpl(float _gamma, float _contrast, float _saturation, float _sigma_color, float _sigma_space) :
- name("TonemapDurand"),
- gamma(_gamma),
- contrast(_contrast),
- saturation(_saturation),
- sigma_color(_sigma_color),
- sigma_space(_sigma_space)
- {
- }
-
- void process(InputArray _src, OutputArray _dst) CV_OVERRIDE
- {
- CV_INSTRUMENT_REGION();
-
- Mat src = _src.getMat();
- CV_Assert(!src.empty());
- _dst.create(src.size(), CV_32FC3);
- Mat img = _dst.getMat();
- Ptr<Tonemap> linear = createTonemap(1.0f);
- linear->process(src, img);
-
- Mat gray_img;
- cvtColor(img, gray_img, COLOR_RGB2GRAY);
- Mat log_img;
- log_(gray_img, log_img);
- Mat map_img;
- bilateralFilter(log_img, map_img, -1, sigma_color, sigma_space);
-
- double min, max;
- minMaxLoc(map_img, &min, &max);
- float scale = contrast / static_cast<float>(max - min);
- exp(map_img * (scale - 1.0f) + log_img, map_img);
- log_img.release();
-
- mapLuminance(img, img, gray_img, map_img, saturation);
- pow(img, 1.0f / gamma, img);
- }
-
- float getGamma() const CV_OVERRIDE { return gamma; }
- void setGamma(float val) CV_OVERRIDE { gamma = val; }
-
- float getSaturation() const CV_OVERRIDE { return saturation; }
- void setSaturation(float val) CV_OVERRIDE { saturation = val; }
-
- float getContrast() const CV_OVERRIDE { return contrast; }
- void setContrast(float val) CV_OVERRIDE { contrast = val; }
-
- float getSigmaColor() const CV_OVERRIDE { return sigma_color; }
- void setSigmaColor(float val) CV_OVERRIDE { sigma_color = val; }
-
- float getSigmaSpace() const CV_OVERRIDE { return sigma_space; }
- void setSigmaSpace(float val) CV_OVERRIDE { sigma_space = val; }
-
- void write(FileStorage& fs) const CV_OVERRIDE
- {
- writeFormat(fs);
- fs << "name" << name
- << "gamma" << gamma
- << "contrast" << contrast
- << "sigma_color" << sigma_color
- << "sigma_space" << sigma_space
- << "saturation" << saturation;
- }
-
- void read(const FileNode& fn) CV_OVERRIDE
- {
- FileNode n = fn["name"];
- CV_Assert(n.isString() && String(n) == name);
- gamma = fn["gamma"];
- contrast = fn["contrast"];
- sigma_color = fn["sigma_color"];
- sigma_space = fn["sigma_space"];
- saturation = fn["saturation"];
- }
-
-protected:
- String name;
- float gamma, contrast, saturation, sigma_color, sigma_space;
-};
-
-Ptr<TonemapDurand> createTonemapDurand(float gamma, float contrast, float saturation, float sigma_color, float sigma_space)
-{
- return makePtr<TonemapDurandImpl>(gamma, contrast, saturation, sigma_color, sigma_space);
-}
-
class TonemapReinhardImpl CV_FINAL : public TonemapReinhard
{
public:
result.convertTo(result, CV_8UC3, 255);
checkEqual(result, expected, 3, "Drago");
- Ptr<TonemapDurand> durand = createTonemapDurand(gamma);
- durand->process(img, result);
- loadImage(test_path + "durand.png", expected);
- result.convertTo(result, CV_8UC3, 255);
- checkEqual(result, expected, 3, "Durand");
-
Ptr<TonemapReinhard> reinhard = createTonemapReinhard(gamma);
reinhard->process(img, result);
loadImage(test_path + "reinhard.png", expected);
//! [Tonemap HDR image]
Mat ldr;
- Ptr<TonemapDurand> tonemap = createTonemapDurand(2.2f);
+ Ptr<Tonemap> tonemap = createTonemap(2.2f);
tonemap->process(hdr, ldr);
//! [Tonemap HDR image]
import org.opencv.photo.MergeDebevec;
import org.opencv.photo.MergeMertens;
import org.opencv.photo.Photo;
-import org.opencv.photo.TonemapDurand;
+import org.opencv.photo.Tonemap;
class HDRImaging {
public void loadExposureSeq(String path, List<Mat> images, List<Float> times) {
//! [Tonemap HDR image]
Mat ldr = new Mat();
- TonemapDurand tonemap = Photo.createTonemapDurand(2.2f, 4.0f, 1.0f, 2.0f, 2.0f);
+ Tonemap tonemap = Photo.createTonemap(2.2f);
tonemap.process(hdr, ldr);
//! [Tonemap HDR image]
## [Make HDR image]
## [Tonemap HDR image]
-tonemap = cv.createTonemapDurand(2.2)
+tonemap = cv.createTonemap(2.2)
ldr = tonemap.process(hdr)
## [Tonemap HDR image]