Skip to content

Commit

Permalink
Update brightness tutorial:
Browse files Browse the repository at this point in the history
  - display and save both color and gray results
  - cycle across the different automatic gamma method
  • Loading branch information
s-trinh committed Oct 13, 2024
1 parent 599789f commit bb37bf8
Showing 1 changed file with 146 additions and 74 deletions.
220 changes: 146 additions & 74 deletions tutorial/imgproc/brightness/tutorial-brightness-adjustment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@
#include <iostream>
#include <visp3/core/vpConfig.h>
#include <visp3/core/vpImage.h>
#include <visp3/gui/vpDisplayGDI.h>
#include <visp3/gui/vpDisplayOpenCV.h>
#include <visp3/gui/vpDisplayX.h>
#include <visp3/core/vpIoTools.h>
#include <visp3/gui/vpDisplayFactory.h>
#include <visp3/io/vpImageIo.h>

#if defined(VISP_HAVE_MODULE_IMGPROC)
Expand All @@ -15,14 +14,49 @@
//! [Include]
#endif

#if ((__cplusplus >= 201103L) || (defined(_MSVC_LANG) && (_MSVC_LANG >= 201103L)))
#include <memory>
#endif

namespace
{
#ifdef ENABLE_VISP_NAMESPACE
using namespace VISP_NAMESPACE_NAME;
#endif

void display(vpImage<vpRGBa> &I_display, vpImage<vpRGBa> &I_color_res, const vpImage<vpRGBa> &I_color_adjust,
vpImage<unsigned char> &I_gray_res, vpImage<unsigned char> &I_gray_adjust, vpImage<vpRGBa> &I_gray_display,
const std::string &title, const std::string &filename_color, const std::string &filename_gray,
const std::string &title_2 = "")
{
I_color_res.insert(I_color_adjust, vpImagePoint(0, I_color_adjust.getWidth()));
I_display.insert(I_color_adjust, vpImagePoint(0, I_color_adjust.getWidth()));

I_gray_res.insert(I_gray_adjust, vpImagePoint(0, I_gray_adjust.getWidth()));
vpImageConvert::convert(I_gray_adjust, I_gray_display);
I_display.insert(I_gray_display, vpImagePoint(I_color_adjust.getHeight(), I_color_adjust.getWidth()));

vpImageIo::write(I_color_res, filename_color);
vpImageIo::write(I_gray_res, filename_gray);

vpDisplay::display(I_display);
vpDisplay::displayText(I_display, 20, 20, title, vpColor::red);
if (!title_2.empty()) {
vpDisplay::displayText(I_display, 40, static_cast<unsigned int>(I_color_adjust.getWidth()*0.85),
title_2, vpColor::green);
}
vpDisplay::flush(I_display);
vpDisplay::getClick(I_display);
}
}

int main(int argc, const char **argv)
{
//! [Macro defined]
#if defined(VISP_HAVE_MODULE_IMGPROC) && \
(defined(VISP_HAVE_X11) || defined(VISP_HAVE_GDI) || defined(VISP_HAVE_OPENCV)) && \
(defined(VISP_HAVE_PNG) || defined(VISP_HAVE_OPENCV))
//! [Macro defined]
//!
#if defined(VISP_HAVE_MODULE_IMGPROC) && defined(VISP_HAVE_DISPLAY) && \
(defined(VISP_HAVE_PNG) || defined(VISP_HAVE_OPENCV) || defined(VISP_HAVE_STBIMAGE) || defined(VISP_HAVE_SIMDLIB)) && \
((__cplusplus >= 201103L) || (defined(_MSVC_LANG) && (_MSVC_LANG >= 201103L)))
//! [Macro defined]
#ifdef ENABLE_VISP_NAMESPACE
using namespace VISP_NAMESPACE_NAME;
#endif
Expand All @@ -34,19 +68,24 @@ int main(int argc, const char **argv)
VISP_NAMESPACE_NAME::vpGammaColorHandling colorHandling = VISP_NAMESPACE_NAME::GAMMA_HSV;
int scale = 240, scaleDiv = 3, level = 0, kernelSize = -1;
double dynamic = 3.0;
int scale_display = 2;

for (int i = 1; i < argc; i++) {
if (std::string(argv[i]) == "--input" && i + 1 < argc) {
input_filename = std::string(argv[i + 1]);
++i;
input_filename = std::string(argv[i]);
}
else if (std::string(argv[i]) == "--alpha" && i + 1 < argc) {
alpha = atof(argv[i + 1]);
++i;
alpha = atof(argv[i]);
}
else if (std::string(argv[i]) == "--beta" && i + 1 < argc) {
beta = atof(argv[i + 1]);
++i;
beta = atof(argv[i]);
}
else if (std::string(argv[i]) == "--gamma" && i + 1 < argc) {
gamma = atof(argv[i + 1]);
++i;
gamma = atof(argv[i]);
}
else if ((std::string(argv[i]) == "--gamma-color-handling") && ((i + 1) < argc)) {
++i;
Expand All @@ -57,19 +96,28 @@ int main(int argc, const char **argv)
method = VISP_NAMESPACE_NAME::vpGammaMethodFromString(argv[i]);
}
else if (std::string(argv[i]) == "--scale" && i + 1 < argc) {
scale = atoi(argv[i + 1]);
++i;
scale = atoi(argv[i]);
}
else if (std::string(argv[i]) == "--scaleDiv" && i + 1 < argc) {
scaleDiv = atoi(argv[i + 1]);
++i;
scaleDiv = atoi(argv[i]);
}
else if (std::string(argv[i]) == "--level" && i + 1 < argc) {
level = atoi(argv[i + 1]);
++i;
level = atoi(argv[i]);
}
else if (std::string(argv[i]) == "--kernelSize" && i + 1 < argc) {
kernelSize = atoi(argv[i + 1]);
++i;
kernelSize = atoi(argv[i]);
}
else if (std::string(argv[i]) == "--dynamic" && i + 1 < argc) {
dynamic = atof(argv[i + 1]);
++i;
dynamic = atof(argv[i]);
}
else if (std::string(argv[i]) == "--scale-display" && i + 1 < argc) {
++i;
scale_display = atoi(argv[i]);
}
else if (std::string(argv[i]) == "--help" || std::string(argv[i]) == "-h") {
std::cout << "Usage: " << argv[0]
Expand All @@ -83,45 +131,51 @@ int main(int argc, const char **argv)
"VISP_NAMESPACE_NAME::retinex()]"
" [--level <level for VISP_NAMESPACE_NAME::retinex()> [--kernelSize "
"<kernelSize for VISP_NAMESPACE_NAME::retinex()>]"
" [--dynamic <dynamic for VISP_NAMESPACE_NAME::retinex()>] [--help]"
" [--dynamic <dynamic for VISP_NAMESPACE_NAME::retinex()>] "
" [--scale-display <display downscaling factor>] "
" [--help]"
<< std::endl;
return EXIT_SUCCESS;
}
}

// Filename without extension to save the results
const std::string input_name = vpIoTools::getNameWE(input_filename);

vpImage<vpRGBa> I_color;
vpImageIo::read(I_color, input_filename);
vpImage<unsigned char> I_gray;
vpImageConvert::convert(I_color, I_gray);
vpImage<vpRGBa> I_gray_display;
vpImageConvert::convert(I_gray, I_gray_display);

// Side-by-side images
vpImage<vpRGBa> I_color_res(I_color.getHeight(), 2 * I_color.getWidth());
I_color_res.insert(I_color, vpImagePoint());
vpImage<unsigned char> I_gray_res(I_gray.getHeight(), 2 * I_gray.getWidth());
I_gray_res.insert(I_gray, vpImagePoint());
#ifdef VISP_HAVE_X11
vpDisplayX d_gray(I_gray_res);
vpDisplayX d(I_color_res);
#elif defined(VISP_HAVE_GDI)
vpDisplayGDI d_gray(I_gray_res);
vpDisplayGDI d(I_color_res);
#elif defined(HAVE_OPENCV_HIGHGUI)
vpDisplayOpenCV d_gray(I_gray_res);
vpDisplayOpenCV d(I_color_res);
#endif

// Side-by-side display for color (top) and gray (bottom) images
vpImage<vpRGBa> I_display(2 * I_color.getHeight(), 2 * I_color.getWidth());
I_display.insert(I_color, vpImagePoint());
I_display.insert(I_gray_display, vpImagePoint(I_color.getHeight(), 0));
std::shared_ptr<vpDisplay> d = vpDisplayFactory::createDisplay();
d->setDownScalingFactor(static_cast<vpDisplay::vpScaleType>(scale_display));
d->init(I_display, 10, 10, "Brightness adjustment results");

//! [Brightness contrast adjustment]
vpImage<vpRGBa> I_color_adjust;
VISP_NAMESPACE_NAME::adjust(I_color, I_color_adjust, alpha, beta);
vpImage<unsigned char> I_gray_adjust;
VISP_NAMESPACE_NAME::adjust(I_gray, I_gray_adjust, alpha, beta);
//! [Brightness contrast adjustment]
I_color_res.insert(I_color_adjust, vpImagePoint(0, I_color.getWidth()));
std::stringstream ss;
ss << "Sample_low_brightness_alpha=" << alpha << "_beta=" << beta << ".png";
vpImageIo::write(I_color_res, ss.str());

vpDisplay::display(I_color_res);
vpDisplay::displayText(I_color_res, 20, 20, "Brightness and contrast adjustment. Click to continue.", vpColor::red);
vpDisplay::flush(I_color_res);
vpDisplay::getClick(I_color_res);
std::stringstream ss_color;
ss_color << input_name << "_adjust_alpha=" << alpha << "_beta=" << beta << ".png";
std::stringstream ss_gray;
ss_gray << input_name << "_adjust_alpha=" << alpha << "_beta=" << beta << "_gray.png";
display(I_display, I_color_res, I_color_adjust, I_gray_res, I_gray_adjust, I_gray_display,
"Brightness and contrast adjustment. Click to continue.", ss_color.str(), ss_gray.str());

//! [Gamma correction]
if (method != VISP_NAMESPACE_NAME::GAMMA_MANUAL) {
Expand All @@ -133,60 +187,78 @@ int main(int argc, const char **argv)
// If the user wants to set a constant user-defined gamma factor, the method must be set to manual.
method = VISP_NAMESPACE_NAME::GAMMA_MANUAL;
}
vpImage<unsigned char> I_gray_gamma_correction;
VISP_NAMESPACE_NAME::gammaCorrection(I_gray, I_gray_gamma_correction, static_cast<float>(gamma), method);
vpImage<vpRGBa> I_color_gamma_correction;
VISP_NAMESPACE_NAME::gammaCorrection(I_color, I_color_gamma_correction, static_cast<float>(gamma), colorHandling, method);
vpImage<unsigned char> I_gray_gamma_correction;
VISP_NAMESPACE_NAME::gammaCorrection(I_gray, I_gray_gamma_correction, static_cast<float>(gamma), method);
//! [Gamma correction]
I_gray_res.insert(I_gray_gamma_correction, vpImagePoint(0, I_gray.getWidth()));
ss.str("");
ss << "Sample_low_brightness_gray.png";
vpImageIo::write(I_gray_res, ss.str());

vpDisplay::display(I_gray_res);
vpDisplay::displayText(I_gray_res, 20, 20, "Gamma correction on gray image. Click to continue.", vpColor::red);
vpDisplay::flush(I_gray_res);
vpDisplay::getClick(I_gray_res);

I_color_res.insert(I_color_gamma_correction, vpImagePoint(0, I_color.getWidth()));
ss.str("");
ss << "Sample_low_brightness_gamma=" << gamma << ".png";
vpImageIo::write(I_color_res, ss.str());

vpDisplay::display(I_color_res);
vpDisplay::displayText(I_color_res, 20, 20, "Gamma correction. Click to continue.", vpColor::red);
vpDisplay::flush(I_color_res);
vpDisplay::getClick(I_color_res);

ss_color.str("");
ss_color << input_name << "_gamma=" << gamma << ".png";
ss_gray.str("");
ss_gray << input_name << "_gamma=" << gamma << "_gray.png";
display(I_display, I_color_res, I_color_gamma_correction, I_gray_res, I_gray_gamma_correction, I_gray_display,
"Gamma correction. Click to continue.", ss_color.str(), ss_gray.str());

// Display results for the different Gamma correction method
for (int gamma_idx = 0; gamma_idx < VISP_NAMESPACE_NAME::GAMMA_METHOD_COUNT; ++gamma_idx) {
gamma = -1.;
VISP_NAMESPACE_NAME::vpGammaMethod gamma_method = static_cast<VISP_NAMESPACE_NAME::vpGammaMethod>(gamma_idx);
if (gamma_method == VISP_NAMESPACE_NAME::GAMMA_MANUAL) {
continue;
}

vpImage<vpRGBa> I_color_gamma_correction;
VISP_NAMESPACE_NAME::gammaCorrection(I_color, I_color_gamma_correction, static_cast<float>(gamma), colorHandling,
gamma_method);
vpImage<unsigned char> I_gray_gamma_correction;
VISP_NAMESPACE_NAME::gammaCorrection(I_gray, I_gray_gamma_correction, static_cast<float>(gamma), gamma_method);

const std::string gamma_name = VISP_NAMESPACE_NAME::vpGammaMethodToString(gamma_method);
ss_color.str("");
ss_color << input_name << "_" << gamma_name << ".png";
ss_gray.str("");
ss_gray << input_name << "_" << gamma_name << "_gray.png";
display(I_display, I_color_res, I_color_gamma_correction, I_gray_res, I_gray_gamma_correction, I_gray_display,
"Gamma correction. Click to continue.", ss_color.str(), ss_gray.str(), gamma_name);
}

//! [Histogram equalization]
vpImage<vpRGBa> I_color_equalize_histogram;
VISP_NAMESPACE_NAME::equalizeHistogram(I_color, I_color_equalize_histogram);
vpImage<unsigned char> I_gray_equalize_histogram;
VISP_NAMESPACE_NAME::equalizeHistogram(I_gray, I_gray_equalize_histogram);
//! [Histogram equalization]
I_color_res.insert(I_color_equalize_histogram, vpImagePoint(0, I_color.getWidth()));
ss.str("");
ss << "Sample_low_brightness_eqHist.png";
vpImageIo::write(I_color_res, ss.str());

vpDisplay::display(I_color_res);
vpDisplay::displayText(I_color_res, 20, 20, "Histogram equalization. Click to continue.", vpColor::red);
vpDisplay::flush(I_color_res);
vpDisplay::getClick(I_color_res);
ss_color.str("");
ss_color << input_name << "_eqHist.png";
ss_gray.str("");
ss_gray << input_name << "_eqHist_gray.png";
display(I_display, I_color_res, I_color_equalize_histogram, I_gray_res, I_gray_equalize_histogram, I_gray_display,
"Histogram equalization. Click to continue.", ss_color.str(), ss_gray.str());

//! [Retinex]
vpImage<vpRGBa> I_color_retinex;
VISP_NAMESPACE_NAME::retinex(I_color, I_color_retinex, scale, scaleDiv, level, dynamic, kernelSize);
// Retinex uses color image as input
// Convert gray image into RGBa format for quick test
vpImage<vpRGBa> I_gray_color;
vpImageConvert::convert(I_gray, I_gray_color);
vpImage<vpRGBa> I_gray_color_retinex;
VISP_NAMESPACE_NAME::retinex(I_gray_color, I_gray_color_retinex, scale, scaleDiv, level, dynamic, kernelSize);
// Convert back to gray
vpImage<unsigned char> I_gray_retinex;
vpImageConvert::convert(I_gray_color_retinex, I_gray_retinex);
//! [Retinex]
I_color_res.insert(I_color_retinex, vpImagePoint(0, I_color.getWidth()));

ss.str("");
ss << "Sample_low_brightness_scale=" << scale << "_scaleDiv=" << scaleDiv << "_level=" << level
ss_color.str("");
ss_color << input_name << "_Retinex_scale=" << scale << "_scaleDiv=" << scaleDiv << "_level=" << level
<< "_dynamic=" << dynamic << "_kernelSize=" << kernelSize << ".png";
vpImageIo::write(I_color_res, ss.str());

vpDisplay::display(I_color_res);
vpDisplay::displayText(I_color_res, 20, 20, "Retinex. Click to quit.", vpColor::red);
vpDisplay::flush(I_color_res);
vpDisplay::getClick(I_color_res);
ss_gray.str("");
ss_gray << input_name << "_Retinex_scale=" << scale << "_scaleDiv=" << scaleDiv << "_level=" << level
<< "_dynamic=" << dynamic << "_kernelSize=" << kernelSize << "_gray.png";
display(I_display, I_color_res, I_color_retinex, I_gray_res, I_gray_retinex, I_gray_display,
"Retinex. Click to quit.", ss_color.str(), ss_gray.str());
#else
(void)argc;
(void)argv;
Expand Down

0 comments on commit bb37bf8

Please sign in to comment.