From 6132943a39802f1279d5d70631ff81665bb49cae Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Fri, 9 Nov 2018 07:07:12 +0000 Subject: [PATCH 1/6] xfeatures2d: validate keypoints mask for SURF --- modules/xfeatures2d/src/surf.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/modules/xfeatures2d/src/surf.cpp b/modules/xfeatures2d/src/surf.cpp index 435380c53..c81a56b3c 100644 --- a/modules/xfeatures2d/src/surf.cpp +++ b/modules/xfeatures2d/src/surf.cpp @@ -944,6 +944,19 @@ void SURF_Impl::detectAndCompute(InputArray _img, InputArray _mask, integral(mask1, msum, CV_32S); } fastHessianDetector( sum, msum, keypoints, nOctaves, nOctaveLayers, (float)hessianThreshold ); + if (!mask.empty()) + { + for (size_t i = 0; i < keypoints.size(); ) + { + Point pt(keypoints[i].pt); + if (mask.at(pt.y, pt.x) == 0) + { + keypoints.erase(keypoints.begin() + i); + continue; // keep "i" + } + i++; + } + } } int i, j, N = (int)keypoints.size(); From 6e3eea54470ff5a1df037f0622afa9a20bcadc80 Mon Sep 17 00:00:00 2001 From: Jukka Komulainen Date: Fri, 9 Nov 2018 19:01:41 +0200 Subject: [PATCH 2/6] Merge pull request #1883 from ytyytyyt:3.4 * add fast bilateral solver from master * fix unused variables warnings in disparity_filtering.cpp * trailing whitespaces removed --- modules/ximgproc/doc/ximgproc.bib | 9 + .../include/opencv2/ximgproc/edge_filter.hpp | 65 ++ modules/ximgproc/samples/colorize.cpp | 417 ++++++++++++ .../ximgproc/samples/disparity_filtering.cpp | 137 +++- modules/ximgproc/src/fbs_filter.cpp | 632 ++++++++++++++++++ modules/ximgproc/test/test_fbs_filter.cpp | 114 ++++ 6 files changed, 1369 insertions(+), 5 deletions(-) create mode 100644 modules/ximgproc/samples/colorize.cpp create mode 100644 modules/ximgproc/src/fbs_filter.cpp create mode 100644 modules/ximgproc/test/test_fbs_filter.cpp diff --git a/modules/ximgproc/doc/ximgproc.bib b/modules/ximgproc/doc/ximgproc.bib index 7bc1c6c0b..b1c7ae0c4 100644 --- a/modules/ximgproc/doc/ximgproc.bib +++ b/modules/ximgproc/doc/ximgproc.bib @@ -301,3 +301,12 @@ url = {http://reference.wolfram.com/language/ref/RidgeFilter.html} } + +@inproceedings{BarronPoole2016, +author = {Jonathan T Barron and Ben Poole}, +title={The Fast Bilateral Solver}, +booktitle={European Conference on Computer Vision (ECCV)}, +year={2016}, +publisher={Springer International Publishing}, +pages={617--632}, +} diff --git a/modules/ximgproc/include/opencv2/ximgproc/edge_filter.hpp b/modules/ximgproc/include/opencv2/ximgproc/edge_filter.hpp index 65cff9e4d..c6fe6525d 100644 --- a/modules/ximgproc/include/opencv2/ximgproc/edge_filter.hpp +++ b/modules/ximgproc/include/opencv2/ximgproc/edge_filter.hpp @@ -375,6 +375,71 @@ void rollingGuidanceFilter(InputArray src, OutputArray dst, int d = -1, double s ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// +/** @brief Interface for implementations of The Fast Bilateral Solver. + +For more details about this solver see @cite BarronPoole2016 . +*/ +class CV_EXPORTS_W FastBilateralSolverFilter : public Algorithm +{ +public: + /** @brief Apply smoothing operation to the source image. + + @param src source image for filtering with unsigned 8-bit or signed 16-bit or floating-point 32-bit depth and up to 3 channels. + + @param confidence confidence image with unsigned 8-bit or floating-point 32-bit confidence and 1 channel. + + @param dst destination image. + */ + CV_WRAP virtual void filter(InputArray src, InputArray confidence, OutputArray dst) = 0; +}; + +/** @brief Factory method, create instance of FastBilateralSolverFilter and execute the initialization routines. + +@param guide image serving as guide for filtering. It should have 8-bit depth and either 1 or 3 channels. + +@param sigma_spatial parameter, that is similar to spatial space sigma in bilateralFilter. + +@param sigma_luma parameter, that is similar to luma space sigma in bilateralFilter. + +@param sigma_chroma parameter, that is similar to chroma space sigma in bilateralFilter. + +@param num_iter number of iterations used for solving, 25 is usually enough. + +@param max_tol solving tolerance used for solving. + +For more details about the Fast Bilateral Solver parameters, see the original paper @cite BarronPoole2016. + +*/ +CV_EXPORTS_W Ptr createFastBilateralSolverFilter(InputArray guide, double sigma_spatial, double sigma_luma, double sigma_chroma, int num_iter = 25, double max_tol = 1e-5); + +/** @brief Simple one-line Fast Bilateral Solver filter call. If you have multiple images to filter with the same +guide then use FastBilateralSolverFilter interface to avoid extra computations. + +@param guide image serving as guide for filtering. It should have 8-bit depth and either 1 or 3 channels. + +@param src source image for filtering with unsigned 8-bit or signed 16-bit or floating-point 32-bit depth and up to 4 channels. + +@param confidence confidence image with unsigned 8-bit or floating-point 32-bit confidence and 1 channel. + +@param dst destination image. + +@param sigma_spatial parameter, that is similar to spatial space sigma in bilateralFilter. + +@param sigma_luma parameter, that is similar to luma space sigma in bilateralFilter. + +@param sigma_chroma parameter, that is similar to chroma space sigma in bilateralFilter. + +@param num_iter number of iterations used for solving, 25 is usually enough. + +@param max_tol solving tolerance used for solving. + +@note Confidence images with CV_8U depth are expected to in [0, 255] and CV_32F in [0, 1] range. +*/ +CV_EXPORTS_W void fastBilateralSolverFilter(InputArray guide, InputArray src, InputArray confidence, OutputArray dst, double sigma_spatial = 8, double sigma_luma = 8, double sigma_chroma = 8, int num_iter = 25, double max_tol = 1e-5); + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + /** @brief Interface for implementations of Fast Global Smoother filter. diff --git a/modules/ximgproc/samples/colorize.cpp b/modules/ximgproc/samples/colorize.cpp new file mode 100644 index 000000000..0887f7e7c --- /dev/null +++ b/modules/ximgproc/samples/colorize.cpp @@ -0,0 +1,417 @@ + +#include "opencv2/core.hpp" +#include "opencv2/highgui.hpp" +#include "opencv2/imgproc.hpp" +#include "opencv2/core/utility.hpp" + +#include +#include +#include +#include + + + +using namespace cv; + +#ifdef HAVE_EIGEN + +#define MARK_RADIUS 5 +#define PALLET_RADIUS 100 +int max_width = 1280; +int max_height = 720; + +static int globalMouseX; +static int globalMouseY; +static int selected_r; +static int selected_g; +static int selected_b; +static bool globalMouseClick = false; +static bool glb_mouse_left = false; +static bool drawByReference = false; +static bool mouseDraw = false; +static bool mouseClick; +static bool mouseLeft; +static int mouseX; +static int mouseY; + +cv::Mat mat_draw; +cv::Mat mat_input_gray; +cv::Mat mat_input_reference; +cv::Mat mat_input_confidence; +cv::Mat mat_pallet(PALLET_RADIUS*2,PALLET_RADIUS*2,CV_8UC3); + + +static void mouseCallback(int event, int x, int y, int flags, void* param); +void drawTrajectoryByReference(cv::Mat& img); +double module(Point pt); +double distance(Point pt1, Point pt2); +double cross(Point pt1, Point pt2); +double angle(Point pt1, Point pt2); +int inCircle(Point p, Point c, int r); +void createPlate(Mat &im1, int radius); + + +#endif + +const String keys = + "{help h usage ? | | print this message }" + "{@image | | input image }" + "{sigma_spatial |8 | parameter of post-filtering }" + "{sigma_luma |8 | parameter of post-filtering }" + "{sigma_chroma |8 | parameter of post-filtering }" + "{dst_path |None | optional path to save the resulting colorized image }" + "{dst_raw_path |None | optional path to save drawed image before filtering }" + "{draw_by_reference |false | optional flag to use color image as reference }" + ; + + + +int main(int argc, char* argv[]) +{ + + CommandLineParser parser(argc,argv,keys); + parser.about("fastBilateralSolverFilter Demo"); + if (parser.has("help")) + { + parser.printMessage(); + return 0; + } + +#ifdef HAVE_EIGEN + + String img = parser.get(0); + double sigma_spatial = parser.get("sigma_spatial"); + double sigma_luma = parser.get("sigma_luma"); + double sigma_chroma = parser.get("sigma_chroma"); + String dst_path = parser.get("dst_path"); + String dst_raw_path = parser.get("dst_raw_path"); + drawByReference = parser.get("draw_by_reference"); + + mat_input_reference = cv::imread(img, IMREAD_COLOR); + if (mat_input_reference.empty()) + { + std::cerr << "input image '" << img << "' could not be read !" << std::endl << std::endl; + parser.printMessage(); + return 1; + } + + cvtColor(mat_input_reference, mat_input_gray, COLOR_BGR2GRAY); + + if(mat_input_gray.cols > max_width) + { + double scale = float(max_width) / float(mat_input_gray.cols); + cv::resize(mat_input_reference, mat_input_reference, cv::Size(), scale, scale); + cv::resize(mat_input_gray, mat_input_gray, cv::Size(), scale, scale); + } + + if(mat_input_gray.rows > max_height) + { + double scale = float(max_height) / float(mat_input_gray.rows); + cv::resize(mat_input_reference, mat_input_reference, cv::Size(), scale, scale); + cv::resize(mat_input_gray, mat_input_gray, cv::Size(), scale, scale); + } + + + float filtering_time; + std::cout << "mat_input_reference:" << mat_input_reference.cols<<"x"<< mat_input_reference.rows<< std::endl; + std::cout << "please select a color from the palette, by clicking into that," << std::endl; + std::cout << " then select a coarse region in the image to be coloured." << std::endl; + std::cout << " press 'escape' to see the final coloured image." << std::endl; + + + cv::Mat mat_gray; + cv::cvtColor(mat_input_reference, mat_gray, cv::COLOR_BGR2GRAY); + + cv::Mat target = mat_input_reference.clone(); + cvtColor(mat_gray, mat_input_reference, COLOR_GRAY2BGR); + + cv::namedWindow("draw", cv::WINDOW_AUTOSIZE); + + // construct pallet + createPlate(mat_pallet, PALLET_RADIUS); + selected_b = 0; + selected_g = 0; + selected_r = 0; + + cv::Mat mat_show(target.rows,target.cols+PALLET_RADIUS*2,CV_8UC3); + cv::Mat color_select(target.rows-mat_pallet.rows,PALLET_RADIUS*2,CV_8UC3,cv::Scalar(selected_b, selected_g, selected_r)); + target.copyTo(Mat(mat_show,Rect(0,0,target.cols,target.rows))); + mat_pallet.copyTo(Mat(mat_show,Rect(target.cols,0,mat_pallet.cols,mat_pallet.rows))); + color_select.copyTo(Mat(mat_show,Rect(target.cols,PALLET_RADIUS*2,color_select.cols,color_select.rows))); + + cv::imshow("draw", mat_show); + cv::setMouseCallback("draw", mouseCallback, (void *)&mat_show); + mat_input_confidence = 0*cv::Mat::ones(mat_gray.size(),mat_gray.type()); + + int show_count = 0; + while (1) + { + mouseX = globalMouseX; + mouseY = globalMouseY; + mouseClick = globalMouseClick; + mouseLeft = glb_mouse_left; + + + if (mouseClick) + { + drawTrajectoryByReference(target); + + if(show_count%5==0) + { + cv::Mat target_temp(target.size(),target.type()); + filtering_time = (double)getTickCount(); + if(mouseDraw) + { + cv::cvtColor(target, target_temp, cv::COLOR_BGR2YCrCb); + std::vector src_channels; + std::vector dst_channels; + + cv::split(target_temp,src_channels); + + cv::Mat result1 = cv::Mat(mat_input_gray.size(),mat_input_gray.type()); + cv::Mat result2 = cv::Mat(mat_input_gray.size(),mat_input_gray.type()); + + dst_channels.push_back(mat_input_gray); + cv::ximgproc::fastBilateralSolverFilter(mat_input_gray,src_channels[1],mat_input_confidence,result1,sigma_spatial,sigma_luma,sigma_chroma); + dst_channels.push_back(result1); + cv::ximgproc::fastBilateralSolverFilter(mat_input_gray,src_channels[2],mat_input_confidence,result2,sigma_spatial,sigma_luma,sigma_chroma); + dst_channels.push_back(result2); + + cv::merge(dst_channels,target_temp); + cv::cvtColor(target_temp, target_temp, cv::COLOR_YCrCb2BGR); + } + else + { + target_temp = target.clone(); + } + filtering_time = ((double)getTickCount() - filtering_time)/getTickFrequency(); + std::cout << "solver time: " << filtering_time << "s" << std::endl; + + cv::Mat color_selected(target_temp.rows-mat_pallet.rows,PALLET_RADIUS*2,CV_8UC3,cv::Scalar(selected_b, selected_g, selected_r)); + target_temp.copyTo(Mat(mat_show,Rect(0,0,target_temp.cols,target_temp.rows))); + mat_pallet.copyTo(Mat(mat_show,Rect(target_temp.cols,0,mat_pallet.cols,mat_pallet.rows))); + color_selected.copyTo(Mat(mat_show,Rect(target_temp.cols,PALLET_RADIUS*2,color_selected.cols,color_selected.rows))); + cv::imshow("draw", mat_show); + } + show_count++; + } + if (cv::waitKey(2) == 27) + break; + } + mat_draw = target.clone(); + cv::cvtColor(target, target, cv::COLOR_BGR2YCrCb); + + std::vector src_channels; + std::vector dst_channels; + + cv::split(target,src_channels); + + cv::Mat result1 = cv::Mat(mat_input_gray.size(),mat_input_gray.type()); + cv::Mat result2 = cv::Mat(mat_input_gray.size(),mat_input_gray.type()); + + filtering_time = (double)getTickCount(); + + // dst_channels.push_back(src_channels[0]); + dst_channels.push_back(mat_input_gray); + cv::ximgproc::fastBilateralSolverFilter(mat_input_gray,src_channels[1],mat_input_confidence,result1,sigma_spatial,sigma_luma,sigma_chroma); + dst_channels.push_back(result1); + cv::ximgproc::fastBilateralSolverFilter(mat_input_gray,src_channels[2],mat_input_confidence,result2,sigma_spatial,sigma_luma,sigma_chroma); + dst_channels.push_back(result2); + + cv::merge(dst_channels,target); + cv::cvtColor(target, target, cv::COLOR_YCrCb2BGR); + + filtering_time = ((double)getTickCount() - filtering_time)/getTickFrequency(); + std::cout << "solver time: " << filtering_time << "s" << std::endl; + + + + cv::imshow("mat_draw",mat_draw); + cv::imshow("output",target); + + if(dst_path!="None") + { + imwrite(dst_path,target); + } + if(dst_raw_path!="None") + { + imwrite(dst_raw_path,mat_draw); + } + + cv::waitKey(0); + + + +#else + std::cout << "Can not find eigen, please build with eigen by set WITH_EIGEN=ON" << '\n'; +#endif + + return 0; +} + + +#ifdef HAVE_EIGEN +static void mouseCallback(int event, int x, int y, int, void*) +{ + switch (event) + { + case cv::EVENT_MOUSEMOVE: + if (globalMouseClick) + { + globalMouseX = x; + globalMouseY = y; + } + break; + + case cv::EVENT_LBUTTONDOWN: + globalMouseClick = true; + globalMouseX = x; + globalMouseY = y; + break; + + case cv::EVENT_LBUTTONUP: + glb_mouse_left = true; + globalMouseClick = false; + break; + } +} + +void drawTrajectoryByReference(cv::Mat& img) +{ + int i, j; + uchar red, green, blue; + float gray; + int y, x; + int r = MARK_RADIUS; + int r2 = r * r; + uchar* colorPix; + uchar* grayPix; + + if(mouseY < PALLET_RADIUS*2 && img.cols <= mouseX && mouseX < img.cols+PALLET_RADIUS*2) + { + colorPix = mat_pallet.ptr(mouseY, mouseX - img.cols); + // colorPix = mat_pallet.ptr(mouseY, mouseX); + selected_b = *colorPix; + colorPix++; + selected_g = *colorPix; + colorPix++; + selected_r = *colorPix; + colorPix++; + std::cout << "x y:("<(y, x); + grayPix = mat_input_gray.ptr(y, x); + for(j=-r; j r2) + { + colorPix += mat_input_reference.channels(); + grayPix += mat_input_gray.channels(); + continue; + } + + if(y<0 || y>=mat_input_reference.rows || x<0 || x>=mat_input_reference.cols) + { + break; + } + + blue = *colorPix; + colorPix++; + green = *colorPix; + colorPix++; + red = *colorPix; + colorPix++; + gray = *grayPix; + grayPix++; + mat_input_confidence.at(y,x) = 255; + float draw_y = 0.229*(float(selected_r)) + 0.587*(float(selected_g)) + 0.114*(float(selected_b)); + int draw_b = int(float(selected_b)*(gray/draw_y)); + int draw_g = int(float(selected_g)*(gray/draw_y)); + int draw_r = int(float(selected_r)*(gray/draw_y)); + + if(drawByReference) + { + cv::circle(img, cv::Point2d(x, y), 0.1, cv::Scalar(blue, green, red), -1); + } + else + { + cv::circle(img, cv::Point2d(x, y), 0.1, cv::Scalar(draw_b, draw_g, draw_r), -1); + } + } + } + } +} + +double module(Point pt) +{ + return sqrt((double)pt.x*pt.x + pt.y*pt.y); +} + +double distance(Point pt1, Point pt2) +{ + int dx = pt1.x - pt2.x; + int dy = pt1.y - pt2.y; + return sqrt((double)dx*dx + dy*dy); +} + +double cross(Point pt1, Point pt2) +{ + return pt1.x*pt2.x + pt1.y*pt2.y; +} + +double angle(Point pt1, Point pt2) +{ + return acos(cross(pt1, pt2) / (module(pt1)*module(pt2) + DBL_EPSILON)); +} + +// p or c is the center +int inCircle(Point p, Point c, int r) +{ + int dx = p.x - c.x; + int dy = p.y - c.y; + return dx*dx + dy*dy <= r*r ? 1 : 0; + +} + +//draw the hsv-plate +void createPlate(Mat &im1, int radius) +{ + Mat hsvImag(Size(radius << 1, radius << 1), CV_8UC3, Scalar(0, 0, 255)); + int w = hsvImag.cols; + int h = hsvImag.rows; + int cx = w >> 1; + int cy = h >> 1; + Point pt1(cx, 0); + + for (int j = 0; j < w; j++) + { + for (int i = 0; i < h; i++) + { + Point pt2(j - cx, i - cy); + if (inCircle(Point(0, 0), pt2, radius)) + { + int theta = angle(pt1, pt2) * 180 / CV_PI; + if (i > cx) + { + theta = -theta + 360; + } + hsvImag.at(i, j)[0] = theta / 2; + hsvImag.at(i, j)[1] = module(pt2) / cx * 255; + hsvImag.at(i, j)[2] = 255; + } + } + } + + + cvtColor(hsvImag, im1, COLOR_HSV2BGR); +} + + +#endif diff --git a/modules/ximgproc/samples/disparity_filtering.cpp b/modules/ximgproc/samples/disparity_filtering.cpp index 767fb9ff6..89dd9adc1 100644 --- a/modules/ximgproc/samples/disparity_filtering.cpp +++ b/modules/ximgproc/samples/disparity_filtering.cpp @@ -4,6 +4,7 @@ #include "opencv2/highgui.hpp" #include "opencv2/core/utility.hpp" #include "opencv2/ximgproc/disparity_filter.hpp" +#include "opencv2/ximgproc.hpp" #include #include @@ -21,15 +22,18 @@ const String keys = "{dst_path |None | optional path to save the resulting filtered disparity map }" "{dst_raw_path |None | optional path to save raw disparity map before filtering }" "{algorithm |bm | stereo matching method (bm or sgbm) }" - "{filter |wls_conf | used post-filtering (wls_conf or wls_no_conf) }" + "{filter |wls_conf | used post-filtering (wls_conf or wls_no_conf or fbs_conf) }" "{no-display | | don't display results }" "{no-downscale | | force stereo matching on full-sized views to improve quality }" "{dst_conf_path |None | optional path to save the confidence map used in filtering }" "{vis_mult |1.0 | coefficient used to scale disparity map visualizations }" "{max_disparity |160 | parameter of stereo matching }" "{window_size |-1 | parameter of stereo matching }" - "{wls_lambda |8000.0 | parameter of post-filtering }" - "{wls_sigma |1.5 | parameter of post-filtering }" + "{wls_lambda |8000.0 | parameter of wls post-filtering }" + "{wls_sigma |1.5 | parameter of wls post-filtering }" + "{fbs_spatial |16.0 | parameter of fbs post-filtering }" + "{fbs_luma |8.0 | parameter of fbs post-filtering }" + "{fbs_chroma |8.0 | parameter of fbs post-filtering }" ; int main(int argc, char** argv) @@ -56,6 +60,9 @@ int main(int argc, char** argv) int max_disp = parser.get("max_disparity"); double lambda = parser.get("wls_lambda"); double sigma = parser.get("wls_sigma"); + double fbs_spatial = parser.get("fbs_spatial"); + double fbs_luma = parser.get("fbs_luma"); + double fbs_chroma = parser.get("fbs_chroma"); double vis_mult = parser.get("vis_mult"); int wsize; @@ -109,12 +116,13 @@ int main(int argc, char** argv) Mat left_for_matcher, right_for_matcher; Mat left_disp,right_disp; - Mat filtered_disp; + Mat filtered_disp,solved_disp,solved_filtered_disp; Mat conf_map = Mat(left.rows,left.cols,CV_8U); conf_map = Scalar(255); Rect ROI; Ptr wls_filter; double matching_time, filtering_time; + double solving_time = 0; if(max_disp<=0 || max_disp%16!=0) { cout<<"Incorrect max_disparity value: it should be positive and divisible by 16"; @@ -125,6 +133,7 @@ int main(int argc, char** argv) cout<<"Incorrect window_size value: it should be positive and odd"; return -1; } + if(filter=="wls_conf") // filtering with confidence (significantly better quality than wls_no_conf) { if(!no_downscale) @@ -201,6 +210,104 @@ int main(int argc, char** argv) ROI = Rect(ROI.x*2,ROI.y*2,ROI.width*2,ROI.height*2); } } + else if(filter=="fbs_conf") // filtering with fbs and confidence using also wls pre-processing + { + if(!no_downscale) + { + // downscale the views to speed-up the matching stage, as we will need to compute both left + // and right disparity maps for confidence map computation + //! [downscale_wls] + max_disp/=2; + if(max_disp%16!=0) + max_disp += 16-(max_disp%16); + resize(left ,left_for_matcher ,Size(),0.5,0.5); + resize(right,right_for_matcher,Size(),0.5,0.5); + //! [downscale_wls] + } + else + { + left_for_matcher = left.clone(); + right_for_matcher = right.clone(); + } + + if(algo=="bm") + { + //! [matching_wls] + Ptr left_matcher = StereoBM::create(max_disp,wsize); + wls_filter = createDisparityWLSFilter(left_matcher); + Ptr right_matcher = createRightMatcher(left_matcher); + + cvtColor(left_for_matcher, left_for_matcher, COLOR_BGR2GRAY); + cvtColor(right_for_matcher, right_for_matcher, COLOR_BGR2GRAY); + + matching_time = (double)getTickCount(); + left_matcher-> compute(left_for_matcher, right_for_matcher,left_disp); + right_matcher->compute(right_for_matcher,left_for_matcher, right_disp); + matching_time = ((double)getTickCount() - matching_time)/getTickFrequency(); + //! [matching_wls] + } + else if(algo=="sgbm") + { + Ptr left_matcher = StereoSGBM::create(0,max_disp,wsize); + left_matcher->setP1(24*wsize*wsize); + left_matcher->setP2(96*wsize*wsize); + left_matcher->setPreFilterCap(63); + left_matcher->setMode(StereoSGBM::MODE_SGBM_3WAY); + wls_filter = createDisparityWLSFilter(left_matcher); + Ptr right_matcher = createRightMatcher(left_matcher); + + matching_time = (double)getTickCount(); + left_matcher-> compute(left_for_matcher, right_for_matcher,left_disp); + right_matcher->compute(right_for_matcher,left_for_matcher, right_disp); + matching_time = ((double)getTickCount() - matching_time)/getTickFrequency(); + } + else + { + cout<<"Unsupported algorithm"; + return -1; + } + + //! [filtering_wls] + wls_filter->setLambda(lambda); + wls_filter->setSigmaColor(sigma); + filtering_time = (double)getTickCount(); + wls_filter->filter(left_disp,left,filtered_disp,right_disp); + filtering_time = ((double)getTickCount() - filtering_time)/getTickFrequency(); + //! [filtering_wls] + + conf_map = wls_filter->getConfidenceMap(); + + Mat left_disp_resized; + resize(left_disp,left_disp_resized,left.size()); + + // Get the ROI that was used in the last filter call: + ROI = wls_filter->getROI(); + if(!no_downscale) + { + // upscale raw disparity and ROI back for a proper comparison: + resize(left_disp,left_disp,Size(),2.0,2.0); + left_disp = left_disp*2.0; + left_disp_resized = left_disp_resized*2.0; + ROI = Rect(ROI.x*2,ROI.y*2,ROI.width*2,ROI.height*2); + } + +#ifdef HAVE_EIGEN + //! [filtering_fbs] + solving_time = (double)getTickCount(); + fastBilateralSolverFilter(left, left_disp_resized, conf_map/255.0f, solved_disp, fbs_spatial, fbs_luma, fbs_chroma); + solving_time = ((double)getTickCount() - solving_time)/getTickFrequency(); + //! [filtering_fbs] + + //! [filtering_wls2fbs] + fastBilateralSolverFilter(left, filtered_disp, conf_map/255.0f, solved_filtered_disp, fbs_spatial, fbs_luma, fbs_chroma); + //! [filtering_wls2fbs] +#else + (void)fbs_spatial; + (void)fbs_luma; + (void)fbs_chroma; + +#endif + } else if(filter=="wls_no_conf") { /* There is no convenience function for the case of filtering with no confidence, so we @@ -263,6 +370,7 @@ int main(int argc, char** argv) cout.precision(2); cout<<"Matching time: "< +#include +#include +#include +#include +#include +#include + + +#ifdef HAVE_EIGEN +# if defined __GNUC__ && defined __APPLE__ +# pragma GCC diagnostic ignored "-Wshadow" +# endif +# include +# include +# include +# include +# include + + + + +#if __cplusplus <= 199711L + #include + typedef std::map mapId; +#else + #include + typedef std::unordered_map mapId; +#endif + +#define EPS 1e-43f + +namespace cv +{ +namespace ximgproc +{ + + class FastBilateralSolverFilterImpl : public FastBilateralSolverFilter + { + public: + + static Ptr create(InputArray guide, double sigma_spatial, double sigma_luma, double sigma_chroma, int num_iter, double max_tol) + { + CV_Assert(guide.type() == CV_8UC1 || guide.type() == CV_8UC3); + FastBilateralSolverFilterImpl *fbs = new FastBilateralSolverFilterImpl(); + Mat gui = guide.getMat(); + fbs->init(gui,sigma_spatial,sigma_luma,sigma_chroma,num_iter,max_tol); + return Ptr(fbs); + } + + void filter(InputArray src, InputArray confidence, OutputArray dst) CV_OVERRIDE + { + + CV_Assert(!src.empty() && (src.depth() == CV_8U || src.depth() == CV_16S || src.depth() == CV_32F) && src.channels()<=4); + CV_Assert(!confidence.empty() && (confidence.depth() == CV_8U || confidence.depth() == CV_32F) && confidence.channels()==1); + if (src.rows() != rows || src.cols() != cols) + { + CV_Error(Error::StsBadSize, "Size of the filtered image must be equal to the size of the guide image"); + return; + } + if (confidence.rows() != rows || confidence.cols() != cols) + { + CV_Error(Error::StsBadSize, "Size of the confidence image must be equal to the size of the guide image"); + return; + } + + std::vector src_channels; + std::vector dst_channels; + if(src.channels()==1) + src_channels.push_back(src.getMat()); + else + split(src,src_channels); + + Mat conf = confidence.getMat(); + + for(int i=0;i& mat) + { + mat = Eigen::SparseMatrix(v.size(),v.size()); + for (int i = 0; i < int(v.size()); i++) + { + mat.insert(i,i) = v(i); + } + } + + + + private: + + int npixels; + int nvertices; + int dim; + int cols; + int rows; + std::vector splat_idx; + std::vector > blur_idx; + Eigen::VectorXf m; + Eigen::VectorXf n; + Eigen::SparseMatrix blurs; + Eigen::SparseMatrix S; + Eigen::SparseMatrix Dn; + Eigen::SparseMatrix Dm; + + struct grid_params + { + float spatialSigma; + float lumaSigma; + float chromaSigma; + grid_params() + { + spatialSigma = 8.0; + lumaSigma = 4.0; + chromaSigma = 4.0; + } + }; + + struct bs_params + { + float lam; + float A_diag_min; + float cg_tol; + int cg_maxiter; + bs_params() + { + lam = 128.0; + A_diag_min = 1e-5; + cg_tol = 1e-5; + cg_maxiter = 25; + } + }; + + grid_params grid_param; + bs_params bs_param; + + }; + + + + void FastBilateralSolverFilterImpl::init(cv::Mat& reference, double sigma_spatial, double sigma_luma, double sigma_chroma, int num_iter, double max_tol) + { + + bs_param.cg_maxiter = num_iter; + bs_param.cg_tol = max_tol; + + if(reference.channels()==1) + { + dim = 3; + cols = reference.cols; + rows = reference.rows; + npixels = cols*rows; + long long hash_vec[3]; + for (int i = 0; i < 3; ++i) + hash_vec[i] = static_cast(std::pow(255, i)); + + mapId hashed_coords; +#if __cplusplus <= 199711L +#else + hashed_coords.reserve(cols*rows); +#endif + + const unsigned char* pref = (const unsigned char*)reference.data; + int vert_idx = 0; + int pix_idx = 0; + + // construct Splat(Slice) matrices + splat_idx.resize(npixels); + for (int y = 0; y < rows; ++y) + { + for (int x = 0; x < cols; ++x) + { + long long coord[3]; + coord[0] = int(x / sigma_spatial); + coord[1] = int(y / sigma_spatial); + coord[2] = int(pref[0] / sigma_luma); + + // convert the coordinate to a hash value + long long hash_coord = 0; + for (int i = 0; i < 3; ++i) + hash_coord += coord[i] * hash_vec[i]; + + // pixels whom are alike will have the same hash value. + // We only want to keep a unique list of hash values, therefore make sure we only insert + // unique hash values. + mapId::iterator it = hashed_coords.find(hash_coord); + if (it == hashed_coords.end()) + { + hashed_coords.insert(std::pair(hash_coord, vert_idx)); + splat_idx[pix_idx] = vert_idx; + ++vert_idx; + } + else + { + splat_idx[pix_idx] = it->second; + } + + pref += 1; // skip 1 bytes (y) + ++pix_idx; + } + } + nvertices = hashed_coords.size(); + + // construct Blur matrices + Eigen::VectorXf ones_nvertices = Eigen::VectorXf::Ones(nvertices); + Eigen::VectorXf ones_npixels = Eigen::VectorXf::Ones(npixels); + diagonal(ones_nvertices,blurs); + blurs *= 10; + for(int offset = -1; offset <= 1;++offset) + { + if(offset == 0) continue; + for (int i = 0; i < dim; ++i) + { + Eigen::SparseMatrix blur_temp(hashed_coords.size(), hashed_coords.size()); + blur_temp.reserve(Eigen::VectorXi::Constant(nvertices,6)); + long long offset_hash_coord = offset * hash_vec[i]; + for (mapId::iterator it = hashed_coords.begin(); it != hashed_coords.end(); ++it) + { + long long neighb_coord = it->first + offset_hash_coord; + mapId::iterator it_neighb = hashed_coords.find(neighb_coord); + if (it_neighb != hashed_coords.end()) + { + blur_temp.insert(it->second,it_neighb->second) = 1.0f; + blur_idx.push_back(std::pair(it->second, it_neighb->second)); + } + } + blurs += blur_temp; + } + } + blurs.finalize(); + + //bistochastize + int maxiter = 10; + n = ones_nvertices; + m = Eigen::VectorXf::Zero(nvertices); + for (int i = 0; i < int(splat_idx.size()); i++) + { + m(splat_idx[i]) += 1.0f; + } + + Eigen::VectorXf bluredn(nvertices); + + for (int i = 0; i < maxiter; i++) + { + Blur(n,bluredn); + n = ((n.array()*m.array()).array()/bluredn.array()).array().sqrt(); + } + Blur(n,bluredn); + + m = n.array() * (bluredn).array(); + diagonal(m,Dm); + diagonal(n,Dn); + + } + else + { + dim = 5; + cv::Mat reference_yuv; + cv::cvtColor(reference, reference_yuv, COLOR_BGR2YCrCb); + + cols = reference_yuv.cols; + rows = reference_yuv.rows; + npixels = cols*rows; + long long hash_vec[5]; + for (int i = 0; i < 5; ++i) + hash_vec[i] = static_cast(std::pow(255, i)); + + mapId hashed_coords; +#if __cplusplus <= 199711L +#else + hashed_coords.reserve(cols*rows); +#endif + + const unsigned char* pref = (const unsigned char*)reference_yuv.data; + int vert_idx = 0; + int pix_idx = 0; + + // construct Splat(Slice) matrices + splat_idx.resize(npixels); + for (int y = 0; y < rows; ++y) + { + for (int x = 0; x < cols; ++x) + { + long long coord[5]; + coord[0] = int(x / sigma_spatial); + coord[1] = int(y / sigma_spatial); + coord[2] = int(pref[0] / sigma_luma); + coord[3] = int(pref[1] / sigma_chroma); + coord[4] = int(pref[2] / sigma_chroma); + + // convert the coordinate to a hash value + long long hash_coord = 0; + for (int i = 0; i < 5; ++i) + hash_coord += coord[i] * hash_vec[i]; + + // pixels whom are alike will have the same hash value. + // We only want to keep a unique list of hash values, therefore make sure we only insert + // unique hash values. + mapId::iterator it = hashed_coords.find(hash_coord); + if (it == hashed_coords.end()) + { + hashed_coords.insert(std::pair(hash_coord, vert_idx)); + splat_idx[pix_idx] = vert_idx; + ++vert_idx; + } + else + { + splat_idx[pix_idx] = it->second; + } + + pref += 3; // skip 3 bytes (y u v) + ++pix_idx; + } + } + nvertices = hashed_coords.size(); + + // construct Blur matrices + Eigen::VectorXf ones_nvertices = Eigen::VectorXf::Ones(nvertices); + Eigen::VectorXf ones_npixels = Eigen::VectorXf::Ones(npixels); + diagonal(ones_nvertices,blurs); + blurs *= 10; + for(int offset = -1; offset <= 1;++offset) + { + if(offset == 0) continue; + for (int i = 0; i < dim; ++i) + { + Eigen::SparseMatrix blur_temp(hashed_coords.size(), hashed_coords.size()); + blur_temp.reserve(Eigen::VectorXi::Constant(nvertices,6)); + long long offset_hash_coord = offset * hash_vec[i]; + for (mapId::iterator it = hashed_coords.begin(); it != hashed_coords.end(); ++it) + { + long long neighb_coord = it->first + offset_hash_coord; + mapId::iterator it_neighb = hashed_coords.find(neighb_coord); + if (it_neighb != hashed_coords.end()) + { + blur_temp.insert(it->second,it_neighb->second) = 1.0f; + blur_idx.push_back(std::pair(it->second, it_neighb->second)); + } + } + blurs += blur_temp; + } + } + blurs.finalize(); + + + //bistochastize + int maxiter = 10; + n = ones_nvertices; + m = Eigen::VectorXf::Zero(nvertices); + for (int i = 0; i < int(splat_idx.size()); i++) + { + m(splat_idx[i]) += 1.0f; + } + + Eigen::VectorXf bluredn(nvertices); + + for (int i = 0; i < maxiter; i++) + { + Blur(n,bluredn); + n = ((n.array()*m.array()).array()/bluredn.array()).array().sqrt(); + } + Blur(n,bluredn); + + m = n.array() * (bluredn).array(); + diagonal(m,Dm); + diagonal(n,Dn); + } + } + + void FastBilateralSolverFilterImpl::Splat(Eigen::VectorXf& input, Eigen::VectorXf& output) + { + output.setZero(); + for (int i = 0; i < int(splat_idx.size()); i++) + { + output(splat_idx[i]) += input(i); + } + + } + + void FastBilateralSolverFilterImpl::Blur(Eigen::VectorXf& input, Eigen::VectorXf& output) + { + output.setZero(); + output = input * 10; + for (int i = 0; i < int(blur_idx.size()); i++) + { + output(blur_idx[i].first) += input(blur_idx[i].second); + } + } + + + void FastBilateralSolverFilterImpl::Slice(Eigen::VectorXf& input, Eigen::VectorXf& output) + { + output.setZero(); + for (int i = 0; i < int(splat_idx.size()); i++) + { + output(i) = input(splat_idx[i]); + } + } + + + void FastBilateralSolverFilterImpl::solve(cv::Mat& target, + cv::Mat& confidence, + cv::Mat& output) + { + + Eigen::SparseMatrix M(nvertices,nvertices); + Eigen::SparseMatrix A_data(nvertices,nvertices); + Eigen::SparseMatrix A(nvertices,nvertices); + Eigen::VectorXf b(nvertices); + Eigen::VectorXf y(nvertices); + Eigen::VectorXf y0(nvertices); + Eigen::VectorXf y1(nvertices); + Eigen::VectorXf w_splat(nvertices); + + Eigen::VectorXf x(npixels); + Eigen::VectorXf w(npixels); + + if(target.depth() == CV_16S) + { + const int16_t *pft = reinterpret_cast(target.data); + for (int i = 0; i < npixels; i++) + { + x(i) = (cv::saturate_cast(pft[i])+32768.0f)/65535.0f; + } + } + else if(target.depth() == CV_8U) + { + const uchar *pft = reinterpret_cast(target.data); + for (int i = 0; i < npixels; i++) + { + x(i) = cv::saturate_cast(pft[i])/255.0f; + } + } + else if(confidence.depth() == CV_32F) + { + const float *pft = reinterpret_cast(target.data); + for (int i = 0; i < npixels; i++) + { + x(i) = pft[i]; + } + } + + if(confidence.depth() == CV_8U) + { + const uchar *pfc = reinterpret_cast(confidence.data); + for (int i = 0; i < npixels; i++) + { + w(i) = cv::saturate_cast(pfc[i])/255.0f; + } + } + else if(confidence.depth() == CV_32F) + { + const float *pfc = reinterpret_cast(confidence.data); + for (int i = 0; i < npixels; i++) + { + w(i) = pfc[i]; + } + } + + //construct A + Splat(w,w_splat); + + diagonal(w_splat,A_data); + A = bs_param.lam * (Dm - Dn * (blurs*Dn)) + A_data ; + + //construct b + b.setZero(); + for (int i = 0; i < int(splat_idx.size()); i++) + { + b(splat_idx[i]) += x(i) * w(i); + } + + //construct guess for y + y0.setZero(); + for (int i = 0; i < int(splat_idx.size()); i++) + { + y0(splat_idx[i]) += x(i); + } + y1.setZero(); + for (int i = 0; i < int(splat_idx.size()); i++) + { + y1(splat_idx[i]) += 1.0f; + } + for (int i = 0; i < nvertices; i++) + { + y0(i) = y0(i)/y1(i); + } + + + // solve Ay = b + Eigen::ConjugateGradient, Eigen::Lower|Eigen::Upper> cg; + cg.compute(A); + cg.setMaxIterations(bs_param.cg_maxiter); + cg.setTolerance(bs_param.cg_tol); + // y = cg.solve(b); + y = cg.solveWithGuess(b,y0); + std::cout << "#iterations: " << cg.iterations() << std::endl; + std::cout << "estimated error: " << cg.error() << std::endl; + + //slice + if(target.depth() == CV_16S) + { + int16_t *pftar = (int16_t*) output.data; + for (int i = 0; i < int(splat_idx.size()); i++) + { + pftar[i] = cv::saturate_cast(y(splat_idx[i]) * 65535.0f - 32768.0f); + } + } + else if (target.depth() == CV_8U) + { + uchar *pftar = (uchar*) output.data; + for (int i = 0; i < int(splat_idx.size()); i++) + { + pftar[i] = cv::saturate_cast(y(splat_idx[i]) * 255.0f); + } + } + else + { + float *pftar = (float*)(output.data); + for (int i = 0; i < int(splat_idx.size()); i++) + { + pftar[i] = y(splat_idx[i]); + } + } + + + } + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +Ptr createFastBilateralSolverFilter(InputArray guide, double sigma_spatial, double sigma_luma, double sigma_chroma, int num_iter, double max_tol) +{ + return Ptr(FastBilateralSolverFilterImpl::create(guide, sigma_spatial, sigma_luma, sigma_chroma, num_iter, max_tol)); +} + +void fastBilateralSolverFilter(InputArray guide, InputArray src, InputArray confidence, OutputArray dst, double sigma_spatial, double sigma_luma, double sigma_chroma, int num_iter, double max_tol) +{ + Ptr fbs = createFastBilateralSolverFilter(guide, sigma_spatial, sigma_luma, sigma_chroma, num_iter, max_tol); + fbs->filter(src, confidence, dst); +} + +} + +} + +#else + +namespace cv +{ +namespace ximgproc +{ + +Ptr createFastBilateralSolverFilter(InputArray, double, double, double, int, double) +{ + CV_Error(Error::StsNotImplemented, "createFastBilateralSolverFilter : needs to be compiled with EIGEN"); +} + +void fastBilateralSolverFilter(InputArray, InputArray, InputArray, OutputArray, double, double, double, int, double) +{ + CV_Error(Error::StsNotImplemented, "fastBilateralSolverFilter : needs to be compiled with EIGEN"); +} + + +} + +} + +#endif // HAVE_EIGEN diff --git a/modules/ximgproc/test/test_fbs_filter.cpp b/modules/ximgproc/test/test_fbs_filter.cpp new file mode 100644 index 000000000..778bf643b --- /dev/null +++ b/modules/ximgproc/test/test_fbs_filter.cpp @@ -0,0 +1,114 @@ +/* + * By downloading, copying, installing or using the software you agree to this license. + * If you do not agree to this license, do not download, install, + * copy or use the software. + * + * + * License Agreement + * For Open Source Computer Vision Library + * (3 - clause BSD License) + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met : + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and / or other materials provided with the distribution. + * + * * Neither the names of the copyright holders nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided by the copyright holders and contributors "as is" and + * any express or implied warranties, including, but not limited to, the implied + * warranties of merchantability and fitness for a particular purpose are disclaimed. + * In no event shall copyright holders or contributors be liable for any direct, + * indirect, incidental, special, exemplary, or consequential damages + * (including, but not limited to, procurement of substitute goods or services; + * loss of use, data, or profits; or business interruption) however caused + * and on any theory of liability, whether in contract, strict liability, + * or tort(including negligence or otherwise) arising in any way out of + * the use of this software, even if advised of the possibility of such damage. + */ + +#include "test_precomp.hpp" + +#ifdef HAVE_EIGEN + +namespace opencv_test { namespace { + +using namespace std; +using namespace cv; +using namespace cv::ximgproc; + +static string getDataDir() +{ + return cvtest::TS::ptr()->get_data_path(); +} + +CV_ENUM(SrcTypes, CV_8UC1, CV_8UC3, CV_8UC4, CV_16SC1, CV_16SC3, CV_32FC1); +CV_ENUM(GuideTypes, CV_8UC1, CV_8UC3) +typedef tuple FBSParams; +typedef TestWithParam FastBilateralSolverTest; + +TEST(FastBilateralSolverTest, SplatSurfaceAccuracy) +{ + RNG rnd(0); + int chanLut[] = {1,3,4}; + + for (int i = 0; i < 5; i++) + { + Size sz(rnd.uniform(512, 1024), rnd.uniform(512, 1024)); + + int guideCn = rnd.uniform(0, 2); // 1 or 3 channels + Mat guide(sz, CV_MAKE_TYPE(CV_8U, chanLut[guideCn])); + randu(guide, 0, 255); + + Scalar surfaceValue; + int srcCn = rnd.uniform(0, 3); // 1, 3 or 4 channels + rnd.fill(surfaceValue, RNG::UNIFORM, 0, 255); + Mat src(sz, CV_MAKE_TYPE(CV_16S, chanLut[srcCn]), surfaceValue); + Mat confidence(sz, CV_MAKE_TYPE(CV_8U, 1), 255); + + double sigma_spatial = rnd.uniform(4.0, 40.0); + double sigma_luma = rnd.uniform(4.0, 40.0); + double sigma_chroma = rnd.uniform(4.0, 40.0); + + Mat res; + fastBilateralSolverFilter(guide, src, confidence, res, sigma_spatial, sigma_luma, sigma_chroma); + + // When filtering a constant image we should get the same image: + double normL1 = cvtest::norm(src, res, NORM_L1)/src.total()/src.channels(); + EXPECT_LE(normL1, 1.0); + } +} + +TEST(FastBilateralSolverTest, ReferenceAccuracy) +{ + string dir = getDataDir() + "cv/edgefilter"; + + Mat src = imread(dir + "/kodim23.png"); + Mat ref = imread(dir + "/fgs/kodim23_lambda=1000_sigma=10.png"); + Mat confidence(src.size(), CV_MAKE_TYPE(CV_8U, 1), 255); + + ASSERT_FALSE(src.empty()); + ASSERT_FALSE(ref.empty()); + + Mat res; + fastBilateralSolverFilter(src,src,confidence,res, 16.0, 16.0, 16.0); + + double totalMaxError = 1.0/64.0*src.total()*src.channels(); + + EXPECT_LE(cvtest::norm(res, ref, NORM_L2), totalMaxError); + EXPECT_LE(cvtest::norm(res, ref, NORM_INF), 100); +} + +INSTANTIATE_TEST_CASE_P(FullSet, FastBilateralSolverTest,Combine(Values(szODD, szQVGA), SrcTypes::all(), GuideTypes::all())); + +} +} + +#endif //HAVE_EIGEN From 05fe693dcca54cd3faffdaa2e2688faa8040003f Mon Sep 17 00:00:00 2001 From: YTY Date: Fri, 9 Nov 2018 23:31:44 +0200 Subject: [PATCH 3/6] fix fbs test with new reference image --- modules/ximgproc/test/test_fbs_filter.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/modules/ximgproc/test/test_fbs_filter.cpp b/modules/ximgproc/test/test_fbs_filter.cpp index 778bf643b..a84b7fbfb 100644 --- a/modules/ximgproc/test/test_fbs_filter.cpp +++ b/modules/ximgproc/test/test_fbs_filter.cpp @@ -82,7 +82,7 @@ TEST(FastBilateralSolverTest, SplatSurfaceAccuracy) // When filtering a constant image we should get the same image: double normL1 = cvtest::norm(src, res, NORM_L1)/src.total()/src.channels(); - EXPECT_LE(normL1, 1.0); + EXPECT_LE(normL1, 1.0/64); } } @@ -91,7 +91,8 @@ TEST(FastBilateralSolverTest, ReferenceAccuracy) string dir = getDataDir() + "cv/edgefilter"; Mat src = imread(dir + "/kodim23.png"); - Mat ref = imread(dir + "/fgs/kodim23_lambda=1000_sigma=10.png"); + Mat ref = imread(dir + "/fbs/kodim23_spatial=16_luma=16_chroma=16.png"); + Mat confidence(src.size(), CV_MAKE_TYPE(CV_8U, 1), 255); ASSERT_FALSE(src.empty()); @@ -103,7 +104,7 @@ TEST(FastBilateralSolverTest, ReferenceAccuracy) double totalMaxError = 1.0/64.0*src.total()*src.channels(); EXPECT_LE(cvtest::norm(res, ref, NORM_L2), totalMaxError); - EXPECT_LE(cvtest::norm(res, ref, NORM_INF), 100); + EXPECT_LE(cvtest::norm(res, ref, NORM_INF), 1); } INSTANTIATE_TEST_CASE_P(FullSet, FastBilateralSolverTest,Combine(Values(szODD, szQVGA), SrcTypes::all(), GuideTypes::all())); From fcb266f72873b1f5fde7f978c307408674c943ac Mon Sep 17 00:00:00 2001 From: tompollok Date: Sat, 10 Nov 2018 00:10:43 +0100 Subject: [PATCH 4/6] refactoring catching all exceptions as const ref --- .../samples/cpp/OpenEXRimages_HDR_Retina_toneMapping.cpp | 2 +- .../cpp/OpenEXRimages_HDR_Retina_toneMapping_video.cpp | 2 +- modules/bioinspired/samples/cpp/retinaDemo.cpp | 2 +- .../samples/cpp/tutorial_code/bioinspired/retina_tutorial.cpp | 2 +- modules/bioinspired/samples/ocl/retina_ocl.cpp | 2 +- modules/bioinspired/src/retina.cpp | 4 ++-- modules/bioinspired/src/retina_ocl.cpp | 4 ++-- modules/bioinspired/src/transientareassegmentationmodule.cpp | 4 ++-- modules/face/samples/facerec_demo.cpp | 2 +- modules/face/samples/facerec_eigenfaces.cpp | 2 +- modules/face/samples/facerec_fisherfaces.cpp | 2 +- modules/face/samples/facerec_lbph.cpp | 2 +- modules/face/samples/facerec_save_load.cpp | 2 +- modules/face/samples/facerec_video.cpp | 2 +- modules/matlab/generator/templates/functional.cpp | 4 ++-- modules/matlab/test/cv_exception.cpp | 2 +- modules/matlab/test/std_exception.cpp | 2 +- modules/ovis/src/ovis.cpp | 4 ++-- 18 files changed, 23 insertions(+), 23 deletions(-) diff --git a/modules/bioinspired/samples/cpp/OpenEXRimages_HDR_Retina_toneMapping.cpp b/modules/bioinspired/samples/cpp/OpenEXRimages_HDR_Retina_toneMapping.cpp index 66cae7719..5d30e9d37 100644 --- a/modules/bioinspired/samples/cpp/OpenEXRimages_HDR_Retina_toneMapping.cpp +++ b/modules/bioinspired/samples/cpp/OpenEXRimages_HDR_Retina_toneMapping.cpp @@ -292,7 +292,7 @@ static void drawPlot(const cv::Mat curve, const std::string figureTitle, const i */ cv::waitKey(10); } - }catch(cv::Exception e) + }catch(const cv::Exception& e) { std::cerr<<"Error using Retina : "<%s\n", e.what()); if (applyDefaultSetupOnFailure) @@ -422,7 +422,7 @@ void RetinaImpl::setup(cv::FileStorage &fs, const bool applyDefaultSetupOnFailur setupIPLMagnoChannel(_retinaParameters.IplMagno.normaliseOutput, _retinaParameters.IplMagno.parasolCells_beta, _retinaParameters.IplMagno.parasolCells_tau, _retinaParameters.IplMagno.parasolCells_k, _retinaParameters.IplMagno.amacrinCellsTemporalCutFrequency,_retinaParameters.IplMagno.V0CompressionParameter, _retinaParameters.IplMagno.localAdaptintegration_tau, _retinaParameters.IplMagno.localAdaptintegration_k); } - catch(Exception &e) + catch(const Exception &e) { printf("RetinaImpl::setup: resetting retina with default parameters\n"); if (applyDefaultSetupOnFailure) diff --git a/modules/bioinspired/src/retina_ocl.cpp b/modules/bioinspired/src/retina_ocl.cpp index b48a412a1..15a19d52d 100644 --- a/modules/bioinspired/src/retina_ocl.cpp +++ b/modules/bioinspired/src/retina_ocl.cpp @@ -127,7 +127,7 @@ void RetinaOCLImpl::setup(String retinaParameterFile, const bool applyDefaultSet cv::FileStorage fs(retinaParameterFile, cv::FileStorage::READ); setup(fs, applyDefaultSetupOnFailure); } - catch(Exception &e) + catch(const Exception &e) { std::cout << "RetinaOCLImpl::setup: wrong/inappropriate xml parameter file : error report :`n=>" << e.what() << std::endl; if (applyDefaultSetupOnFailure) @@ -181,7 +181,7 @@ void RetinaOCLImpl::setup(cv::FileStorage &fs, const bool applyDefaultSetupOnFai setupIPLMagnoChannel(_retinaParameters.IplMagno.normaliseOutput, _retinaParameters.IplMagno.parasolCells_beta, _retinaParameters.IplMagno.parasolCells_tau, _retinaParameters.IplMagno.parasolCells_k, _retinaParameters.IplMagno.amacrinCellsTemporalCutFrequency, _retinaParameters.IplMagno.V0CompressionParameter, _retinaParameters.IplMagno.localAdaptintegration_tau, _retinaParameters.IplMagno.localAdaptintegration_k); } - catch(Exception &e) + catch(const Exception &e) { std::cout << "RetinaOCLImpl::setup: resetting retina with default parameters" << std::endl; if (applyDefaultSetupOnFailure) diff --git a/modules/bioinspired/src/transientareassegmentationmodule.cpp b/modules/bioinspired/src/transientareassegmentationmodule.cpp index b3342209d..42a60cbef 100644 --- a/modules/bioinspired/src/transientareassegmentationmodule.cpp +++ b/modules/bioinspired/src/transientareassegmentationmodule.cpp @@ -298,7 +298,7 @@ void TransientAreasSegmentationModuleImpl::setup(String segmentationParameterFil // opening retinaParameterFile in read mode cv::FileStorage fs(segmentationParameterFile, cv::FileStorage::READ); setup(fs, applyDefaultSetupOnFailure); - }catch(cv::Exception &e) + }catch(const cv::Exception &e) { printf("Retina::setup: wrong/unappropriate xml parameter file : error report :`n=>%s\n", e.what()); if (applyDefaultSetupOnFailure) @@ -338,7 +338,7 @@ void TransientAreasSegmentationModuleImpl::setup(cv::FileStorage &fs, const bool currFn["contextEnergy_spatialConstant"]>>_segmentationParameters.contextEnergy_spatialConstant; setup(_segmentationParameters); - }catch(cv::Exception &e) + }catch(const cv::Exception &e) { std::cout<<"Retina::setup: resetting retina with default parameters"<getParentSceneNode()->getParentSceneNode(); } - catch (ItemIdentityException&) + catch (const ItemIdentityException&) { // ignore } @@ -159,7 +159,7 @@ static SceneNode& _getSceneNode(SceneManager* sceneMgr, const String& name) if (!mo) mo = sceneMgr->getMovableObject(name, "Light"); } - catch (ItemIdentityException&) + catch (const ItemIdentityException&) { // ignore } From 2074cc48e543d6d87aded45488bbf39da154b400 Mon Sep 17 00:00:00 2001 From: Suleyman TURKMEN Date: Wed, 31 Oct 2018 19:38:19 +0300 Subject: [PATCH 5/6] minor changes --- modules/aruco/src/aruco.cpp | 9 ++++---- modules/aruco/src/charuco.cpp | 12 +++++----- modules/cnn_3dobj/src/cnn_feature.cpp | 18 +++++++-------- modules/cvv/samples/cvv_demo.cpp | 2 +- .../src/qtutil/filter/diffFilterWidget.cpp | 4 ++-- .../face_landmark_detection.markdown | 2 +- .../face_landmark_trainer.markdown | 4 ++-- .../face_landmark_video.markdown | 4 ++-- .../sample_face_swapping.markdown | 4 ++-- modules/img_hash/src/average_hash.cpp | 12 ++-------- modules/img_hash/src/block_mean_hash.cpp | 12 ++-------- modules/img_hash/src/color_moment_hash.cpp | 11 +++++----- modules/img_hash/src/marr_hildreth_hash.cpp | 13 +++-------- modules/img_hash/src/phash.cpp | 12 ++-------- modules/img_hash/src/radial_variance_hash.cpp | 4 ++-- .../line_descriptor/src/binary_descriptor.cpp | 3 +-- modules/reg/samples/map_test.cpp | 16 +++++++------- .../tutorial_customizing_cn_tracker.cpp | 2 +- modules/tracking/src/TrackingFunctionPF.hpp | 2 +- modules/tracking/src/trackerBoosting.cpp | 4 ++-- modules/tracking/src/trackerCSRT.cpp | 22 ++++++------------- modules/tracking/src/trackerCSRTUtils.cpp | 2 +- modules/tracking/src/trackerKCF.cpp | 2 +- modules/xphoto/samples/inpainting.cpp | 15 +++++-------- 24 files changed, 72 insertions(+), 119 deletions(-) diff --git a/modules/aruco/src/aruco.cpp b/modules/aruco/src/aruco.cpp index 4137eea34..76cd9edb3 100644 --- a/modules/aruco/src/aruco.cpp +++ b/modules/aruco/src/aruco.cpp @@ -103,13 +103,12 @@ Ptr DetectorParameters::create() { */ static void _convertToGrey(InputArray _in, OutputArray _out) { - CV_Assert(_in.getMat().channels() == 1 || _in.getMat().channels() == 3); + CV_Assert(_in.type() == CV_8UC1 || _in.type() == CV_8UC3); - _out.create(_in.getMat().size(), CV_8UC1); - if(_in.getMat().type() == CV_8UC3) - cvtColor(_in.getMat(), _out.getMat(), COLOR_BGR2GRAY); + if(_in.type() == CV_8UC3) + cvtColor(_in, _out, COLOR_BGR2GRAY); else - _in.getMat().copyTo(_out); + _in.copyTo(_out); } diff --git a/modules/aruco/src/charuco.cpp b/modules/aruco/src/charuco.cpp index 06ebbe5e3..5e5f01a9a 100644 --- a/modules/aruco/src/charuco.cpp +++ b/modules/aruco/src/charuco.cpp @@ -345,10 +345,10 @@ static int _selectAndRefineChessboardCorners(InputArray _allCorners, InputArray // corner refinement, first convert input image to grey Mat grey; - if(_image.getMat().type() == CV_8UC3) - cvtColor(_image.getMat(), grey, COLOR_BGR2GRAY); + if(_image.type() == CV_8UC3) + cvtColor(_image, grey, COLOR_BGR2GRAY); else - _image.getMat().copyTo(grey); + _image.copyTo(grey); const Ptr params = DetectorParameters::create(); // use default params for corner refinement @@ -754,10 +754,10 @@ void detectCharucoDiamond(InputArray _image, InputArrayOfArrays _markerCorners, // convert input image to grey Mat grey; - if(_image.getMat().type() == CV_8UC3) - cvtColor(_image.getMat(), grey, COLOR_BGR2GRAY); + if(_image.type() == CV_8UC3) + cvtColor(_image, grey, COLOR_BGR2GRAY); else - _image.getMat().copyTo(grey); + _image.copyTo(grey); // for each of the detected markers, try to find a diamond for(unsigned int i = 0; i < _markerIds.total(); i++) { diff --git a/modules/cnn_3dobj/src/cnn_feature.cpp b/modules/cnn_3dobj/src/cnn_feature.cpp index 690f245e4..a5d48a0e0 100755 --- a/modules/cnn_3dobj/src/cnn_feature.cpp +++ b/modules/cnn_3dobj/src/cnn_feature.cpp @@ -222,26 +222,24 @@ namespace cnn_3dobj { /* Convert the input image to the input image format of the network. */ cv::Mat sample; - if (img.channels() == 3 && num_channels == 1) - cv::cvtColor(img, sample, CV_BGR2GRAY); - else if (img.channels() == 4 && num_channels == 1) - cv::cvtColor(img, sample, CV_BGRA2GRAY); + if (num_channels == 1) + cv::cvtColor(img, sample, COLOR_BGR2GRAY); else if (img.channels() == 4 && num_channels == 3) - cv::cvtColor(img, sample, CV_BGRA2BGR); + cv::cvtColor(img, sample, COLOR_BGRA2BGR); else if (img.channels() == 1 && num_channels == 3) - cv::cvtColor(img, sample, CV_GRAY2BGR); + cv::cvtColor(img, sample, COLOR_GRAY2BGR); else sample = img; + cv::Mat sample_resized; if (sample.size() != input_geometry) cv::resize(sample, sample_resized, input_geometry); else sample_resized = sample; + cv::Mat sample_float; - if (num_channels == 3) - sample_resized.convertTo(sample_float, CV_32FC3); - else - sample_resized.convertTo(sample_float, CV_32FC1); + sample_resized.convertTo(sample_float, CV_32F); + cv::Mat sample_normalized; if (net_ready == 2) cv::subtract(sample_float, mean_, sample_normalized); diff --git a/modules/cvv/samples/cvv_demo.cpp b/modules/cvv/samples/cvv_demo.cpp index 14aafbeb1..f98dfef92 100644 --- a/modules/cvv/samples/cvv_demo.cpp +++ b/modules/cvv/samples/cvv_demo.cpp @@ -84,7 +84,7 @@ main(int argc, char** argv) // convert to grayscale cv::Mat imgGray; - cv::cvtColor(imgRead, imgGray, CV_BGR2GRAY); + cv::cvtColor(imgRead, imgGray, COLOR_BGR2GRAY); cvv::debugFilter(imgRead, imgGray, CVVISUAL_LOCATION, "to gray"); // detect ORB features diff --git a/modules/cvv/src/qtutil/filter/diffFilterWidget.cpp b/modules/cvv/src/qtutil/filter/diffFilterWidget.cpp index 05e296389..a555c8498 100644 --- a/modules/cvv/src/qtutil/filter/diffFilterWidget.cpp +++ b/modules/cvv/src/qtutil/filter/diffFilterWidget.cpp @@ -69,8 +69,8 @@ void DiffFilterFunction::applyFilter(InputArray in, OutputArray out) const } cv::Mat originalHSV, filteredHSV; - cv::cvtColor(in.at(0).get(), originalHSV, CV_BGR2HSV); - cv::cvtColor(in.at(1).get(), filteredHSV, CV_BGR2HSV); + cv::cvtColor(in.at(0).get(), originalHSV, COLOR_BGR2HSV); + cv::cvtColor(in.at(1).get(), filteredHSV, COLOR_BGR2HSV); auto diffHSV = cv::abs(originalHSV - filteredHSV); std::array splitVector; diff --git a/modules/face/tutorials/face_landmark/face_landmark_detection.markdown b/modules/face/tutorials/face_landmark/face_landmark_detection.markdown index bc566fa14..36d5f8222 100644 --- a/modules/face/tutorials/face_landmark/face_landmark_detection.markdown +++ b/modules/face/tutorials/face_landmark/face_landmark_detection.markdown @@ -46,7 +46,7 @@ resize(img,img,Size(460,460),0,0,INTER_LINEAR_EXACT); Mat gray; std::vector faces; if(img.channels()>1){ - cvtColor(img.getMat(),gray,CV_BGR2GRAY); + cvtColor(img.getMat(),gray,COLOR_BGR2GRAY); } else{ gray = img.getMat().clone(); diff --git a/modules/face/tutorials/face_landmark/face_landmark_trainer.markdown b/modules/face/tutorials/face_landmark/face_landmark_trainer.markdown index e6af33578..601a6b4c4 100644 --- a/modules/face/tutorials/face_landmark/face_landmark_trainer.markdown +++ b/modules/face/tutorials/face_landmark/face_landmark_trainer.markdown @@ -65,7 +65,7 @@ bool myDetector( InputArray image, OutputArray ROIs ){ Mat gray; std::vector faces; if(image.channels()>1){ - cvtColor(image.getMat(),gray,CV_BGR2GRAY); + cvtColor(image.getMat(),gray,COLOR_BGR2GRAY); } else{ gray = image.getMat().clone(); @@ -174,4 +174,4 @@ filename specified.As the training starts successfully you will see something li **The error rate on test images depends on the number of images used for training used as follows :** -![](images/test.png) \ No newline at end of file +![](images/test.png) diff --git a/modules/face/tutorials/face_landmark/face_landmark_video.markdown b/modules/face/tutorials/face_landmark/face_landmark_video.markdown index 4b1ed2a51..2ca51f4dd 100644 --- a/modules/face/tutorials/face_landmark/face_landmark_video.markdown +++ b/modules/face/tutorials/face_landmark/face_landmark_video.markdown @@ -26,7 +26,7 @@ bool myDetector( InputArray image, OutputArray ROIs ){ Mat gray; std::vector faces; if(image.channels()>1){ - cvtColor(image.getMat(),gray,CV_BGR2GRAY); + cvtColor(image.getMat(),gray,COLOR_BGR2GRAY); } else{ gray = image.getMat().clone(); @@ -107,4 +107,4 @@ Sample video: @htmlonly -@endhtmlonly \ No newline at end of file +@endhtmlonly diff --git a/modules/face/tutorials/face_landmark/sample_face_swapping.markdown b/modules/face/tutorials/face_landmark/sample_face_swapping.markdown index 04e50c3c8..0504b0b1b 100644 --- a/modules/face/tutorials/face_landmark/sample_face_swapping.markdown +++ b/modules/face/tutorials/face_landmark/sample_face_swapping.markdown @@ -25,7 +25,7 @@ bool myDetector( InputArray image, OutputArray ROIs ){ Mat gray; std::vector faces; if(image.channels()>1){ - cvtColor(image.getMat(),gray,CV_BGR2GRAY); + cvtColor(image.getMat(),gray,COLOR_BGR2GRAY); } else{ gray = image.getMat().clone(); @@ -144,4 +144,4 @@ Second image Results after swapping ---------------------- -![](images/face_swapped.jpg) \ No newline at end of file +![](images/face_swapped.jpg) diff --git a/modules/img_hash/src/average_hash.cpp b/modules/img_hash/src/average_hash.cpp index 316a2165c..5b5d15e13 100644 --- a/modules/img_hash/src/average_hash.cpp +++ b/modules/img_hash/src/average_hash.cpp @@ -27,18 +27,10 @@ public: input.type() == CV_8U); cv::resize(input, resizeImg, cv::Size(8,8), 0, 0, INTER_LINEAR_EXACT); - if(input.type() == CV_8UC3) - { - cv::cvtColor(resizeImg, grayImg, CV_BGR2GRAY); - } - else if(input.type() == CV_8UC4) - { - cv::cvtColor(resizeImg, grayImg, CV_BGRA2GRAY); - } + if(input.channels() > 1) + cv::cvtColor(resizeImg, grayImg, COLOR_BGR2GRAY); else - { grayImg = resizeImg; - } uchar const imgMean = static_cast(cvRound(cv::mean(grayImg)[0])); cv::compare(grayImg, imgMean, bitsImg, CMP_GT); diff --git a/modules/img_hash/src/block_mean_hash.cpp b/modules/img_hash/src/block_mean_hash.cpp index 15d4fd3c1..b68428422 100644 --- a/modules/img_hash/src/block_mean_hash.cpp +++ b/modules/img_hash/src/block_mean_hash.cpp @@ -40,18 +40,10 @@ public: input.type() == CV_8U); cv::resize(input, resizeImg_, cv::Size(imgWidth,imgHeight), 0, 0, INTER_LINEAR_EXACT); - if(input.type() == CV_8UC3) - { - cv::cvtColor(resizeImg_, grayImg_, CV_BGR2GRAY); - } - else if(input.type() == CV_8UC4) - { - cv::cvtColor(resizeImg_, grayImg_, CV_BGRA2GRAY); - } + if(input.channels() > 1) + cv::cvtColor(resizeImg_, grayImg_, COLOR_BGR2GRAY); else - { grayImg_ = resizeImg_; - } int pixColStep = blockWidth; int pixRowStep = blockHeigth; diff --git a/modules/img_hash/src/color_moment_hash.cpp b/modules/img_hash/src/color_moment_hash.cpp index 90f2972cc..7785648e6 100644 --- a/modules/img_hash/src/color_moment_hash.cpp +++ b/modules/img_hash/src/color_moment_hash.cpp @@ -28,25 +28,24 @@ public: } else if(input.type() == CV_8UC4) { - cv::cvtColor(input, colorImg_, CV_BGRA2BGR); + cv::cvtColor(input, colorImg_, COLOR_BGRA2BGR); } else { - cv::cvtColor(input, colorImg_, CV_GRAY2BGR); + cv::cvtColor(input, colorImg_, COLOR_GRAY2BGR); } - cv::resize(colorImg_, resizeImg_, cv::Size(512,512), 0, 0, - INTER_CUBIC); + cv::resize(colorImg_, resizeImg_, cv::Size(512,512), 0, 0, INTER_CUBIC); cv::GaussianBlur(resizeImg_, blurImg_, cv::Size(3,3), 0, 0); - cv::cvtColor(blurImg_, colorSpace_, CV_BGR2HSV); + cv::cvtColor(blurImg_, colorSpace_, COLOR_BGR2HSV); cv::split(colorSpace_, channels_); outputArr.create(1, 42, CV_64F); cv::Mat hash = outputArr.getMat(); hash.setTo(0); computeMoments(hash.ptr(0)); - cv::cvtColor(blurImg_, colorSpace_, CV_BGR2YCrCb); + cv::cvtColor(blurImg_, colorSpace_, COLOR_BGR2YCrCb); cv::split(colorSpace_, channels_); computeMoments(hash.ptr(0) + 21); } diff --git a/modules/img_hash/src/marr_hildreth_hash.cpp b/modules/img_hash/src/marr_hildreth_hash.cpp index 2feeb0e78..cee136aac 100644 --- a/modules/img_hash/src/marr_hildreth_hash.cpp +++ b/modules/img_hash/src/marr_hildreth_hash.cpp @@ -105,18 +105,11 @@ public: input.type() == CV_8UC3 || input.type() == CV_8U); - if(input.type() == CV_8UC3) - { - cv::cvtColor(input, grayImg, CV_BGR2GRAY); - } - else if(input.type() == CV_8UC4) - { - cv::cvtColor(input, grayImg, CV_BGRA2GRAY); - } + if(input.channels() > 1) + cv::cvtColor(input, grayImg, COLOR_BGR2GRAY); else - { grayImg = input; - } + //pHash use Canny-deritch filter to blur the image cv::GaussianBlur(grayImg, blurImg, cv::Size(7, 7), 0); cv::resize(blurImg, resizeImg, cv::Size(512, 512), 0, 0, INTER_CUBIC); diff --git a/modules/img_hash/src/phash.cpp b/modules/img_hash/src/phash.cpp index 03eefa97b..13949471e 100644 --- a/modules/img_hash/src/phash.cpp +++ b/modules/img_hash/src/phash.cpp @@ -21,18 +21,10 @@ public: input.type() == CV_8U); cv::resize(input, resizeImg, cv::Size(32,32), 0, 0, INTER_LINEAR_EXACT); - if(input.type() == CV_8UC3) - { - cv::cvtColor(resizeImg, grayImg, CV_BGR2GRAY); - } - else if(input.type() == CV_8UC4) - { - cv::cvtColor(resizeImg, grayImg, CV_BGRA2GRAY); - } + if(input.channels() > 1) + cv::cvtColor(resizeImg, grayImg, COLOR_BGR2GRAY); else - { grayImg = resizeImg; - } grayImg.convertTo(grayFImg, CV_32F); cv::dct(grayFImg, dctImg); diff --git a/modules/img_hash/src/radial_variance_hash.cpp b/modules/img_hash/src/radial_variance_hash.cpp index b2eaef2ec..d442595cc 100644 --- a/modules/img_hash/src/radial_variance_hash.cpp +++ b/modules/img_hash/src/radial_variance_hash.cpp @@ -53,11 +53,11 @@ public: if(input.type() == CV_8UC3) { - cv::cvtColor(input, grayImg_, CV_BGR2GRAY); + cv::cvtColor(input, grayImg_, COLOR_BGR2GRAY); } else if(input.type() == CV_8UC4) { - cv::cvtColor(input, grayImg_, CV_BGRA2GRAY); + cv::cvtColor(input, grayImg_, COLOR_BGRA2GRAY); } else { diff --git a/modules/line_descriptor/src/binary_descriptor.cpp b/modules/line_descriptor/src/binary_descriptor.cpp index e5de2f9aa..b8c9fbf3c 100644 --- a/modules/line_descriptor/src/binary_descriptor.cpp +++ b/modules/line_descriptor/src/binary_descriptor.cpp @@ -548,7 +548,7 @@ void BinaryDescriptor::computeImpl( const Mat& imageSrc, std::vector& k if( imageSrc.channels() != 1 ) cvtColor( imageSrc, image, COLOR_BGR2GRAY ); else - image = imageSrc.clone(); + image = imageSrc; /*check whether image's depth is different from 0 */ if( image.depth() != 0 ) @@ -627,7 +627,6 @@ void BinaryDescriptor::computeImpl( const Mat& imageSrc, std::vector& k { for ( size_t j = 0; j < sl[i].size(); ) { - //if( (int) ( sl[i][j] ).octaveCount > params.numOfOctave_ ) if( (int) ( sl[i][j] ).octaveCount > octaveIndex ) ( sl[i] ).erase( ( sl[i] ).begin() + j ); else j++; diff --git a/modules/reg/samples/map_test.cpp b/modules/reg/samples/map_test.cpp index c59ce96ed..454803a51 100644 --- a/modules/reg/samples/map_test.cpp +++ b/modules/reg/samples/map_test.cpp @@ -73,9 +73,9 @@ static void showDifference(const Mat& image1, const Mat& image2, const char* tit image1.convertTo(img1, CV_32FC3); image2.convertTo(img2, CV_32FC3); if(img1.channels() != 1) - cvtColor(img1, img1, CV_RGB2GRAY); + cvtColor(img1, img1, COLOR_BGR2GRAY); if(img2.channels() != 1) - cvtColor(img2, img2, CV_RGB2GRAY); + cvtColor(img2, img2, COLOR_BGR2GRAY); Mat imgDiff; img1.copyTo(imgDiff); @@ -273,11 +273,11 @@ static void calcHomographyFeature(const Mat& image1, const Mat& image2) Mat gray_image2; // Convert to Grayscale if(image1.channels() != 1) - cvtColor(image1, gray_image1, CV_RGB2GRAY); + cvtColor(image1, gray_image1, COLOR_BGR2GRAY); else image1.copyTo(gray_image1); if(image2.channels() != 1) - cvtColor(image2, gray_image2, CV_RGB2GRAY); + cvtColor(image2, gray_image2, COLOR_BGR2GRAY); else image2.copyTo(gray_image2); @@ -335,7 +335,7 @@ static void calcHomographyFeature(const Mat& image1, const Mat& image2) } // Find the Homography Matrix - Mat H = findHomography( obj, scene, CV_RANSAC ); + Mat H = findHomography( obj, scene, RANSAC ); // Use the Homography Matrix to warp the images Mat result; Mat Hinv = H.inv(); @@ -393,7 +393,7 @@ static void comparePixelVsFeature(const Mat& img1_8b, const Mat& img2_8b) int main(void) { Mat img1; - img1 = imread("home.png", CV_LOAD_IMAGE_UNCHANGED); + img1 = imread("home.png", IMREAD_UNCHANGED); if(!img1.data) { cout << "Could not open or find file" << endl; return -1; @@ -408,13 +408,13 @@ int main(void) testProjective(img1); #ifdef COMPARE_FEATURES - Mat imgcmp1 = imread("LR_05.png", CV_LOAD_IMAGE_UNCHANGED); + Mat imgcmp1 = imread("LR_05.png", IMREAD_UNCHANGED); if(!imgcmp1.data) { cout << "Could not open or find file" << endl; return -1; } - Mat imgcmp2 = imread("LR_06.png", CV_LOAD_IMAGE_UNCHANGED); + Mat imgcmp2 = imread("LR_06.png", IMREAD_UNCHANGED); if(!imgcmp2.data) { cout << "Could not open or find file" << endl; return -1; diff --git a/modules/tracking/samples/tutorial_customizing_cn_tracker.cpp b/modules/tracking/samples/tutorial_customizing_cn_tracker.cpp index 14259dfbf..31d3b3c4c 100644 --- a/modules/tracking/samples/tutorial_customizing_cn_tracker.cpp +++ b/modules/tracking/samples/tutorial_customizing_cn_tracker.cpp @@ -102,7 +102,7 @@ void sobelExtractor(const Mat img, const Rect roi, Mat& feat){ //! [insideimage] patch=img(region).clone(); - cvtColor(patch,patch, CV_BGR2GRAY); + cvtColor(patch,patch, COLOR_BGR2GRAY); //! [padding] // add some padding to compensate when the patch is outside image border diff --git a/modules/tracking/src/TrackingFunctionPF.hpp b/modules/tracking/src/TrackingFunctionPF.hpp index fb6039b74..8ae9208fd 100644 --- a/modules/tracking/src/TrackingFunctionPF.hpp +++ b/modules/tracking/src/TrackingFunctionPF.hpp @@ -31,7 +31,7 @@ namespace cv{ Mat hsv; img.convertTo(hsv,CV_32F,1.0/255.0); - cvtColor(hsv,hsv,CV_BGR2HSV); + cvtColor(hsv,hsv,COLOR_BGR2HSV); HShist=Mat_(nh,ns,0.0); Vhist=Mat_(1,nv,0.0); diff --git a/modules/tracking/src/trackerBoosting.cpp b/modules/tracking/src/trackerBoosting.cpp index 32ca27120..05b11aa2d 100644 --- a/modules/tracking/src/trackerBoosting.cpp +++ b/modules/tracking/src/trackerBoosting.cpp @@ -126,7 +126,7 @@ bool TrackerBoostingImpl::initImpl( const Mat& image, const Rect2d& boundingBox Mat_ intImage; Mat_ intSqImage; Mat image_; - cvtColor( image, image_, CV_RGB2GRAY ); + cvtColor( image, image_, COLOR_BGR2GRAY ); integral( image_, intImage, intSqImage, CV_32S ); TrackerSamplerCS::Params CSparameters; CSparameters.overlap = params.samplerOverlap; @@ -208,7 +208,7 @@ bool TrackerBoostingImpl::updateImpl( const Mat& image, Rect2d& boundingBox ) Mat_ intImage; Mat_ intSqImage; Mat image_; - cvtColor( image, image_, CV_RGB2GRAY ); + cvtColor( image, image_, COLOR_BGR2GRAY ); integral( image_, intImage, intSqImage, CV_32S ); //get the last location [AAM] X(k-1) Ptr lastLocation = model->getLastTargetState(); diff --git a/modules/tracking/src/trackerCSRT.cpp b/modules/tracking/src/trackerCSRT.cpp index d46cf1432..0c541cfb7 100644 --- a/modules/tracking/src/trackerCSRT.cpp +++ b/modules/tracking/src/trackerCSRT.cpp @@ -201,7 +201,7 @@ std::vector TrackerCSRTImpl::get_features(const Mat &patch, const Size2i &f } if(params.use_gray) { Mat gray_m; - cvtColor(patch, gray_m, CV_BGR2GRAY); + cvtColor(patch, gray_m, COLOR_BGR2GRAY); resize(gray_m, gray_m, feature_size, 0, 0, INTER_CUBIC); gray_m.convertTo(gray_m, CV_32FC1, 1.0/255.0, -0.5); features.push_back(gray_m); @@ -465,15 +465,11 @@ Point2f TrackerCSRTImpl::estimate_new_position(const Mat &image) // ********************************************************************* bool TrackerCSRTImpl::updateImpl(const Mat& image_, Rect2d& boundingBox) { - //treat gray image as color image Mat image; - if(image_.channels() == 1) { - std::vector channels(3); - channels[0] = channels[1] = channels[2] = image_; - merge(channels, image); - } else { + if(image_.channels() == 1) //treat gray image as color image + cvtColor(image_, image, COLOR_GRAY2BGR); + else image = image_; - } object_center = estimate_new_position(image); if (object_center.x < 0 && object_center.y < 0) @@ -512,15 +508,11 @@ bool TrackerCSRTImpl::updateImpl(const Mat& image_, Rect2d& boundingBox) // ********************************************************************* bool TrackerCSRTImpl::initImpl(const Mat& image_, const Rect2d& boundingBox) { - //treat gray image as color image Mat image; - if(image_.channels() == 1) { - std::vector channels(3); - channels[0] = channels[1] = channels[2] = image_; - merge(channels, image); - } else { + if(image_.channels() == 1) //treat gray image as color image + cvtColor(image_, image, COLOR_GRAY2BGR); + else image = image_; - } current_scale_factor = 1.0; image_size = image.size(); diff --git a/modules/tracking/src/trackerCSRTUtils.cpp b/modules/tracking/src/trackerCSRTUtils.cpp index 2f8aba306..15aa00a16 100644 --- a/modules/tracking/src/trackerCSRTUtils.cpp +++ b/modules/tracking/src/trackerCSRTUtils.cpp @@ -552,7 +552,7 @@ double get_min(const Mat &m) Mat bgr2hsv(const Mat &img) { Mat hsv_img; - cvtColor(img, hsv_img, CV_BGR2HSV); + cvtColor(img, hsv_img, COLOR_BGR2HSV); std::vector hsv_img_channels; split(hsv_img, hsv_img_channels); hsv_img_channels.at(0).convertTo(hsv_img_channels.at(0), CV_8UC1, 255.0 / 180.0); diff --git a/modules/tracking/src/trackerKCF.cpp b/modules/tracking/src/trackerKCF.cpp index 474dceb5b..471ad71f7 100644 --- a/modules/tracking/src/trackerKCF.cpp +++ b/modules/tracking/src/trackerKCF.cpp @@ -700,7 +700,7 @@ namespace cv{ break; default: // GRAY if(img.channels()>1) - cvtColor(patch,feat, CV_BGR2GRAY); + cvtColor(patch,feat, COLOR_BGR2GRAY); else feat=patch; //feat.convertTo(feat,CV_32F); diff --git a/modules/xphoto/samples/inpainting.cpp b/modules/xphoto/samples/inpainting.cpp index 340b06322..5c07fe0b8 100644 --- a/modules/xphoto/samples/inpainting.cpp +++ b/modules/xphoto/samples/inpainting.cpp @@ -3,9 +3,6 @@ #include "opencv2/imgproc.hpp" #include "opencv2/highgui.hpp" -#include "opencv2/core/utility.hpp" -#include "opencv2/imgproc/types_c.h" - #include #include @@ -41,22 +38,22 @@ int main( int argc, const char** argv ) std::string maskFilename = parser.get("m"); std::string outFilename = parser.get("o"); - cv::Mat src = cv::imread(inFilename, -1); + cv::Mat src = cv::imread(inFilename, cv::IMREAD_UNCHANGED); if ( src.empty() ) { printf( "Cannot read image file: %s\n", inFilename.c_str() ); return -1; } - cv::cvtColor(src, src, CV_RGB2Lab); + cv::cvtColor(src, src, cv::COLOR_BGR2Lab); - cv::Mat mask = cv::imread(maskFilename, 0); + cv::Mat mask = cv::imread(maskFilename, cv::IMREAD_GRAYSCALE); if ( mask.empty() ) { printf( "Cannot read image file: %s\n", maskFilename.c_str() ); return -1; } - cv::threshold(mask, mask, 128, 255, CV_THRESH_BINARY | CV_THRESH_OTSU); + cv::threshold(mask, mask, 128, 255, cv::THRESH_BINARY | cv::THRESH_OTSU); cv::Mat res(src.size(), src.type()); @@ -65,7 +62,7 @@ int main( int argc, const char** argv ) std::cout << "time = " << (clock() - time) / double(CLOCKS_PER_SEC) << std::endl; - cv::cvtColor(res, res, CV_Lab2RGB); + cv::cvtColor(res, res, cv::COLOR_Lab2BGR); if ( outFilename == "" ) { @@ -78,4 +75,4 @@ int main( int argc, const char** argv ) cv::imwrite(outFilename, res); return 0; -} \ No newline at end of file +} From cd6f7d1291898cf9a1185e5974a6f20b4127b3d0 Mon Sep 17 00:00:00 2001 From: LaurentBerger Date: Thu, 8 Nov 2018 22:07:42 +0100 Subject: [PATCH 6/6] Rewrite deriche filter- add test - add python wrapper --- .../opencv2/ximgproc/deriche_filter.hpp | 20 +- modules/ximgproc/samples/dericheSample.py | 60 ++++++ modules/ximgproc/src/deriche_filter.cpp | 194 ++++++++++-------- modules/ximgproc/test/test_deriche_filter.cpp | 41 ++++ 4 files changed, 214 insertions(+), 101 deletions(-) create mode 100644 modules/ximgproc/samples/dericheSample.py create mode 100644 modules/ximgproc/test/test_deriche_filter.cpp diff --git a/modules/ximgproc/include/opencv2/ximgproc/deriche_filter.hpp b/modules/ximgproc/include/opencv2/ximgproc/deriche_filter.hpp index 2371feb6d..26d3b6759 100644 --- a/modules/ximgproc/include/opencv2/ximgproc/deriche_filter.hpp +++ b/modules/ximgproc/include/opencv2/ximgproc/deriche_filter.hpp @@ -51,25 +51,25 @@ namespace ximgproc { * * For more details about this implementation, please see http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.476.5736&rep=rep1&type=pdf * -* @param _op Source 8-bit or 16bit image, 1-channel or 3-channel image. -* @param _dst result CV_32FC image with same number of channel than _op. -* @param alphaDerive double see paper -* @param alphaMean double see paper +* @param op Source 8-bit or 16bit image, 1-channel or 3-channel image. +* @param dst result CV_32FC image with same number of channel than _op. +* @param alpha double see paper +* @param omega double see paper * */ -CV_EXPORTS void GradientDericheY(InputArray _op, OutputArray _dst, double alphaDerive,double alphaMean); +CV_EXPORTS_W void GradientDericheY(InputArray op, OutputArray dst, double alpha,double omega); /** * @brief Applies X Deriche filter to an image. * * For more details about this implementation, please see http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.476.5736&rep=rep1&type=pdf * -* @param _op Source 8-bit or 16bit image, 1-channel or 3-channel image. -* @param _dst result CV_32FC image with same number of channel than _op. -* @param alphaDerive double see paper -* @param alphaMean double see paper +* @param op Source 8-bit or 16bit image, 1-channel or 3-channel image. +* @param dst result CV_32FC image with same number of channel than _op. +* @param alpha double see paper +* @param omega double see paper * */ -CV_EXPORTS void GradientDericheX(InputArray _op, OutputArray _dst, double alphaDerive,double alphaMean); +CV_EXPORTS_W void GradientDericheX(InputArray op, OutputArray dst, double alpha,double omega); } } diff --git a/modules/ximgproc/samples/dericheSample.py b/modules/ximgproc/samples/dericheSample.py new file mode 100644 index 000000000..6468b07c8 --- /dev/null +++ b/modules/ximgproc/samples/dericheSample.py @@ -0,0 +1,60 @@ +import sys +import numpy as np +import cv2 as cv + +def AddSlider(sliderName,windowName,minSlider,maxSlider,valDefault, update=[]): + if update is None: + cv.createTrackbar(sliderName, windowName, valDefault,maxSlider-minSlider+1) + else: + cv.createTrackbar(sliderName, windowName, valDefault,maxSlider-minSlider+1, update) + cv.setTrackbarMin(sliderName, windowName, minSlider) + cv.setTrackbarMax(sliderName, windowName, maxSlider) + cv.setTrackbarPos(sliderName, windowName, valDefault) +class Filtrage: + def __init__(self): + self.s =0 + self.alpha = 100 + self.omega = 100 + self.updateFiltre=True + self.img=[] + self.dximg=[] + self.dyimg=[] + self.module=[] + def DericheFilter(self): + self.dximg = cv.ximgproc.GradientDericheX( self.img, self.alpha/100., self.omega/1000. ) + self.dyimg = cv.ximgproc.GradientDericheY( self.img, self.alpha/100., self.omega/1000. ) + dx2=self.dximg*self.dximg + dy2=self.dyimg*self.dyimg + self.module = np.sqrt(dx2+dy2) + cv.normalize(src=self.module,dst=self.module,norm_type=cv.NORM_MINMAX) + def SlideBarDeriche(self): + cv.destroyWindow(self.filename) + cv.namedWindow(self.filename) + AddSlider("alpha",self.filename,1,400,self.alpha,self.UpdateAlpha) + AddSlider("omega",self.filename,1,1000,self.omega,self.UpdateOmega) + + def UpdateOmega(self,x ): + self.updateFiltre=True + self.omega=x + def UpdateAlpha(self,x ): + self.updateFiltre=True + self.alpha=x + def run(self,argv): + # Load the source image + self.filename = argv[0] if len(argv) > 0 else "../doc/pics/corridor_fld.jpg" + self.img=cv.imread(self.filename,cv.IMREAD_GRAYSCALE) + if self.img is None: + print ('cannot read file') + return + self.SlideBarDeriche() + while True: + cv.imshow(self.filename,self.img) + if self.updateFiltre: + self.DericheFilter() + cv.imshow("module",self.module) + self.updateFiltre =False + code = cv.waitKey(10) + if code==27: + break +if __name__ == '__main__': + Filtrage().run(sys.argv[1:]) diff --git a/modules/ximgproc/src/deriche_filter.cpp b/modules/ximgproc/src/deriche_filter.cpp index 3a20b2cf1..635004972 100644 --- a/modules/ximgproc/src/deriche_filter.cpp +++ b/modules/ximgproc/src/deriche_filter.cpp @@ -46,23 +46,23 @@ Using Canny's criteria to derive a recursively implemented optimal edge detector namespace cv { namespace ximgproc { template static void -VerticalIIRFilter(Mat &img,Mat &dst,const Range &r,double alphaDerive) +VerticalIIRFilter(Mat &img,Mat &dst,const Range &r,double alpha,double omega) { float *f2; int tailleSequence = (img.rows>img.cols) ? img.rows : img.cols; Mat matG1(1, tailleSequence, CV_64FC1), matG2(1, tailleSequence, CV_64FC1); double *g1 = matG1.ptr(0), *g2 = (double*)matG2.ptr(0); - double kp = pow(1 - exp(-alphaDerive), 2.0) / exp(-alphaDerive); - double a1, a2, a3, a4; + double a2, a3; double b1, b2; int rows = img.rows, cols = img.cols; + double c = (1 - 2 * exp(-alpha)*cos(omega) + exp(-2 * alpha)) / (exp(-alpha)*sin(omega)); + + double a = -c * exp(-alpha)*sin(omega); + a2 = 1;// kp*exp(-alpha); + a3 = 1;//-kp*exp(-alpha); + b1 = -2 * exp(-alpha)*cos(omega); + b2 = exp(-2 * alpha); - kp = pow(1 - exp(-alphaDerive), 2.0) / exp(-alphaDerive); - a1 = 0; - a2 = kp*exp(-alphaDerive), a3 = -kp*exp(-alphaDerive); - a4 = 0; - b1 = 2 * exp(-alphaDerive); - b2 = -exp(-2 * alphaDerive); for (int j = r.start; j(0); c1 += (rows - 1)*cols + j; i = rows - 1; - g2[i] = (a3 + a4)* *c1; + g2[i] = a3 * *c1; i--; c1 -= cols; - g2[i] = a3* c1[cols] + a4 * c1[cols] + (b1)*g2[i + 1]; + g2[i] = a3* c1[cols] + (b1)*g2[i + 1]; i--; c1 -= cols; for (i = rows - 3; i >= 0; i--, c1 -= cols) - g2[i] = a3*c1[cols] + a4* c1[2 * cols] + - b1*g2[i + 1] + b2*g2[i + 2]; + g2[i] = a3*c1[cols] - + b1*g2[i + 1] - b2*g2[i + 2]; for (i = 0; i(a*(g1[i] - g2[i])); } } template static void -HorizontalIIRFilter(Mat &img, Mat &dst, const Range &r, double alphaDerive) +HorizontalIIRFilter(Mat &img, Mat &dst, const Range &r, double alpha, double omega) { float *f1; int rows = img.rows, cols = img.cols; int tailleSequence = (rows>cols) ? rows : cols; Mat matG1(1, tailleSequence, CV_64FC1), matG2(1, tailleSequence, CV_64FC1); double *g1 = (double*)matG1.ptr(0), *g2 = (double*)matG2.ptr(0); - double kp;; - double a1, a2, a3, a4; + double a,a2, a3; double b1, b2; + double c = (1 - 2 * exp(-alpha)*cos(omega) + exp(-2 * alpha)) / (exp(-alpha)*sin(omega)); - kp = pow(1 - exp(-alphaDerive), 2.0) / exp(-alphaDerive); - a1 = 0; - a2 = kp*exp(-alphaDerive); - a3 = -kp*exp(-alphaDerive); - a4 = 0; - b1 = 2 * exp(-alphaDerive); - b2 = -exp(-2 * alphaDerive); + a = -c*exp(-alpha)*sin(omega); + a2 = 1;// kp*exp(-alpha); + a3 = 1;//-kp*exp(-alpha); + b1 = -2 * exp(-alpha)*cos(omega); + b2 = exp(-2 * alpha); for (int i = r.start; i(i); T *c1 = img.ptr(i); int j = 0; - g1[j] = (a1 + a2)* *c1; + g1[j] = a2* *c1; j++; c1++; - g1[j] = a1 * c1[0] + a2*c1[j - 1] + (b1)* g1[j - 1]; + g1[j] = a2*c1[j - 1] - (b1)* g1[j - 1]; j++; c1++; for (j = 2; j(0); c1 += i*cols + cols - 1; j = cols - 1; - g2[j] = (a3 + a4)* *c1; + g2[j] = a3* *c1; j--; c1--; - g2[j] = (a3 + a4) * c1[1] + b1 * g2[j + 1]; + g2[j] = a3 * c1[1] - b1 * g2[j + 1]; j--; c1--; for (j = cols - 3; j >= 0; j--, c1--) - g2[j] = a3*c1[1] + a4*c1[2] + b1*g2[j + 1] + b2*g2[j + 2]; + g2[j] = a3*c1[1] - b1*g2[j + 1] - b2*g2[j + 2]; for (j = 0; j(a*(g1[j] - g2[j])); } } @@ -151,15 +149,17 @@ class ParallelGradientDericheYCols : public ParallelLoopBody private: Mat &img; Mat &dst; - double alphaDerive; + double alpha; + double omega; bool verbose; public: - ParallelGradientDericheYCols(Mat &imgSrc, Mat &d, double ald) : + ParallelGradientDericheYCols(Mat &imgSrc, Mat &d, double ald,double o) : img(imgSrc), dst(d), - alphaDerive(ald), + alpha(ald), + omega(o), verbose(false) { int type = img.depth(); @@ -175,19 +175,19 @@ public: switch (img.depth()) { case CV_8U: - VerticalIIRFilter(img,dst,range, alphaDerive); + VerticalIIRFilter(img,dst,range, alpha,omega); break; case CV_8S: - VerticalIIRFilter(img, dst, range, alphaDerive); + VerticalIIRFilter(img, dst, range, alpha, omega); break; case CV_16U: - VerticalIIRFilter(img, dst, range, alphaDerive); + VerticalIIRFilter(img, dst, range, alpha, omega); break; case CV_16S: - VerticalIIRFilter(img, dst, range, alphaDerive); + VerticalIIRFilter(img, dst, range, alpha, omega); break; case CV_32F: - VerticalIIRFilter(img, dst, range, alphaDerive); + VerticalIIRFilter(img, dst, range, alpha, omega); break; default: return; @@ -204,14 +204,16 @@ class ParallelGradientDericheYRows : public ParallelLoopBody private: Mat &img; Mat &dst; - double alphaMoyenne; + double alpha; + double omega; bool verbose; public: - ParallelGradientDericheYRows(Mat& imgSrc, Mat &d, double alm) : + ParallelGradientDericheYRows(Mat& imgSrc, Mat &d, double ald,double o) : img(imgSrc), dst(d), - alphaMoyenne(alm), + alpha(ald), + omega(o), verbose(false) { int type = img.depth(); @@ -228,42 +230,44 @@ public: int tailleSequence = (img.rows>img.cols) ? img.rows : img.cols; Mat matG1(1,tailleSequence,CV_64FC1), matG2(1,tailleSequence,CV_64FC1); double *g1 = matG1.ptr(0), *g2 = matG2.ptr(0); - double k, a5, a6, a7, a8; - double b3, b4; int cols = img.cols; - k = pow(1 - exp(-alphaMoyenne), 2.0) / (1 + 2 * alphaMoyenne*exp(-alphaMoyenne) - exp(-2 * alphaMoyenne)); - a5 = k; - a6 = k*exp(-alphaMoyenne)*(alphaMoyenne - 1); - a7 = k*exp(-alphaMoyenne)*(alphaMoyenne + 1); - a8 = -k*exp(-2 * alphaMoyenne); - b3 = 2 * exp(-alphaMoyenne); - b4 = -exp(-2 * alphaMoyenne); + + double a2po2 = (alpha*alpha + omega * omega); + double k = (1 - 2 * exp(-alpha)*cos(omega) + exp(-2 * alpha))*a2po2; + k = k / (2 * alpha*exp(-alpha)*sin(omega) + omega - omega * exp(-2 * alpha)); + double c1 = k * alpha / a2po2; + double c2 = k * omega / a2po2; + double a0 = c2; + double a1 = (-c2 * cos(omega) + c1 * sin(omega))*exp(-alpha); + double b1 = -2 * exp(-alpha)*cos(omega); + double b2 = exp(-2 * alpha); + double a2 = a1 - c2 * b1, a3 = -c2 * b2; for (int i = range.start; i(i); f1 = img.ptr(i); int j = 0; - g1[j] = (a5 + a6)* *f1; + g1[j] = (a0 + a1)* *f1; j++; f1++; - g1[j] = a5 * f1[0] + a6*f1[j - 1] + (b3)* g1[j - 1]; + g1[j] = a0 * f1[0] + a1*f1[j - 1] - b1* g1[j - 1]; j++; f1++; for (j = 2; j= 0; j--, f1--) - g2[j] = a7*f1[1] + a8*f1[2] + b3*g2[j + 1] + b4*g2[j + 2]; + g2[j] = a2*f1[1] + a3*f1[2] - b1*g2[j + 1] - b2*g2[j + 2]; for (j = 0; jcols) ? rows : cols; Mat matG1(1,tailleSequence,CV_64FC1), matG2(1,tailleSequence,CV_64FC1); double *g1 = (double*)matG1.ptr(0), *g2 = (double*)matG2.ptr(0); - double k, a5, a6, a7, a8 = 0; - double b3, b4; + double a2po2 = (alpha*alpha + omega * omega); + double k = (1 - 2 * exp(-alpha)*cos(omega) + exp(-2 * alpha))*a2po2; + k = k / (2 * alpha*exp(-alpha)*sin(omega) + omega - omega * exp(-2 * alpha)); + double c1 = k * alpha / a2po2; + double c2 = k * omega / a2po2; + double a0 = c2; + double a1 = (-c2 * cos(omega) + c1 * sin(omega))*exp(-alpha); + double b1 = -2 * exp(-alpha)*cos(omega); + double b2=exp(-2*alpha); + double a2=a1-c2*b1, a3=-c2*b2; - k = pow(1 - exp(-alphaMoyenne), 2.0) / (1 + 2 * alphaMoyenne*exp(-alphaMoyenne) - exp(-2 * alphaMoyenne)); - a5 = k, a6 = k*exp(-alphaMoyenne)*(alphaMoyenne - 1); - a7 = k*exp(-alphaMoyenne)*(alphaMoyenne + 1), a8 = -k*exp(-2 * alphaMoyenne); - b3 = 2 * exp(-alphaMoyenne); - b4 = -exp(-2 * alphaMoyenne); for (int j = range.start; j(0); f1 += j; int i = 0; - g1[i] = (a5 + a6)* *f1; + g1[i] = (a0 + a1)* *f1; i++; f1 += cols; - g1[i] = a5 * *f1 + a6 * f1[-cols] + (b3)* g1[i - 1]; + g1[i] = a0 * *f1 + a1 * f1[-cols] - (b1)* g1[i - 1]; i++; f1 += cols; for (i = 2; i(0); f1 += (rows - 1)*cols + j; i = rows - 1; - g2[i] = (a7 + a8)* *f1; + g2[i] = (a2 + a3)* *f1; i--; f1 -= cols; - g2[i] = (a7 + a8)* f1[cols] + (b3)*g2[i + 1]; + g2[i] = (a2 + a3)* f1[cols] - b2*g2[i + 1]; i--; f1 -= cols; for (i = rows - 3; i >= 0; i--, f1 -= cols) - g2[i] = a7*f1[cols] + a8* f1[2 * cols] + - b3*g2[i + 1] + b4*g2[i + 2]; + g2[i] = a2*f1[cols] + a3* f1[2 * cols] - + b1*g2[i + 1] - b2*g2[i + 2]; for (i = 0; i(i)) + (j*img.channels()); @@ -358,14 +367,16 @@ class ParallelGradientDericheXRows : public ParallelLoopBody private: Mat &img; Mat &dst; - double alphaDerive; + double alpha; + double omega; bool verbose; public: - ParallelGradientDericheXRows(Mat& imgSrc, Mat &d, double ald) : + ParallelGradientDericheXRows(Mat& imgSrc, Mat &d, double ald, double o) : img(imgSrc), dst(d), - alphaDerive(ald), + alpha(ald), + omega(o), verbose(false) { int type = img.depth(); @@ -381,19 +392,19 @@ public: switch (img.depth()) { case CV_8U: - HorizontalIIRFilter(img,dst,range,alphaDerive); + HorizontalIIRFilter(img,dst,range, alpha,omega); break; case CV_8S: - HorizontalIIRFilter(img, dst, range, alphaDerive); + HorizontalIIRFilter(img, dst, range, alpha, omega); break; case CV_16U: - HorizontalIIRFilter(img, dst, range, alphaDerive); + HorizontalIIRFilter(img, dst, range, alpha, omega); break; case CV_16S: - HorizontalIIRFilter(img, dst, range, alphaDerive); + HorizontalIIRFilter(img, dst, range, alpha, omega); break; case CV_32F: - HorizontalIIRFilter(img, dst, range, alphaDerive); + HorizontalIIRFilter(img, dst, range, alpha, omega); break; default: return; @@ -404,10 +415,11 @@ public: }; }; -void GradientDericheY(InputArray _op, OutputArray _dst,double alphaDerive, double alphaMean) +void GradientDericheY(InputArray _op, OutputArray _dst,double alphaDerive, double omega) { std::vector planSrc; split(_op, planSrc); + std::vector planTmp; std::vector planDst; for (size_t i = 0; i < planSrc.size(); i++) @@ -415,15 +427,15 @@ void GradientDericheY(InputArray _op, OutputArray _dst,double alphaDerive, doubl planTmp.push_back(Mat(_op.size(), CV_32FC1)); planDst.push_back(Mat(_op.size(), CV_32FC1)); CV_Assert(planSrc[i].isContinuous() && planTmp[i].isContinuous() && planDst[i].isContinuous()); - ParallelGradientDericheYCols x(planSrc[i], planTmp[i], alphaDerive); + ParallelGradientDericheYCols x(planSrc[i], planTmp[i], alphaDerive,omega); parallel_for_(Range(0, planSrc[i].cols), x, getNumThreads()); - ParallelGradientDericheYRows xr(planTmp[i], planDst[i], alphaMean); + ParallelGradientDericheYRows xr(planTmp[i], planDst[i], alphaDerive, omega); parallel_for_(Range(0, planTmp[i].rows), xr, getNumThreads()); } merge(planDst, _dst); } -void GradientDericheX(InputArray _op, OutputArray _dst, double alphaDerive, double alphaMean) +void GradientDericheX(InputArray _op, OutputArray _dst, double alpha, double omega) { std::vector planSrc; split(_op, planSrc); @@ -435,9 +447,9 @@ void GradientDericheX(InputArray _op, OutputArray _dst, double alphaDerive, doub planDst.push_back(Mat(_op.size(), CV_32FC1)); CV_Assert(planSrc[i].isContinuous() && planTmp[i].isContinuous() && planDst[i].isContinuous()); - ParallelGradientDericheXRows x(planSrc[i], planTmp[i], alphaDerive); + ParallelGradientDericheXRows x(planSrc[i], planTmp[i], alpha, omega); parallel_for_(Range(0, planSrc[i].rows), x, getNumThreads()); - ParallelGradientDericheXCols xr(planTmp[i], planDst[i], alphaMean); + ParallelGradientDericheXCols xr(planTmp[i], planDst[i], alpha, omega); parallel_for_(Range(0, planTmp[i].cols), xr, getNumThreads()); } merge(planDst, _dst); diff --git a/modules/ximgproc/test/test_deriche_filter.cpp b/modules/ximgproc/test/test_deriche_filter.cpp new file mode 100644 index 000000000..65aabae84 --- /dev/null +++ b/modules/ximgproc/test/test_deriche_filter.cpp @@ -0,0 +1,41 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +#include "test_precomp.hpp" + +namespace opencv_test { namespace { + +TEST(ximgproc_DericheFilter, regression) +{ + Mat img = Mat::zeros(64, 64, CV_8UC3); + Mat res = Mat::zeros(64, 64, CV_32FC3); + img.at(31, 31) = Vec3b(1, 2, 4); + double a = 0.5; + double w = 0.0005; + Mat dst; + + ximgproc::GradientDericheX(img, dst, a, w); + double c = pow(1 - exp(-a), 2.0) * exp(a); + double k = pow(a*(1 - exp(-a)), 2.0) / (1 + 2 * a*exp(-a) - exp(-2 * a)); + for (int i = 0; i < img.rows; i++) + { + double n = -31 + i; + for (int j = 0; j < img.cols; j++) + { + double m = -31 + j; + double x = -c * exp(-a * fabs(m))*sin(w*m); + x = x * (k*(a*sin(w*fabs(n)) + w * cos(w*fabs(n)))*exp(-a * fabs(n))) / (a*a + w * w); + x = x / (w*w); + float xx=static_cast(x); + res.at(i, j) = Vec3f(xx, 2 * xx, 4 * xx); + } + } + EXPECT_LE(cv::norm(res, dst, NORM_INF), 1e-5); + + Mat dst2; + ximgproc::GradientDericheY(img, dst2, a, w); + cv::transpose(dst2, dst2); + EXPECT_LE(cv::norm(dst2, dst, NORM_INF), 1e-5); +} +} +} // namespace