diff --git a/modules/imgproc/include/opencv2/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc.hpp index 2f447b9cd..2e1361466 100644 --- a/modules/imgproc/include/opencv2/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc.hpp @@ -191,10 +191,10 @@ enum { HOUGH_STANDARD = 0, HOUGH_GRADIENT = 3 }; -//! Variants of Line Segment Detector +//! Variants of Line Segment Detector enum lsd_refine_lvl - { LSD_REFINE_NONE = 0, - LSD_REFINE_STD = 1, + { LSD_REFINE_NONE = 0, + LSD_REFINE_STD = 1, LSD_REFINE_ADV = 2 }; @@ -843,35 +843,35 @@ public: /** * Create an LSD object. Specifying scale, number of subdivisions for the image, should the lines be refined and other constants as follows: * - * @param _refine How should the lines found be refined? + * @param _refine How should the lines found be refined? * REFINE_NONE - No refinement applied. - * REFINE_STD - Standard refinement is applied. E.g. breaking arches into smaller line approximations. - * REFINE_ADV - Advanced refinement. Number of false alarms is calculated, + * REFINE_STD - Standard refinement is applied. E.g. breaking arches into smaller line approximations. + * REFINE_ADV - Advanced refinement. Number of false alarms is calculated, * lines are refined through increase of precision, decrement in size, etc. * @param _scale The scale of the image that will be used to find the lines. Range (0..1]. * @param _sigma_scale Sigma for Gaussian filter is computed as sigma = _sigma_scale/_scale. - * @param _quant Bound to the quantization error on the gradient norm. + * @param _quant Bound to the quantization error on the gradient norm. * @param _ang_th Gradient angle tolerance in degrees. * @param _log_eps Detection threshold: -log10(NFA) > _log_eps * @param _density_th Minimal density of aligned region points in rectangle. * @param _n_bins Number of bins in pseudo-ordering of gradient modulus. */ - LSD(lsd_refine_lvl _refine = LSD_REFINE_STD, double _scale = 0.8, - double _sigma_scale = 0.6, double _quant = 2.0, double _ang_th = 22.5, + LSD(lsd_refine_lvl _refine = LSD_REFINE_STD, double _scale = 0.8, + double _sigma_scale = 0.6, double _quant = 2.0, double _ang_th = 22.5, double _log_eps = 0, double _density_th = 0.7, int _n_bins = 1024); /** * Detect lines in the input image with the specified ROI. * - * @param _image A grayscale(CV_8UC1) input image. + * @param _image A grayscale(CV_8UC1) input image. * @param _lines Return: A vector of Vec4i elements specifying the beginning and ending point of a line. - * Where Vec4i is (x1, y1, x2, y2), point 1 is the start, point 2 - end. + * Where Vec4i is (x1, y1, x2, y2), point 1 is the start, point 2 - end. * Returned lines are strictly oriented depending on the gradient. - * @param _roi Return: ROI of the image, where lines are to be found. If specified, the returning + * @param _roi Return: ROI of the image, where lines are to be found. If specified, the returning * lines coordinates are image wise. * @param width Return: Vector of widths of the regions, where the lines are found. E.g. Width of line. * @param prec Return: Vector of precisions with which the lines are found. - * @param nfa Return: Vector containing number of false alarms in the line region, with precision of 10%. + * @param nfa Return: Vector containing number of false alarms in the line region, with precision of 10%. * The bigger the value, logarithmically better the detection. * * -1 corresponds to 10 mean false alarms * * 0 corresponds to 1 mean false alarm @@ -884,16 +884,16 @@ public: /** * Draw lines on the given canvas. * - * @param image The image, where lines will be drawn. + * @param image The image, where lines will be drawn. * Should have the size of the image, where the lines were found * @param lines The lines that need to be drawn - */ + */ static void drawSegments(cv::Mat& image, const std::vector& lines); /** * Draw both vectors on the image canvas. Uses blue for lines 1 and red for lines 2. * - * @param image The image, where lines will be drawn. + * @param image The image, where lines will be drawn. * Should have the size of the image, where the lines were found * @param lines1 The first lines that need to be drawn. Color - Blue. * @param lines2 The second lines that need to be drawn. Color - Red. @@ -905,7 +905,7 @@ private: cv::Mat image; cv::Mat_ scaled_image; double *scaled_image_data; - cv::Mat_ angles; // in rads + cv::Mat_ angles; // in rads double *angles_data; cv::Mat_ modgrad; double *modgrad_data; @@ -956,18 +956,18 @@ private: * Detect lines in the whole input image. * * @param lines Return: A vector of Vec4i elements specifying the beginning and ending point of a line. - * Where Vec4i is (x1, y1, x2, y2), point 1 is the start, point 2 - end. + * Where Vec4i is (x1, y1, x2, y2), point 1 is the start, point 2 - end. * Returned lines are strictly oriented depending on the gradient. * @param widths Return: Vector of widths of the regions, where the lines are found. E.g. Width of line. * @param precisions Return: Vector of precisions with which the lines are found. - * @param nfas Return: Vector containing number of false alarms in the line region, with precision of 10%. + * @param nfas Return: Vector containing number of false alarms in the line region, with precision of 10%. * The bigger the value, logarithmically better the detection. * * -1 corresponds to 10 mean false alarms * * 0 corresponds to 1 mean false alarm * * 1 corresponds to 0.1 mean false alarms */ - void flsd(std::vector& lines, - std::vector* widths, std::vector* precisions, + void flsd(std::vector& lines, + std::vector* widths, std::vector* precisions, std::vector* nfas); /** @@ -975,13 +975,13 @@ private: * * @param threshold The minimum value of the angle that is considered defined, otherwise NOTDEF * @param n_bins The number of bins with which gradients are ordered by, using bucket sort. - * @param list Return: Vector of coordinate points that are pseudo ordered by magnitude. + * @param list Return: Vector of coordinate points that are pseudo ordered by magnitude. * Pixels would be ordered by norm value, up to a precision given by max_grad/n_bins. */ void ll_angle(const double& threshold, const unsigned int& n_bins, std::vector& list); /** - * Grow a region starting from point s with a defined precision, + * Grow a region starting from point s with a defined precision, * returning the containing points size and the angle of the gradients. * * @param s Starting point for the region. @@ -1014,41 +1014,41 @@ private: const double& y, const double& reg_angle, const double& prec) const; /** - * An estimation of the angle tolerance is performed by the standard deviation of the angle at points - * near the region's starting point. Then, a new region is grown starting from the same point, but using the - * estimated angle tolerance. If this fails to produce a rectangle with the right density of region points, + * An estimation of the angle tolerance is performed by the standard deviation of the angle at points + * near the region's starting point. Then, a new region is grown starting from the same point, but using the + * estimated angle tolerance. If this fails to produce a rectangle with the right density of region points, * 'reduce_region_radius' is called to try to satisfy this condition. - */ + */ bool refine(std::vector& reg, int& reg_size, double reg_angle, const double prec, double p, rect& rec, const double& density_th); /** - * Reduce the region size, by elimination the points far from the starting point, until that leads to + * Reduce the region size, by elimination the points far from the starting point, until that leads to * rectangle with the right density of region points or to discard the region if too small. */ bool reduce_region_radius(std::vector& reg, int& reg_size, double reg_angle, const double prec, double p, rect& rec, double density, const double& density_th); -/** +/** * Try some rectangles variations to improve NFA value. Only if the rectangle is not meaningful (i.e., log_nfa <= log_eps). * @return The new NFA value. */ double rect_improve(rect& rec) const; -/** +/** * Calculates the number of correctly aligned points within the rectangle. * @return The new NFA value. */ double rect_nfa(const rect& rec) const; -/** +/** * Computes the NFA values based on the total number of points, points that agree. - * n, k, p are the binomial parameters. + * n, k, p are the binomial parameters. * @return The new NFA value. */ double nfa(const int& n, const int& k, const double& p) const; -/** +/** * Is the point at place 'address' aligned to angle theta, up to precision 'prec'? * @return Whether the point is aligned. */ diff --git a/modules/imgproc/src/lsd.cpp b/modules/imgproc/src/lsd.cpp index fde40daa9..a33cfd076 100644 --- a/modules/imgproc/src/lsd.cpp +++ b/modules/imgproc/src/lsd.cpp @@ -46,25 +46,25 @@ using namespace cv; ///////////////////////////////////////////////////////////////////////////////////////// -// Default LSD parameters +// Default LSD parameters // SIGMA_SCALE 0.6 - Sigma for Gaussian filter is computed as sigma = sigma_scale/scale. -// QUANT 2.0 - Bound to the quantization error on the gradient norm. +// QUANT 2.0 - Bound to the quantization error on the gradient norm. // ANG_TH 22.5 - Gradient angle tolerance in degrees. // LOG_EPS 0.0 - Detection threshold: -log10(NFA) > log_eps // DENSITY_TH 0.7 - Minimal density of region points in rectangle. // N_BINS 1024 - Number of bins in pseudo-ordering of gradient modulus. -// PI +// PI #ifndef M_PI -#define M_PI CV_PI // 3.14159265358979323846 +#define M_PI CV_PI // 3.14159265358979323846 #endif -#define M_3_2_PI (3 * CV_PI) / 2 // 4.71238898038 // 3/2 pi -#define M_2__PI 2 * CV_PI // 6.28318530718 // 2 pi +#define M_3_2_PI (3 * CV_PI) / 2 // 4.71238898038 // 3/2 pi +#define M_2__PI 2 * CV_PI // 6.28318530718 // 2 pi -#define NOTDEF double(-1024.0) // Label for pixels with undefined gradient. +#define NOTDEF double(-1024.0) // Label for pixels with undefined gradient. -#define NOTUSED 0 // Label for pixels not used in yet. -#define USED 1 // Label for pixels already used in detection. +#define NOTUSED 0 // Label for pixels not used in yet. +#define USED 1 // Label for pixels already used in detection. #define RELATIVE_ERROR_FACTOR 100.0 @@ -127,7 +127,7 @@ inline bool AsmallerB_XoverY(const edge& a, const edge& b) else return a.p.x < b.p.x; } -/** +/** * Computes the natural logarithm of the absolute value of * the gamma function of x using Windschitl method. * See http://www.rskey.org/gamma.htm @@ -138,7 +138,7 @@ inline double log_gamma_windschitl(const double& x) + 0.5*x*log(x*sinh(1/x) + 1/(810.0*pow(x, 6.0))); } -/** +/** * Computes the natural logarithm of the absolute value of * the gamma function of x using the Lanczos approximation. * See http://www.rskey.org/gamma.htm @@ -159,8 +159,8 @@ inline double log_gamma_lanczos(const double& x) } /////////////////////////////////////////////////////////////////////////////////////////////////////////////// -LSD::LSD(lsd_refine_lvl _refine, double _scale, double _sigma_scale, double _quant, - double _ang_th, double _log_eps, double _density_th, int _n_bins) +LSD::LSD(lsd_refine_lvl _refine, double _scale, double _sigma_scale, double _quant, + double _ang_th, double _log_eps, double _density_th, int _n_bins) :SCALE(_scale), doRefine(_refine), SIGMA_SCALE(_sigma_scale), QUANT(_quant), ANG_TH(_ang_th), LOG_EPS(_log_eps), DENSITY_TH(_density_th), N_BINS(_n_bins) { @@ -197,7 +197,7 @@ void LSD::detect(const cv::InputArray _image, cv::OutputArray _lines, cv::Rect _ flsd(lines, w, p, n); Mat(lines).copyTo(_lines); - if (w) Mat(*w).copyTo(_width); + if (w) Mat(*w).copyTo(_width); if (p) Mat(*p).copyTo(_prec); if (n) Mat(*n).copyTo(_nfa); @@ -206,15 +206,15 @@ void LSD::detect(const cv::InputArray _image, cv::OutputArray _lines, cv::Rect _ delete n; } -void LSD::flsd(std::vector& lines, - std::vector* widths, std::vector* precisions, +void LSD::flsd(std::vector& lines, + std::vector* widths, std::vector* precisions, std::vector* nfas) { // Angle tolerance const double prec = M_PI * ANG_TH / 180; const double p = ANG_TH / 180; const double rho = QUANT / sin(prec); // gradient magnitude threshold - + std::vector list; if (SCALE != 1) { @@ -222,7 +222,7 @@ void LSD::flsd(std::vector& lines, const double sigma = (SCALE < 1)?(SIGMA_SCALE / SCALE):(SIGMA_SCALE); const double sprec = 3; const unsigned int h = (unsigned int)(ceil(sigma * sqrt(2 * sprec * log(10.0)))); - Size ksize(1 + 2 * h, 1 + 2 * h); // kernel size + Size ksize(1 + 2 * h, 1 + 2 * h); // kernel size GaussianBlur(image, gaussian_img, ksize, sigma); // Scale image to needed size resize(gaussian_img, scaled_image, Size(), SCALE, SCALE); @@ -235,14 +235,14 @@ void LSD::flsd(std::vector& lines, } LOG_NT = 5 * (log10(double(img_width)) + log10(double(img_height))) / 2 + log10(11.0); - const int min_reg_size = int(-LOG_NT/log10(p)); // minimal number of points in region that can give a meaningful event - + const int min_reg_size = int(-LOG_NT/log10(p)); // minimal number of points in region that can give a meaningful event + // // Initialize region only when needed // Mat region = Mat::zeros(scaled_image.size(), CV_8UC1); used = Mat_::zeros(scaled_image.size()); // zeros = NOTUSED std::vector reg(img_width * img_height); - - // Search for line segments + + // Search for line segments unsigned int ls_count = 0; unsigned int list_size = list.size(); for(unsigned int i = 0; i < list_size; ++i) @@ -253,10 +253,10 @@ void LSD::flsd(std::vector& lines, int reg_size; double reg_angle; region_grow(list[i].p, reg, reg_size, reg_angle, prec); - + // Ignore small regions if(reg_size < min_reg_size) { continue; } - + // Construct rectangular approximation for the region rect rec; region2rect(reg, reg_size, reg_angle, prec, p, rec); @@ -288,7 +288,7 @@ void LSD::flsd(std::vector& lines, rec.x2 /= SCALE; rec.y2 /= SCALE; rec.width /= SCALE; } - + if(roi.area()) // if a roi has been given by the user, adjust coordinates { rec.x1 += roix; @@ -308,11 +308,8 @@ void LSD::flsd(std::vector& lines, // { // region.data[reg[i].x + reg[i].y * width] = ls_count; // } - } - } - } void LSD::ll_angle(const double& threshold, const unsigned int& n_bins, std::vector& list) @@ -320,21 +317,21 @@ void LSD::ll_angle(const double& threshold, const unsigned int& n_bins, std::vec //Initialize data angles = cv::Mat_(scaled_image.size()); modgrad = cv::Mat_(scaled_image.size()); - + angles_data = angles.ptr(0); modgrad_data = modgrad.ptr(0); scaled_image_data = scaled_image.ptr(0); - img_width = scaled_image.cols; + img_width = scaled_image.cols; img_height = scaled_image.rows; - // Undefined the down and right boundaries + // Undefined the down and right boundaries angles.row(img_height - 1).setTo(NOTDEF); angles.col(img_width - 1).setTo(NOTDEF); - + // Computing gradient for remaining pixels - CV_Assert(scaled_image.isContinuous() && - modgrad.isContinuous() && + CV_Assert(scaled_image.isContinuous() && + modgrad.isContinuous() && angles.isContinuous()); // Accessing image data linearly double max_grad = -1; @@ -344,13 +341,13 @@ void LSD::ll_angle(const double& threshold, const unsigned int& n_bins, std::vec { double DA = scaled_image_data[addr + img_width + 1] - scaled_image_data[addr]; double BC = scaled_image_data[addr + 1] - scaled_image_data[addr + img_width]; - double gx = DA + BC; // gradient x component - double gy = DA - BC; // gradient y component - double norm = std::sqrt((gx * gx + gy * gy) / 4); // gradient norm - + double gx = DA + BC; // gradient x component + double gy = DA - BC; // gradient y component + double norm = std::sqrt((gx * gx + gy * gy) / 4); // gradient norm + modgrad_data[addr] = norm; // store gradient - if (norm <= threshold) // norm too small, gradient no defined + if (norm <= threshold) // norm too small, gradient no defined { angles_data[addr] = NOTDEF; } @@ -362,7 +359,7 @@ void LSD::ll_angle(const double& threshold, const unsigned int& n_bins, std::vec } } - + // Compute histogram of gradient values list = std::vector(img_width * img_height); std::vector range_s(n_bins); @@ -375,7 +372,7 @@ void LSD::ll_angle(const double& threshold, const unsigned int& n_bins, std::vec const double* norm = modgrad_data + y * img_width; for(int x = 0; x < img_width - 1; ++x, ++norm) { - // Store the point in the right bin according to its norm + // Store the point in the right bin according to its norm int i = int((*norm) * bin_coef); if(!range_e[i]) { @@ -480,7 +477,7 @@ void LSD::region2rect(const std::vector& reg, const int reg_size, c // Weighted sum must differ from 0 CV_Assert(sum > 0); - + x /= sum; y /= sum; @@ -495,7 +492,7 @@ void LSD::region2rect(const std::vector& reg, const int reg_size, c { double regdx = double(reg[i].x) - x; double regdy = double(reg[i].y) - y; - + double l = regdx * dx + regdy * dy; double w = -regdx * dy + regdy * dx; @@ -530,10 +527,10 @@ double LSD::get_theta(const std::vector& reg, const int& reg_size, double Iyy = 0.0; double Ixy = 0.0; - // Compute inertia matrix + // Compute inertia matrix for(int i = 0; i < reg_size; ++i) { - const double& regx = reg[i].x; + const double& regx = reg[i].x; const double& regy = reg[i].y; const double& weight = reg[i].modgrad; double dx = regx - x; @@ -554,7 +551,7 @@ double LSD::get_theta(const std::vector& reg, const int& reg_size, cv::fastAtan2(lambda - Ixx, Ixy):cv::fastAtan2(Ixy, lambda - Iyy); // in degs theta *= DEG_TO_RADS; - // Correct angle by 180 deg if necessary + // Correct angle by 180 deg if necessary if(angle_diff(theta, reg_angle) > prec) { theta += M_PI; } return theta; @@ -588,7 +585,7 @@ bool LSD::refine(std::vector& reg, int& reg_size, double reg_angle, } double mean_angle = sum / double(n); // 2 * standard deviation - double tau = 2.0 * sqrt((s_sum - 2.0 * mean_angle * sum) / double(n) + mean_angle * mean_angle); + double tau = 2.0 * sqrt((s_sum - 2.0 * mean_angle * sum) / double(n) + mean_angle * mean_angle); // Try new region region_grow(Point(reg[0].x, reg[0].y), reg, reg_size, reg_angle, tau); @@ -598,8 +595,8 @@ bool LSD::refine(std::vector& reg, int& reg_size, double reg_angle, region2rect(reg, reg_size, reg_angle, prec, p, rec); density = double(reg_size) / (dist(rec.x1, rec.y1, rec.x2, rec.y2) * rec.width); - if (density < density_th) - { + if (density < density_th) + { return reduce_region_radius(reg, reg_size, reg_angle, prec, p, rec, density, density_th); } else @@ -621,22 +618,22 @@ bool LSD::reduce_region_radius(std::vector& reg, int& reg_size, dou while(density < density_th) { radSq *= 0.75*0.75; // Reduce region's radius to 75% of its value - // Remove points from the region and update 'used' map + // Remove points from the region and update 'used' map for(int i = 0; i < reg_size; ++i) { if(distSq(xc, yc, double(reg[i].x), double(reg[i].y)) > radSq) { - // Remove point from the region + // Remove point from the region *(reg[i].used) = NOTUSED; std::swap(reg[i], reg[reg_size - 1]); --reg_size; - --i; // To avoid skipping one point + --i; // To avoid skipping one point } } if(reg_size < 2) { return false; } - // Re-compute rectangle + // Re-compute rectangle region2rect(reg, reg_size ,reg_angle, prec, p, rec); // Re-compute region points density @@ -687,7 +684,7 @@ double LSD::rect_improve(rect& rec) const } } if(log_nfa > LOG_EPS) return log_nfa; - + // Try to reduce one side of rectangle r = rect(rec); for(unsigned int n = 0; n < 5; ++n) @@ -765,9 +762,9 @@ double LSD::rect_nfa(const rect& rec) const ordered_x[1].p.x = rec.x2 - dyhw; ordered_x[1].p.y = rec.y2 + dxhw; ordered_x[1].taken = false; ordered_x[2].p.x = rec.x2 + dyhw; ordered_x[2].p.y = rec.y2 - dxhw; ordered_x[2].taken = false; ordered_x[3].p.x = rec.x1 + dyhw; ordered_x[3].p.y = rec.y1 - dxhw; ordered_x[3].taken = false; - + std::sort(ordered_x.begin(), ordered_x.end(), AsmallerB_XoverY); - + // Find min y. And mark as taken. find max y. for(unsigned int i = 1; i < 4; ++i) { @@ -782,7 +779,7 @@ double LSD::rect_nfa(const rect& rec) const { if(!ordered_x[i].taken) { - if(!leftmost) // if uninitialized + if(!leftmost) // if uninitialized { leftmost = &ordered_x[i]; } @@ -800,7 +797,7 @@ double LSD::rect_nfa(const rect& rec) const { if(!ordered_x[i].taken) { - if(!rightmost) // if uninitialized + if(!rightmost) // if uninitialized { rightmost = &ordered_x[i]; } @@ -818,7 +815,7 @@ double LSD::rect_nfa(const rect& rec) const { if(!ordered_x[i].taken) { - if(!tailp) // if uninitialized + if(!tailp) // if uninitialized { tailp = &ordered_x[i]; } @@ -830,20 +827,20 @@ double LSD::rect_nfa(const rect& rec) const } tailp->taken = true; - double flstep = (min_y->p.y != leftmost->p.y) ? + double flstep = (min_y->p.y != leftmost->p.y) ? (min_y->p.x - leftmost->p.x) / (min_y->p.y - leftmost->p.y) : 0; //first left step - double slstep = (leftmost->p.y != tailp->p.x) ? + double slstep = (leftmost->p.y != tailp->p.x) ? (leftmost->p.x - tailp->p.x) / (leftmost->p.y - tailp->p.x) : 0; //second left step - - double frstep = (min_y->p.y != rightmost->p.y) ? + + double frstep = (min_y->p.y != rightmost->p.y) ? (min_y->p.x - rightmost->p.x) / (min_y->p.y - rightmost->p.y) : 0; //first right step - double srstep = (rightmost->p.y != tailp->p.x) ? + double srstep = (rightmost->p.y != tailp->p.x) ? (rightmost->p.x - tailp->p.x) / (rightmost->p.y - tailp->p.x) : 0; //second right step - + double lstep = flstep, rstep = frstep; - int left_x = min_y->p.x, right_x = min_y->p.x; - + int left_x = min_y->p.x, right_x = min_y->p.x; + // Loop around all points in the region and count those that are aligned. int min_iter = std::max(min_y->p.y, 0); int max_iter = std::min(max_y->p.y, img_height - 1); @@ -872,7 +869,7 @@ double LSD::rect_nfa(const rect& rec) const double LSD::nfa(const int& n, const int& k, const double& p) const { // Trivial cases - if(n == 0 || k == 0) { return -LOG_NT; } + if(n == 0 || k == 0) { return -LOG_NT; } if(n == k) { return -LOG_NT - double(n) * log10(p); } double p_term = p / (1 - p); @@ -882,7 +879,7 @@ double LSD::nfa(const int& n, const int& k, const double& p) const + double(k) * log(p) + double(n-k) * log(1.0 - p); double term = exp(log1term); - if(double_equal(term, 0)) + if(double_equal(term, 0)) { if(k > n * p) return -log1term / M_LN10 - LOG_NT; else return -LOG_NT; @@ -913,7 +910,7 @@ inline bool LSD::isAligned(const int& address, const double& theta, const double const double& a = angles_data[address]; if(a == NOTDEF) { return false; } - // It is assumed that 'theta' and 'a' are in the range [-pi,pi] + // It is assumed that 'theta' and 'a' are in the range [-pi,pi] double n_theta = theta - a; if(n_theta < 0) { n_theta = -n_theta; } if(n_theta > M_3_2_PI) @@ -939,7 +936,7 @@ void LSD::drawSegments(cv::Mat& image, const std::vector& lines) { cv::cvtColor(image, gray, CV_BGR2GRAY); } - + // Create a 3 channel image in order to draw colored lines std::vector planes; planes.push_back(gray); @@ -991,10 +988,10 @@ int LSD::compareSegments(const cv::Size& size, const std::vector& lin Mat Ig; if (image->channels() == 1) { - cv::cvtColor(*image, *image, CV_GRAY2BGR); + cv::cvtColor(*image, *image, CV_GRAY2BGR); } CV_Assert(image->isContinuous() && I1.isContinuous() && I2.isContinuous()); - + for (unsigned int i = 0; i < I1.total(); ++i) { uchar i1 = I1.data[i]; diff --git a/modules/imgproc/test/test_lsd.cpp b/modules/imgproc/test/test_lsd.cpp index 1f0b5051a..5092955e2 100644 --- a/modules/imgproc/test/test_lsd.cpp +++ b/modules/imgproc/test/test_lsd.cpp @@ -13,20 +13,20 @@ public: LSDBase() {}; protected: - Mat test_image; - vector lines; + Mat test_image; + vector lines; - void GenerateWhiteNoise(Mat& image); - void GenerateConstColor(Mat& image); - void GenerateLines(Mat& image, const unsigned int numLines); - void GenerateRotatedRect(Mat& image); - virtual void SetUp(); + void GenerateWhiteNoise(Mat& image); + void GenerateConstColor(Mat& image); + void GenerateLines(Mat& image, const unsigned int numLines); + void GenerateRotatedRect(Mat& image); + virtual void SetUp(); }; class LSD_ADV: public LSDBase { public: - LSD_ADV() {}; + LSD_ADV() {}; protected: }; @@ -34,7 +34,7 @@ protected: class LSD_STD: public LSDBase { public: - LSD_STD() {}; + LSD_STD() {}; protected: }; @@ -42,171 +42,171 @@ protected: class LSD_NONE: public LSDBase { public: - LSD_NONE() {}; + LSD_NONE() {}; protected: }; void LSDBase::GenerateWhiteNoise(Mat& image) { - image = Mat(img_size, CV_8UC1); - RNG rng(getTickCount()); - rng.fill(image, RNG::UNIFORM, 0, 256); + image = Mat(img_size, CV_8UC1); + RNG rng(getTickCount()); + rng.fill(image, RNG::UNIFORM, 0, 256); } void LSDBase::GenerateConstColor(Mat& image) { - RNG rng(getTickCount()); - image = Mat(img_size, CV_8UC1, Scalar::all(rng.uniform(0, 256))); + RNG rng(getTickCount()); + image = Mat(img_size, CV_8UC1, Scalar::all(rng.uniform(0, 256))); } void LSDBase::GenerateLines(Mat& image, const unsigned int numLines) { - RNG rng(getTickCount()); - image = Mat(img_size, CV_8UC1, Scalar::all(rng.uniform(0, 128))); - - for(unsigned int i = 0; i < numLines; ++i) - { - int y = rng.uniform(10, img_size.width - 10); - Point p1(y, 10); - Point p2(y, img_size.height - 10); - line(image, p1, p2, Scalar(255), 1); - } + RNG rng(getTickCount()); + image = Mat(img_size, CV_8UC1, Scalar::all(rng.uniform(0, 128))); + + for(unsigned int i = 0; i < numLines; ++i) + { + int y = rng.uniform(10, img_size.width - 10); + Point p1(y, 10); + Point p2(y, img_size.height - 10); + line(image, p1, p2, Scalar(255), 1); + } } void LSDBase::GenerateRotatedRect(Mat& image) { - RNG rng(getTickCount()); - image = Mat::zeros(img_size, CV_8UC1); - - Point center(rng.uniform(img_size.width/4, img_size.width*3/4), - rng.uniform(img_size.height/4, img_size.height*3/4)); - Size rect_size(rng.uniform(img_size.width/8, img_size.width/6), - rng.uniform(img_size.height/8, img_size.height/6)); - float angle = rng.uniform(0, 360); - - Point2f vertices[4]; - - RotatedRect rRect = RotatedRect(center, rect_size, angle); + RNG rng(getTickCount()); + image = Mat::zeros(img_size, CV_8UC1); - rRect.points(vertices); - for (int i = 0; i < 4; i++) - { - line(image, vertices[i], vertices[(i + 1) % 4], Scalar(255)); - } + Point center(rng.uniform(img_size.width/4, img_size.width*3/4), + rng.uniform(img_size.height/4, img_size.height*3/4)); + Size rect_size(rng.uniform(img_size.width/8, img_size.width/6), + rng.uniform(img_size.height/8, img_size.height/6)); + float angle = rng.uniform(0, 360); + + Point2f vertices[4]; + + RotatedRect rRect = RotatedRect(center, rect_size, angle); + + rRect.points(vertices); + for (int i = 0; i < 4; i++) + { + line(image, vertices[i], vertices[(i + 1) % 4], Scalar(255)); + } } void LSDBase::SetUp() { - lines.clear(); - test_image = Mat(); + lines.clear(); + test_image = Mat(); } TEST_F(LSD_ADV, whiteNoise) { - GenerateWhiteNoise(test_image); - LSD detector(LSD_REFINE_ADV); - detector.detect(test_image, lines); + GenerateWhiteNoise(test_image); + LSD detector(LSD_REFINE_ADV); + detector.detect(test_image, lines); - ASSERT_GE((unsigned int)(40), lines.size()); + ASSERT_GE((unsigned int)(40), lines.size()); } TEST_F(LSD_ADV, constColor) { - GenerateConstColor(test_image); - LSD detector(LSD_REFINE_ADV); - detector.detect(test_image, lines); + GenerateConstColor(test_image); + LSD detector(LSD_REFINE_ADV); + detector.detect(test_image, lines); - ASSERT_EQ((unsigned int)(0), lines.size()); + ASSERT_EQ((unsigned int)(0), lines.size()); } TEST_F(LSD_ADV, lines) { - const unsigned int numOfLines = 3; - GenerateLines(test_image, numOfLines); - LSD detector(LSD_REFINE_ADV); - detector.detect(test_image, lines); + const unsigned int numOfLines = 3; + GenerateLines(test_image, numOfLines); + LSD detector(LSD_REFINE_ADV); + detector.detect(test_image, lines); - ASSERT_EQ(numOfLines * 2, lines.size()); // * 2 because of Gibbs effect + ASSERT_EQ(numOfLines * 2, lines.size()); // * 2 because of Gibbs effect } TEST_F(LSD_ADV, rotatedRect) { - GenerateRotatedRect(test_image); - LSD detector(LSD_REFINE_ADV); - detector.detect(test_image, lines); - ASSERT_LE((unsigned int)(4), lines.size()); + GenerateRotatedRect(test_image); + LSD detector(LSD_REFINE_ADV); + detector.detect(test_image, lines); + ASSERT_LE((unsigned int)(4), lines.size()); } TEST_F(LSD_STD, whiteNoise) { - GenerateWhiteNoise(test_image); - LSD detector(LSD_REFINE_STD); - detector.detect(test_image, lines); + GenerateWhiteNoise(test_image); + LSD detector(LSD_REFINE_STD); + detector.detect(test_image, lines); - ASSERT_GE((unsigned int)(50), lines.size()); + ASSERT_GE((unsigned int)(50), lines.size()); } TEST_F(LSD_STD, constColor) { - GenerateConstColor(test_image); - LSD detector(LSD_REFINE_STD); - detector.detect(test_image, lines); + GenerateConstColor(test_image); + LSD detector(LSD_REFINE_STD); + detector.detect(test_image, lines); - ASSERT_EQ((unsigned int)(0), lines.size()); + ASSERT_EQ((unsigned int)(0), lines.size()); } TEST_F(LSD_STD, lines) { - const unsigned int numOfLines = 3; //1 - GenerateLines(test_image, numOfLines); - LSD detector(LSD_REFINE_STD); - detector.detect(test_image, lines); + const unsigned int numOfLines = 3; //1 + GenerateLines(test_image, numOfLines); + LSD detector(LSD_REFINE_STD); + detector.detect(test_image, lines); - ASSERT_EQ(numOfLines * 2, lines.size()); // * 2 because of Gibbs effect + ASSERT_EQ(numOfLines * 2, lines.size()); // * 2 because of Gibbs effect } TEST_F(LSD_STD, rotatedRect) { - GenerateRotatedRect(test_image); - LSD detector(LSD_REFINE_STD); - detector.detect(test_image, lines); - ASSERT_EQ((unsigned int)(8), lines.size()); + GenerateRotatedRect(test_image); + LSD detector(LSD_REFINE_STD); + detector.detect(test_image, lines); + ASSERT_EQ((unsigned int)(8), lines.size()); } TEST_F(LSD_NONE, whiteNoise) { - GenerateWhiteNoise(test_image); - LSD detector(LSD_REFINE_NONE); - detector.detect(test_image, lines); + GenerateWhiteNoise(test_image); + LSD detector(LSD_REFINE_NONE); + detector.detect(test_image, lines); - ASSERT_GE((unsigned int)(50), lines.size()); + ASSERT_GE((unsigned int)(50), lines.size()); } TEST_F(LSD_NONE, constColor) { - GenerateConstColor(test_image); - LSD detector(LSD_REFINE_NONE); - detector.detect(test_image, lines); + GenerateConstColor(test_image); + LSD detector(LSD_REFINE_NONE); + detector.detect(test_image, lines); - ASSERT_EQ((unsigned int)(0), lines.size()); + ASSERT_EQ((unsigned int)(0), lines.size()); } TEST_F(LSD_NONE, lines) { - const unsigned int numOfLines = 3; //1 - GenerateLines(test_image, numOfLines); - LSD detector(LSD_REFINE_NONE); - detector.detect(test_image, lines); + const unsigned int numOfLines = 3; //1 + GenerateLines(test_image, numOfLines); + LSD detector(LSD_REFINE_NONE); + detector.detect(test_image, lines); - ASSERT_EQ(numOfLines * 2, lines.size()); // * 2 because of Gibbs effect + ASSERT_EQ(numOfLines * 2, lines.size()); // * 2 because of Gibbs effect } TEST_F(LSD_NONE, rotatedRect) { - GenerateRotatedRect(test_image); - LSD detector(LSD_REFINE_NONE); - detector.detect(test_image, lines); - ASSERT_EQ((unsigned int)(8), lines.size()); + GenerateRotatedRect(test_image); + LSD detector(LSD_REFINE_NONE); + detector.detect(test_image, lines); + ASSERT_EQ((unsigned int)(8), lines.size()); } diff --git a/samples/cpp/lsd_lines.cpp b/samples/cpp/lsd_lines.cpp index 03547dda8..f74c7d9f6 100644 --- a/samples/cpp/lsd_lines.cpp +++ b/samples/cpp/lsd_lines.cpp @@ -2,6 +2,7 @@ #include #include "opencv2/core/core.hpp" +#include "opencv2/core/utility.hpp" #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/highgui/highgui.hpp" @@ -10,41 +11,41 @@ using namespace cv; int main(int argc, char** argv) { - if (argc != 2) - { - std::cout << "lsd_lines [input image]" << std::endl; - return false; - } - - std::string in = argv[1]; + if (argc != 2) + { + std::cout << "lsd_lines [input image]" << std::endl; + return false; + } - Mat image = imread(in, CV_LOAD_IMAGE_GRAYSCALE); + std::string in = argv[1]; - // Create and LSD detector with std refinement. - LSD lsd_std(LSD_REFINE_STD); - double start = double(getTickCount()); - vector lines_std; - lsd_std.detect(image, lines_std); - double duration_ms = (double(getTickCount()) - start) * 1000 / getTickFrequency(); - std::cout << "OpenCV STD (blue) - " << duration_ms << " ms." << std::endl; - - // Create an LSD detector with no refinement applied. - LSD lsd_none(LSD_REFINE_NONE); - start = double(getTickCount()); - vector lines_none; - lsd_none.detect(image, lines_none); - duration_ms = (double(getTickCount()) - start) * 1000 / getTickFrequency(); - std::cout << "OpenCV NONE (red)- " << duration_ms << " ms." << std::endl; - std::cout << "Overlapping pixels are shown in purple." << std::endl; - - Mat difference = Mat::zeros(image.size(), CV_8UC1); - LSD::compareSegments(image.size(), lines_std, lines_none, &difference); - imshow("Line difference", difference); + Mat image = imread(in, IMREAD_GRAYSCALE); - Mat drawnLines(image); - LSD::drawSegments(drawnLines, lines_std); - imshow("Standard refinement", drawnLines); + // Create and LSD detector with std refinement. + LSD lsd_std(LSD_REFINE_STD); + double start = double(getTickCount()); + vector lines_std; + lsd_std.detect(image, lines_std); + double duration_ms = (double(getTickCount()) - start) * 1000 / getTickFrequency(); + std::cout << "OpenCV STD (blue) - " << duration_ms << " ms." << std::endl; - waitKey(); - return 0; + // Create an LSD detector with no refinement applied. + LSD lsd_none(LSD_REFINE_NONE); + start = double(getTickCount()); + vector lines_none; + lsd_none.detect(image, lines_none); + duration_ms = (double(getTickCount()) - start) * 1000 / getTickFrequency(); + std::cout << "OpenCV NONE (red)- " << duration_ms << " ms." << std::endl; + std::cout << "Overlapping pixels are shown in purple." << std::endl; + + Mat difference = Mat::zeros(image.size(), CV_8UC1); + LSD::compareSegments(image.size(), lines_std, lines_none, &difference); + imshow("Line difference", difference); + + Mat drawnLines(image); + LSD::drawSegments(drawnLines, lines_std); + imshow("Standard refinement", drawnLines); + + waitKey(); + return 0; }