Skip to content

Conversation

@samyak-268
Copy link
Contributor

This is in response to the feature request: 4024 and is same as PR.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You probably forgot to add the adapted header file to your PR and therefore it crashes. Prototypes of your functions need to be in the public part of the module namespace.

@samyak-268
Copy link
Contributor Author

@StevenPuttemans : Working on that.

@StevenPuttemans
Copy link

👍

@samyak-268
Copy link
Contributor Author

@StevenPuttemans : Added function prototype. Could you review this?
Thanks!

@StevenPuttemans
Copy link

I do not have review powers, but I can take a look at it tomorrow!

@samyak-268
Copy link
Contributor Author

Sure! Thanks a lot 👍

@vpisarev
Copy link
Contributor

vpisarev commented Mar 3, 2015

@samyak-268, thanks a lot! Can you please add some doxygen comments with the function and parameter description?

@samyak-268
Copy link
Contributor Author

@vpisarev : Sure, will be doing that very soon.

@samyak-268
Copy link
Contributor Author

@vpisarev I added some doxygen comments along with the code.

@samyak-268
Copy link
Contributor Author

@vpisarev @StevenPuttemans : I was thinking of adding some sample/tutorial code for the Niblack module. Should I send a fresh PR for that or updating this one would be fine?

@StevenPuttemans
Copy link

O simply include the sample here!

Added doxygen comments and parameter descriptions.
Added sample code demonstrating Niblack thresholding.
@samyak-268
Copy link
Contributor Author

@StevenPuttemans @vpisarev Updated PR with the following changes:

  • Changed Niblack threshold from (mean - (k*std_dev)) to (mean + (k*std_dev)) which is the correct implementation as per the original text.
  • Added sample code that demonstrates the use of Niblack thresholding. The value of k in the sample can be modified using track-bar.

Adding the sample made me realize that I was missing a CV_EXPORTS_W in the header!

@vpisarev
Copy link
Contributor

vpisarev commented Apr 3, 2015

@samyak-268, thanks! May I ask you to do 2 more things:

  1. as far as I can see, using double for stddev image is not mandatory in this case; can you change it do float? (which is ~5x faster than double on ARM)
  2. can you add some simple regression test?

@samyak-268
Copy link
Contributor Author

@vpisarev : Sure. I am a little busy for the next few days. Will look into this as soon as I find time. Hope that's all right.

@vpisarev
Copy link
Contributor

ok, I have yet another request. This seems to be just one relatively small function. Can you please put it to ximgproc (extended/advanced image processing) instead of creating a whole new module?

@samyak-268
Copy link
Contributor Author

Coming back to this PR after quite a long time!

@vpisarev : I have changed the type of Mat stddev from double to float. Regarding your other suggestion, what sort of checks is a regression test supposed to perform? It would be helpful if you could guide me to some existing regression tests within the repo. Is the modules/ximgproc/test/ directory the right place to look for the same?

All Niblack related code now resides inside ximgproc and not as a
separate new module.
@samyak-268
Copy link
Contributor Author

@StevenPuttemans : Included everything within ximgproc. The code no longer resides in it's own module. Is this what you were looking for?
Thanks!

@StevenPuttemans
Copy link

Seems good to me, but you will need acceptance of @vpisarev

@samyak-268
Copy link
Contributor Author

Hey! Just a gentle reminder. It's been quite a while, anything that needs to be done from my end in regards to this PR? Thanks!

@StevenPuttemans
Copy link

@samyak-268 I am afraid not. Seeing that I know of PR's waiting since June ... I want to ask you to wait at least a little bit more :)

Ow and you could merge the 3 commits into 1, to facilitate the merging faster.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest to add image conversion to grayscale (IMREAD_GRAYSCALE flag), otherwise the exception will be thrown here.

@mshabunin
Copy link
Contributor

I get some strange results using your example:
image

It seems something goes wrong.

@samyak-268
Copy link
Contributor Author

@mshabunin : A little busy for a few days. I'll look into your comments soon. Thanks!

@mschoeneck
Copy link

I have written some statistical threshold functions some time ago from this paper http://www.math-info.univ-paris5.fr/~vincent/articles/DRR_nick_binarization_09.pdf .

I have never really used this, but the first impression looked good. Perhabs you can use this for your implementation.

void statisticalThreshold(InputArray inputImage, OutputArray outputImage, int maxValue, int blockSize, double k, int algorithmType) {
    CV_Assert(!inputImage.empty() && (inputImage.kind() == _InputArray::MAT || inputImage.kind() == _InputArray::UMAT));
    CV_Assert(outputImage.kind() == _OutputArray::MAT || outputImage.kind() == _OutputArray::UMAT);

    UMat _inputImage = inputImage.getUMat();
    outputImage.create(inputImage.size(), CV_8U);
    UMat _outputImage = outputImage.getUMat();
    int nCompareType = CMP_GT;
    //int nNumberOfPixels = _inputImage.total();

    UMat normImage, meanImage, meanImageSquare, tempImage1, tempImage2, varianceImage, stdDevImage;
    normalize(_inputImage, normImage, 0, 255, NORM_MINMAX, CV_32F);
    boxFilter(normImage, meanImage, CV_32F, Size(blockSize, blockSize), Point(-1, -1), true, BORDER_REFLECT101);
    sqrBoxFilter(normImage, tempImage1, CV_32F, Size(blockSize, blockSize), Point(-1, -1), true, BORDER_REFLECT101);
    multiply(meanImage, meanImage, meanImageSquare);
    subtract(tempImage1, meanImageSquare, varianceImage);

    // Mean and squared mean image with integral image
    //int windowSizeHalf = blockSize / 2;
    //copyMakeBorder(_inputImage, borderImage, windowSizeHalf, windowSizeHalf, windowSizeHalf, windowSizeHalf, BORDER_REFLECT101);
    //integral(borderImage, integralImage, integralSquareImage, CV_32F, CV_32F);
    //UMat addImage1, addImage2, stdDevImage;
    //add(integralImage(Rect(0, 0, _inputImage.cols, _inputImage.rows)), integralImage(Rect(blockSize-1, blockSize-1, _inputImage.cols, _inputImage.rows)), addImage1);
    //add(integralImage(Rect(blockSize-1, 0, _inputImage.cols, _inputImage.rows)), integralImage(Rect(0, blockSize-1, _inputImage.cols, _inputImage.rows)), addImage2);
    //addWeighted(addImage1, 1. / (blockSize*blockSize), addImage2, -1. / (blockSize*blockSize), 0, meanImage, CV_32F);
    //multiply(meanImage, meanImage, meanSquareImage, 1.0, CV_32F);
    //add(integralSquareImage(Rect(0, 0, _inputImage.cols, _inputImage.rows)), integralSquareImage(Rect(blockSize, blockSize, _inputImage.cols, _inputImage.rows)), addImage1);
    //add(integralSquareImage(Rect(blockSize, 0, _inputImage.cols, _inputImage.rows)), integralSquareImage(Rect(0, blockSize, _inputImage.cols, _inputImage.rows)), addImage2);
    //addWeighted(addImage1, 1. / (blockSize*blockSize), addImage2, -1. / (blockSize*blockSize), 0, squareMeanImage, CV_32F);
    //subtract(tempImage1, tempImage2, subImage, noArray(), CV_32F);
    //cv::sqrt(subImage, stdDevImage);

    switch (algorithmType) {
    case CV_THRESH_NIBLACK:
        nCompareType = CMP_LE;
    case CV_THRESH_NIBLACK_INV:
        sqrt(varianceImage, stdDevImage);
        scaleAdd(stdDevImage, k, meanImage, tempImage1);
        break;
    case CV_THRESH_SAUVOLA:
        nCompareType = CMP_LE;
    case CV_THRESH_SAUVOLA_INV:
        sqrt(varianceImage, stdDevImage);
        stdDevImage.convertTo(tempImage1, CV_32F, (1. / 128), -1.);
        tempImage1.convertTo(tempImage2, CV_32F, k, 1.);
        multiply(meanImage, tempImage2, tempImage1, 1.);
        break;
    case CV_THRESH_WOLF:
        nCompareType = CMP_LE;
    case CV_THRESH_WOLF_INV:
        sqrt(varianceImage, stdDevImage);
        multiply(stdDevImage, meanImage, tempImage2, (k / 128.));
        scaleAdd(meanImage, (1. - k), tempImage2, tempImage1);
        break;
    case CV_THRESH_NICK:
        nCompareType = CMP_LE;
    case CV_THRESH_NICK_INV:
        add(meanImageSquare, varianceImage, tempImage1);
        //scaleAdd(meanImageSquare, nNumberOfPixels / (nNumberOfPixels - 1.), varianceImage, tempImage2);
        sqrt(tempImage1, tempImage2);
        scaleAdd(tempImage2, k, meanImage, tempImage1);
        break;
    default:
        CV_Error(Error::StsBadArg, "Threshold type unknown.");
    }
    compare(normImage, tempImage1, meanImage, nCompareType);
    meanImage.convertTo(_outputImage, CV_8U, maxValue, 0);

    return;
}

@vpisarev vpisarev self-assigned this Dec 14, 2015
@vpisarev
Copy link
Contributor

thanks! let's put it in 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants