# cv::fastNlMeansDenoising does not return

Hi,

I have some problems with cv::findCirclesGrid. Some of my image have very poor contrast and cv::findCircleGrid sometimes takes forever (several minutes) before it returns false.

Therefore, I want to make a better contrast using cv::equalizeHist. The problem with this is, that the image gets really noisy. I tried to denoise it with cv::fastNlMeansDenoising.

I waited several minutes, but the function did not return and I have no idea what to do now.

Has anyone an idea how I could denoise (or generally prepare) my images before using cv::findCirclesGrid? I use Visual Studio 2013 Pro and OpenCv 2.4.9 (x86).

I attach one sample image bevor and after cv::equalizeHist. And here is my code:

for (auto &img : images)
{
cv::Mat gray;

cv::cvtColor(img, gray, CV_BGRA2GRAY);

cv::Mat grayFiltered(gray.rows, gray.cols, gray.type());

//cv::Ptr<cv::CLAHE> clahe = cv::createCLAHE();
//clahe->setClipLimit(2);

//clahe->apply(gray, gray);
cv::equalizeHist(gray, gray);

cv::fastNlMeansDenoising(gray, grayFiltered);
//cv::threshold(gray, gray, 160, 255, CV_THRESH_BINARY); // Needs a different threshold, depending on the actual image
}


low_contrast.png

better_contrast_but_noisy.png

edit retag close merge delete

Sort by » oldest newest most voted

In this case, you can simply use normalize to enhance the contrast.

more

I tried normalize (with MINMAX and [0 255]) and it works as long as I don't have reflexions in the background. I tried to remove these reflexions (threshold + inpaint), but the regions around the reflexions are very bright so normalize makes no noticeable changes. I don't know if it is really possible to remove such bright spots in the background.

Here is an example for an image with reflexion. bright_spots.png

( 2015-01-13 08:35:52 -0500 )edit

If you are looking for a fast solution, you can make norm/normalize use only the center part of the image to compute the multipliers and normalize the entire image. In the bottom part of the documentation of normalize it is explained how this could be done.

( 2015-01-13 09:55:52 -0500 )edit

I tried to use norm + Mat::convertTo, as it is mentioned in the doc to normalize. The result is a almost all withe image: almoste_all_white.png

This is the code I used

cv::Mat roi(gray, cv::Rect(gray.rows / 2 - 350, gray.cols / 2 - 350, 700, 700));
double norm = cv::norm(/*gray*/roi, CV_L2/*, roi*/);
gray.convertTo(grayFiltered, grayFiltered.type(), norm);


I must confess, I don't really understand how to use the Lx Norms on images. When I understand the documentation of normalize correctly, I cannot use normalize directly with an input mask to modify the whole image. So I have to use the norm + convertTo combination. One problem is, that norm does not allow NORM_MINMAX. So I don't really know if I use it the right way.

( 2015-01-14 07:23:58 -0500 )edit

@Tankard Print the value of norm. I would guess that alpha has to be 256/norm, or something proportional to that

( 2015-01-14 08:00:42 -0500 )edit

The norm value for this image is 33289.517779625465. 256/norm or pixelCount/norm don't work. I don't really know what would be a "normal" value for alpha.

( 2015-01-14 08:45:33 -0500 )edit

cv::Mat roi(gray, cv::Rect(gray.rows / 2 - 350, gray.cols / 2 - 350, 700, 700));
double minVal, maxVal;
cv::minMaxLoc(roi, &minVal, &maxVal);
gray.convertTo(grayFiltered, grayFiltered.type(), 255.0/(maxVal-minVal), -minVal);

( 2015-01-14 09:27:34 -0500 )edit

Thanks a lot. This worked for the images I have so far. I had no idea about cv::minMaxLoc.

( 2015-01-14 09:57:24 -0500 )edit

@Tankard Very well! If you problem is solved, can you please accept the answer? (Tag under the answer score)

( 2015-01-15 04:11:07 -0500 )edit

Official site

GitHub

Wiki

Documentation