Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
tutorial-brightness-adjustment.cpp
1
2
3#include <cstdlib>
4#include <iostream>
5#include <visp3/core/vpConfig.h>
6#include <visp3/core/vpImage.h>
7#include <visp3/core/vpIoTools.h>
8#include <visp3/gui/vpDisplayFactory.h>
9#include <visp3/io/vpImageIo.h>
10
11#if defined(VISP_HAVE_MODULE_IMGPROC)
13#include <visp3/imgproc/vpImgproc.h>
15#endif
16
17#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
18#include <memory>
19#endif
20
21#ifdef ENABLE_VISP_NAMESPACE
22using namespace VISP_NAMESPACE_NAME;
23#endif
24
25#if defined(VISP_HAVE_MODULE_IMGPROC) && defined(VISP_HAVE_DISPLAY) && (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11) && \
26 (defined(VISP_HAVE_PNG) || defined(VISP_HAVE_OPENCV) || defined(VISP_HAVE_STBIMAGE) || defined(VISP_HAVE_SIMDLIB))
27namespace
28{
29void display(vpImage<vpRGBa> &I_display, vpImage<vpRGBa> &I_color_res, const vpImage<vpRGBa> &I_color_adjust,
30 vpImage<unsigned char> &I_gray_res, vpImage<unsigned char> &I_gray_adjust, vpImage<vpRGBa> &I_gray_display,
31 const std::string &title, const std::string &filename_color, const std::string &filename_gray,
32 const std::string &title_2 = "")
33{
34 I_color_res.insert(I_color_adjust, vpImagePoint(0, I_color_adjust.getWidth()));
35 I_display.insert(I_color_adjust, vpImagePoint(0, I_color_adjust.getWidth()));
36
37 I_gray_res.insert(I_gray_adjust, vpImagePoint(0, I_gray_adjust.getWidth()));
38 vpImageConvert::convert(I_gray_adjust, I_gray_display);
39 I_display.insert(I_gray_display, vpImagePoint(I_color_adjust.getHeight(), I_color_adjust.getWidth()));
40
41 vpImageIo::write(I_color_res, filename_color);
42 vpImageIo::write(I_gray_res, filename_gray);
43
44 vpDisplay::display(I_display);
45 vpDisplay::displayText(I_display, 20, 20, title, vpColor::red);
46 if (!title_2.empty()) {
47 vpDisplay::displayText(I_display, 40, static_cast<unsigned int>(I_color_adjust.getWidth()*0.85),
48 title_2, vpColor::green);
49 }
50 vpDisplay::flush(I_display);
51 vpDisplay::getClick(I_display);
52}
53}
54#endif
55
56int main(int argc, const char **argv)
57{
59#if defined(VISP_HAVE_MODULE_IMGPROC) && defined(VISP_HAVE_DISPLAY) && (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11) && \
60 (defined(VISP_HAVE_PNG) || defined(VISP_HAVE_OPENCV) || defined(VISP_HAVE_STBIMAGE) || defined(VISP_HAVE_SIMDLIB))
62
63 std::string input_filename = "Sample_low_brightness.png";
64 double alpha = 10.0, beta = 50.0;
65 double gamma = 3.5;
68 int scale = 240, scaleDiv = 3, level = 0, kernelSize = -1;
69 double dynamic = 3.0;
70 int scale_display = 2;
71
72 for (int i = 1; i < argc; i++) {
73 if (std::string(argv[i]) == "--input" && i + 1 < argc) {
74 ++i;
75 input_filename = std::string(argv[i]);
76 }
77 else if (std::string(argv[i]) == "--alpha" && i + 1 < argc) {
78 ++i;
79 alpha = atof(argv[i]);
80 }
81 else if (std::string(argv[i]) == "--beta" && i + 1 < argc) {
82 ++i;
83 beta = atof(argv[i]);
84 }
85 else if (std::string(argv[i]) == "--gamma" && i + 1 < argc) {
86 ++i;
87 gamma = atof(argv[i]);
88 }
89 else if ((std::string(argv[i]) == "--gamma-color-handling") && ((i + 1) < argc)) {
90 ++i;
92 }
93 else if ((std::string(argv[i]) == "--gamma-method") && ((i + 1) < argc)) {
94 ++i;
96 }
97 else if (std::string(argv[i]) == "--scale" && i + 1 < argc) {
98 ++i;
99 scale = atoi(argv[i]);
100 }
101 else if (std::string(argv[i]) == "--scaleDiv" && i + 1 < argc) {
102 ++i;
103 scaleDiv = atoi(argv[i]);
104 }
105 else if (std::string(argv[i]) == "--level" && i + 1 < argc) {
106 ++i;
107 level = atoi(argv[i]);
108 }
109 else if (std::string(argv[i]) == "--kernelSize" && i + 1 < argc) {
110 ++i;
111 kernelSize = atoi(argv[i]);
112 }
113 else if (std::string(argv[i]) == "--dynamic" && i + 1 < argc) {
114 ++i;
115 dynamic = atof(argv[i]);
116 }
117 else if (std::string(argv[i]) == "--scale-display" && i + 1 < argc) {
118 ++i;
119 scale_display = atoi(argv[i]);
120 }
121 else if (std::string(argv[i]) == "--help" || std::string(argv[i]) == "-h") {
122 std::cout << "Usage: " << argv[0]
123 << " [--input <input image>]"
124 " [--alpha <alpha for adjust()>] [--beta <beta for adjust()>]"
125 " [--gamma <gamma for gammaCorrection()>]"
126 " [--gamma-color-handling " << VISP_NAMESPACE_NAME::vpGammaColorHandlingList() << "]"
127 " [--gamma-method " << VISP_NAMESPACE_NAME::vpGammaMethodList() << "]"
128 " [--scale <scale for retinex()> [--scaleDiv for retinex()]"
129 " [--level <level for retinex()> [--kernelSize <kernelSize for retinex()>]"
130 " [--dynamic <dynamic for retinex()>] "
131 " [--scale-display <display downscaling factor>] "
132 " [--help]"
133 << std::endl;
134 return EXIT_SUCCESS;
135 }
136 }
137
138 // Filename without extension to save the results
139 const std::string input_name = vpIoTools::getNameWE(input_filename);
140
141 vpImage<vpRGBa> I_color;
142 vpImageIo::read(I_color, input_filename);
144 vpImageConvert::convert(I_color, I_gray);
145 vpImage<vpRGBa> I_gray_display;
146 vpImageConvert::convert(I_gray, I_gray_display);
147
148 // Side-by-side images
149 vpImage<vpRGBa> I_color_res(I_color.getHeight(), 2 * I_color.getWidth());
150 I_color_res.insert(I_color, vpImagePoint());
151 vpImage<unsigned char> I_gray_res(I_gray.getHeight(), 2 * I_gray.getWidth());
152 I_gray_res.insert(I_gray, vpImagePoint());
153
154 // Side-by-side display for color (top) and gray (bottom) images
155 vpImage<vpRGBa> I_display(2 * I_color.getHeight(), 2 * I_color.getWidth());
156 I_display.insert(I_color, vpImagePoint());
157 I_display.insert(I_gray_display, vpImagePoint(I_color.getHeight(), 0));
158 std::shared_ptr<vpDisplay> d = vpDisplayFactory::createDisplay();
159 d->setDownScalingFactor(static_cast<vpDisplay::vpScaleType>(scale_display));
160 d->init(I_display, 10, 10, "Brightness adjustment results");
161
163 vpImage<vpRGBa> I_color_adjust;
164 VISP_NAMESPACE_NAME::adjust(I_color, I_color_adjust, alpha, beta);
165 vpImage<unsigned char> I_gray_adjust;
166 VISP_NAMESPACE_NAME::adjust(I_gray, I_gray_adjust, alpha, beta);
168
169 std::stringstream ss_color;
170 ss_color << input_name << "_adjust_alpha=" << alpha << "_beta=" << beta << ".png";
171 std::stringstream ss_gray;
172 ss_gray << input_name << "_adjust_alpha=" << alpha << "_beta=" << beta << "_gray.png";
173 display(I_display, I_color_res, I_color_adjust, I_gray_res, I_gray_adjust, I_gray_display,
174 "Brightness and contrast adjustment. Click to continue.", ss_color.str(), ss_gray.str());
175
177 if (method != VISP_NAMESPACE_NAME::GAMMA_MANUAL) {
178 // If the user wants to use an automatic method, the gamma factor must be negative.
179 gamma = -1.;
180 }
181
182 if (gamma > 0.) {
183 // If the user wants to set a constant user-defined gamma factor, the method must be set to manual.
185 }
186 vpImage<vpRGBa> I_color_gamma_correction;
187 VISP_NAMESPACE_NAME::gammaCorrection(I_color, I_color_gamma_correction, static_cast<float>(gamma), colorHandling, method);
188 vpImage<unsigned char> I_gray_gamma_correction;
189 VISP_NAMESPACE_NAME::gammaCorrection(I_gray, I_gray_gamma_correction, static_cast<float>(gamma), method);
191
192 ss_color.str("");
193 ss_color << input_name << "_gamma=" << gamma << ".png";
194 ss_gray.str("");
195 ss_gray << input_name << "_gamma=" << gamma << "_gray.png";
196 display(I_display, I_color_res, I_color_gamma_correction, I_gray_res, I_gray_gamma_correction, I_gray_display,
197 "Gamma correction. Click to continue.", ss_color.str(), ss_gray.str());
198
199 // Display results for the different Gamma correction method
200 for (int gamma_idx = 0; gamma_idx < VISP_NAMESPACE_NAME::GAMMA_METHOD_COUNT; ++gamma_idx) {
201 gamma = -1.;
202 VISP_NAMESPACE_NAME::vpGammaMethod gamma_method = static_cast<VISP_NAMESPACE_NAME::vpGammaMethod>(gamma_idx);
203 if (gamma_method == VISP_NAMESPACE_NAME::GAMMA_MANUAL) {
204 continue;
205 }
206
207 vpImage<vpRGBa> I_color_gamma_correction;
208 VISP_NAMESPACE_NAME::gammaCorrection(I_color, I_color_gamma_correction, static_cast<float>(gamma), colorHandling,
209 gamma_method);
210 vpImage<unsigned char> I_gray_gamma_correction;
211 VISP_NAMESPACE_NAME::gammaCorrection(I_gray, I_gray_gamma_correction, static_cast<float>(gamma), gamma_method);
212
213 const std::string gamma_name = VISP_NAMESPACE_NAME::vpGammaMethodToString(gamma_method);
214 ss_color.str("");
215 ss_color << input_name << "_" << gamma_name << ".png";
216 ss_gray.str("");
217 ss_gray << input_name << "_" << gamma_name << "_gray.png";
218 display(I_display, I_color_res, I_color_gamma_correction, I_gray_res, I_gray_gamma_correction, I_gray_display,
219 "Gamma correction. Click to continue.", ss_color.str(), ss_gray.str(), gamma_name);
220 }
221
223 vpImage<vpRGBa> I_color_equalize_histogram;
224 VISP_NAMESPACE_NAME::equalizeHistogram(I_color, I_color_equalize_histogram);
225 vpImage<unsigned char> I_gray_equalize_histogram;
226 VISP_NAMESPACE_NAME::equalizeHistogram(I_gray, I_gray_equalize_histogram);
228
229 ss_color.str("");
230 ss_color << input_name << "_eqHist.png";
231 ss_gray.str("");
232 ss_gray << input_name << "_eqHist_gray.png";
233 display(I_display, I_color_res, I_color_equalize_histogram, I_gray_res, I_gray_equalize_histogram, I_gray_display,
234 "Histogram equalization. Click to continue.", ss_color.str(), ss_gray.str());
235
237 vpImage<vpRGBa> I_color_retinex;
238 VISP_NAMESPACE_NAME::retinex(I_color, I_color_retinex, scale, scaleDiv, level, dynamic, kernelSize);
239 // Retinex uses color image as input
240 // Convert gray image into RGBa format for quick test
241 vpImage<vpRGBa> I_gray_color;
242 vpImageConvert::convert(I_gray, I_gray_color);
243 vpImage<vpRGBa> I_gray_color_retinex;
244 VISP_NAMESPACE_NAME::retinex(I_gray_color, I_gray_color_retinex, scale, scaleDiv, level, dynamic, kernelSize);
245 // Convert back to gray
246 vpImage<unsigned char> I_gray_retinex;
247 vpImageConvert::convert(I_gray_color_retinex, I_gray_retinex);
249
250 ss_color.str("");
251 ss_color << input_name << "_Retinex_scale=" << scale << "_scaleDiv=" << scaleDiv << "_level=" << level
252 << "_dynamic=" << dynamic << "_kernelSize=" << kernelSize << ".png";
253 ss_gray.str("");
254 ss_gray << input_name << "_Retinex_scale=" << scale << "_scaleDiv=" << scaleDiv << "_level=" << level
255 << "_dynamic=" << dynamic << "_kernelSize=" << kernelSize << "_gray.png";
256 display(I_display, I_color_res, I_color_retinex, I_gray_res, I_gray_retinex, I_gray_display,
257 "Retinex. Click to quit.", ss_color.str(), ss_gray.str());
258#else
259 (void)argc;
260 (void)argv;
261#endif
262 return EXIT_SUCCESS;
263}
static const vpColor red
Definition vpColor.h:198
static const vpColor green
Definition vpColor.h:201
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
static void display(const vpImage< unsigned char > &I)
static void flush(const vpImage< unsigned char > &I)
static void displayText(const vpImage< unsigned char > &I, const vpImagePoint &ip, const std::string &s, const vpColor &color)
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
static void read(vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
static void write(const vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition of the vpImage class member functions.
Definition vpImage.h:131
unsigned int getWidth() const
Definition vpImage.h:242
void insert(const vpImage< Type > &src, const vpImagePoint &topLeft)
Definition vpImage.h:639
unsigned int getHeight() const
Definition vpImage.h:181
static std::string getNameWE(const std::string &pathname)
VISP_EXPORT void adjust(VISP_NAMESPACE_ADDRESSING vpImage< unsigned char > &I, double alpha, double beta)
VISP_EXPORT void gammaCorrection(VISP_NAMESPACE_ADDRESSING vpImage< unsigned char > &I, const float &gamma, const vpGammaMethod &method=GAMMA_MANUAL, const VISP_NAMESPACE_ADDRESSING vpImage< bool > *p_mask=nullptr)
VISP_EXPORT void equalizeHistogram(VISP_NAMESPACE_ADDRESSING vpImage< unsigned char > &I, const VISP_NAMESPACE_ADDRESSING vpImage< bool > *p_mask=nullptr)
VISP_EXPORT void retinex(VISP_NAMESPACE_ADDRESSING vpImage< VISP_NAMESPACE_ADDRESSING vpRGBa > &I, int scale=240, int scaleDiv=3, int level=RETINEX_UNIFORM, double dynamic=1.2, int kernelSize=-1)
VISP_EXPORT vpGammaMethod vpGammaMethodFromString(const std::string &name)
Cast a string into a vpGammaMethod.
VISP_EXPORT vpGammaColorHandling vpGammaColorHandlingFromString(const std::string &name)
Cast a string into a vpGammaColorHandling.
vpGammaColorHandling
How to handle color images when applying Gamma Correction.
Definition vpImgproc.h:147
VISP_EXPORT std::string vpGammaMethodList(const std::string &pref="<", const std::string &sep=" , ", const std::string &suf=">")
Get the list of available vpGammaMethod.
Definition vpImgproc.cpp:73
VISP_EXPORT std::string vpGammaColorHandlingList(const std::string &pref="<", const std::string &sep=" , ", const std::string &suf=">")
Get the list of available vpGammaColorHandling.
vpGammaMethod
Gamma Correction automatic methods.
Definition vpImgproc.h:98
VISP_EXPORT std::string vpGammaMethodToString(const vpGammaMethod &type)
Cast a vpGammaMethod into a string, to know its name.
Definition vpImgproc.cpp:87
std::shared_ptr< vpDisplay > createDisplay()
Return a smart pointer vpDisplay specialization if a GUI library is available or nullptr otherwise.