4#include <visp3/core/vpConfig.h>
5#include <visp3/core/vpImage.h>
6#include <visp3/core/vpIoTools.h>
7#include <visp3/core/vpImageTools.h>
8#include <visp3/core/vpCannyEdgeDetection.h>
9#include <visp3/core/vpImageFilter.h>
10#include <visp3/core/vpFont.h>
11#include <visp3/io/vpImageIo.h>
12#include <visp3/io/vpVideoReader.h>
15#if defined(VISP_HAVE_MODULE_IMGPROC) && defined(VISP_HAVE_SIMDLIB) && (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
16#include <visp3/imgproc/vpImgproc.h>
19#ifdef ENABLE_VISP_NAMESPACE
26void computeMeanMaxStdev(
const vpImage<T> &I,
float &mean,
float &max,
float &stdev)
28 max = std::numeric_limits<float>::epsilon();
31 unsigned int nbRows = I.getRows();
32 unsigned int nbCols = I.getCols();
33 float scale = 1.f / (
static_cast<float>(nbRows) *
static_cast<float>(nbCols));
34 for (
unsigned int r = 0;
r < nbRows;
r++) {
35 for (
unsigned int c = 0; c < nbCols; c++) {
37 max = std::max<float>(max,
static_cast<float>(I[r][c]));
41 for (
unsigned int r = 0;
r < nbRows;
r++) {
42 for (
unsigned int c = 0; c < nbCols; c++) {
43 stdev += (I[
r][c] - mean) * (I[r][c] - mean);
47 stdev = std::sqrt(stdev);
56 apertureSize, filteringType);
58 for (
unsigned int i = 0;
i < dIx.
getHeight();
i++) {
59 for (
unsigned int j = 0;
j < dIx.
getWidth();
j++) {
60 dIxy[
i][
j] = std::sqrt(dIx[i][j]*dIx[i][j] + dIy[i][j]*dIy[i][j]);
64 float mean, max, stdev;
65 computeMeanMaxStdev(dIxy, mean, max, stdev);
71 I_canny_visp = cannyDetector.
detect(I);
77 std::vector<int> hist(256, 0);
78 for (
unsigned int i = 0;
i < I.getHeight();
i++) {
79 for (
unsigned int j = 0;
j < I.getWidth();
j++) {
85 double N = I.getSize();
87 for (
size_t i = 0;
i < hist.size();
i++) {
91 double p = hist[
i] / N;
92 cost += -
p * std::log2(p);
99int main(
int argc,
const char **argv)
101 std::string input =
"Sample_low_brightness.png";
102 std::string output =
"Results";
103 int gaussianKernelSize = 3;
104 float gaussianStdev = 1.0f;
105 int apertureSize = 3;
106 unsigned int max_resolution = 800;
110 for (
int i = 1;
i < argc;
i++) {
111 if (std::string(argv[i]) ==
"--input" && i + 1 < argc) {
113 input = std::string(argv[i]);
115 else if (std::string(argv[i]) ==
"--max-resolution" && i + 1 < argc) {
117 max_resolution = std::atoi(argv[i]);
119 else if (std::string(argv[i]) ==
"--gaussian-kernel-size" && i + 1 < argc) {
121 gaussianKernelSize = std::atoi(argv[i]);
123 else if (std::string(argv[i]) ==
"--gaussian-std" && i + 1 < argc) {
125 gaussianStdev =
static_cast<float>(std::atof(argv[i]));
127 else if (std::string(argv[i]) ==
"--aperture-size" && i + 1 < argc) {
129 apertureSize = std::atoi(argv[i]);
131 else if (std::string(argv[i]) ==
"--canny-filtering-type" && i + 1 < argc) {
133 int type = std::atoi(argv[i]);
138 else if (std::string(argv[i]) ==
"--gamma-rgb") {
141 else if (std::string(argv[i]) ==
"--output" && i + 1 < argc) {
143 output = std::string(argv[i]);
146 std::cout <<
"Usage: " << argv[0]
147 <<
" [--input <input path or image sequence pattern>]"
148 " [--max-resolution <resolution_in_px> (max image resolution, otherwise the input image is resized)]"
149 " [--gaussian-kernel-size <e.g. 3, 5, 7>]"
150 " [--gaussian-std <e.g. 1>]"
151 " [--aperture-size <e.g. 3>]"
152 " [--canny-filtering-type <0=CANNY_GBLUR_SOBEL_FILTERING, 1=CANNY_GBLUR_SCHARR_FILTERING>]"
153 " [--gamma-rgb (RGB colorspace, else HSV]"
154 " [--output <folder path> (to save the results)]"
160 std::cout <<
"Input: " << input << std::endl;
161 std::cout <<
"Max image resolution: " << max_resolution << std::endl;
162 std::cout <<
"Gaussian kernel size: " << gaussianKernelSize << std::endl;
163 std::cout <<
"Gaussian standard deviation: " << gaussianStdev << std::endl;
164 std::cout <<
"Aperture size: " << apertureSize << std::endl;
165 std::cout <<
"Canny filtering type: " << filteringType << std::endl;
167 std::cout <<
"Output result folder: " << output << std::endl;
170 float lowerThresh = -1.;
171 float upperThresh = -1.;
172 float lowerThreshRatio = 0.6f;
173 float upperThreshRatio = 0.8f;
175 lowerThresh, upperThresh, lowerThreshRatio, upperThreshRatio,
186 reader.
open(I_color_ori);
189 if (I_color_ori.
getWidth() > max_resolution || I_color_ori.
getHeight() > max_resolution) {
190 float factor_w = I_color_ori.
getWidth() /
static_cast<float>(max_resolution);
191 float factor_h = I_color_ori.
getHeight() /
static_cast<float>(max_resolution);
192 int resize_factor_w =
static_cast<int>(factor_w);
193 int resize_factor_h =
static_cast<int>(factor_h);
194 int resize_factor = std::max(resize_factor_w, resize_factor_h);
199 I_color = I_color_ori;
205 std::vector<std::vector<double>> computation_times(nb_methods);
212 bool read_single_image =
false;
213 while (!read_single_image && (single_image || !reader.
end())) {
214 std::cout <<
"\n" << reader.
getFrameIndex() <<
")" << std::endl;
218 if (I_color_ori.
getWidth() > max_resolution || I_color_ori.
getHeight() > max_resolution) {
219 float factor_w = I_color_ori.
getWidth() /
static_cast<float>(max_resolution);
220 float factor_h = I_color_ori.
getHeight() /
static_cast<float>(max_resolution);
221 int resize_factor_w =
static_cast<int>(factor_w);
222 int resize_factor_h =
static_cast<int>(factor_h);
223 int resize_factor = std::max(resize_factor_w, resize_factor_h);
228 I_color = I_color_ori;
232 const int nb_cols = 4;
238 int offset_text_start_y = 25;
241 double offset_text1 = 0.01;
242 double offset_text2 = 0.26;
244 char buffer[FILENAME_MAX];
248 computeCanny(I_gray, cannyDetector, gaussianKernelSize, gaussianStdev, apertureSize,
249 filteringType, dIxy_uchar, I_canny_visp);
250 const double img_ori_Canny = I_canny_visp.
getMeanValue();
251 const double img_ori_entropy = computeImageEntropy(I_gray);
255 computation_times[offset_idx].push_back(-1);
263 snprintf(buffer, FILENAME_MAX,
"Entropy: %.4f", img_ori_entropy);
266 snprintf(buffer, FILENAME_MAX,
"Entropy: %.4f", img_ori_entropy);
269 snprintf(buffer, FILENAME_MAX,
"Canny mean: %.2f", I_canny_visp.
getMeanValue());
280 const double gamma = -1;
283 gamma_colorspace, gamma_method);
287 computation_times[offset_idx].push_back(end_time-start_time);
290 const double img_corrected_entropy = computeImageEntropy(I_gray_gamma_correction);
291 computeCanny(I_gray_gamma_correction, cannyDetector, gaussianKernelSize, gaussianStdev, apertureSize,
292 filteringType, dIxy_uchar, I_canny_visp);
300 snprintf(buffer, FILENAME_MAX,
"Entropy: %.4f", img_ori_entropy);
303 std::ostringstream oss;
305 snprintf(buffer, FILENAME_MAX, oss.str().c_str(), (end_time-start_time));
306 font.drawText(I_res_stack, buffer,
vpImagePoint(offset_idx*I_color.
getHeight() + offset_text_start_y,
309 snprintf(buffer, FILENAME_MAX,
"Entropy: %.4f", img_corrected_entropy);
312 double canny_mean_perc = 100 * I_canny_visp.
getMeanValue() / img_ori_Canny;
313 snprintf(buffer, FILENAME_MAX,
"Canny mean: %.2f (%.2f%%)", I_canny_visp.
getMeanValue(), canny_mean_perc);
314 font.drawText(I_res_stack, buffer,
vpImagePoint(offset_idx*I_color.
getHeight() + offset_text_start_y+2*text_h,
318 if (!output.empty()) {
319 std::stringstream output_filename;
320 const std::string extension =
".jpeg";
327 std::cout <<
"Write result to: " << output_filename.str() << std::endl;
332 read_single_image =
true;
336 std::cout <<
"\nStats:" << std::endl;
337 std::cout <<
"Nb images: " << nb_images << std::endl;
345 <<
vpMath::getMean(computation_times[1 + gamma_idx-1]) <<
" ms ; median="
354 std::cerr <<
"C++11 is required." << std::endl;
Class that implements the Canny's edge detector. It is possible to use a boolean mask to ignore some ...
vpImage< unsigned char > detect(const vpImage< vpRGBa > &I_color)
Detect the edges in an image. Convert the color image into a gray-scale image.
void setGradients(const vpImage< float > &dIx, const vpImage< float > &dIy)
Set the Gradients of the image that will be processed.
Font drawing functions for image.
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
vpCannyFilteringAndGradientType
Canny filter and gradient operators to apply on the image before the edge detection stage.
@ CANNY_GBLUR_SOBEL_FILTERING
Apply Gaussian blur + Sobel operator on the input image.
@ CANNY_GBLUR_SCHARR_FILTERING
Apply Gaussian blur + Scharr operator on the input image.
static void computePartialDerivatives(const cv::Mat &cv_I, cv::Mat &cv_dIx, cv::Mat &cv_dIy, const bool &computeDx=true, const bool &computeDy=true, const bool &normalize=true, const unsigned int &gaussianKernelSize=5, const float &gaussianStdev=2.f, const unsigned int &apertureGradient=3, const vpCannyFilteringAndGradientType &filteringType=CANNY_GBLUR_SOBEL_FILTERING)
Compute the partial derivatives (i.e. horizontal and vertical gradients) of the input image.
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.
void init(unsigned int height, unsigned int width)
Set the size of the image.
unsigned int getWidth() const
void insert(const vpImage< Type > &src, const vpImagePoint &topLeft)
unsigned int getHeight() const
double getMeanValue(const vpImage< bool > *p_mask=nullptr, unsigned int *nbValidPoints=nullptr) const
Return the mean value of the bitmap.
static double getMedian(const std::vector< double > &v)
static double getMean(const std::vector< double > &v)
Class that enables to manipulate easily a video file or a sequence of images. As it inherits from the...
void open(vpImage< vpRGBa > &I) VP_OVERRIDE
void setFileName(const std::string &filename)
std::string getFrameName() const
long getFrameIndex() const
void acquire(vpImage< vpRGBa > &I) VP_OVERRIDE
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)
vpGammaColorHandling
How to handle color images when applying Gamma Correction.
vpGammaMethod
Gamma Correction automatic methods.
VISP_EXPORT std::string vpGammaMethodToString(const vpGammaMethod &type)
Cast a vpGammaMethod into a string, to know its name.
VISP_EXPORT double measureTimeMs()