Ask Your Question

AdaptiveThreshold with non-square block sizes

asked 2018-12-13 03:36:46 -0600

racone gravatar image

updated 2018-12-13 03:53:04 -0600

berak gravatar image

Is there an elegant way, in C++, to use the adaptiveThreshold with a non-square block size? e.g. 5x1 or 3x15 In my case, I want the threshold to be calculated only in X and Y direction separately.

Using python, I can realize that by slicing the image into its rows and columns.


for row in range(0, img.shape[0]):
  imgThr[row:row+1, :] = cv2.adaptiveThreshold(img[row:row+1, :], 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 0)
edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted

answered 2018-12-13 03:56:40 -0600

berak gravatar image

updated 2018-12-13 04:15:11 -0600

cv::Mat has similar slicing options, than those you use in numpy already,

imgThr(Range(y,y+1), Range::all())

would be the c++ equivalent to the numpy:

imgThr[row:row+1, :]
edit flag offensive delete link more


@berak why can we change int blockSize in Size s in adaptiveThreshold? In source code, adaptiveThreshod uses boxFilter and gaussianBlur with a parameter of size type

LBerger gravatar imageLBerger ( 2018-12-13 04:03:17 -0600 )edit

hehe, i did not dare to look there, but now i will....

berak gravatar imageberak ( 2018-12-13 04:14:39 -0600 )edit

@LBerger, that might indeed be possible, but there are some limitations, like only 3,5,7,9,11 can be used, so the most "horizontal" kernel would be 11x3

berak gravatar imageberak ( 2018-12-13 04:19:02 -0600 )edit

where did you find limit ? gaussianBlur and boxFilter

LBerger gravatar imageLBerger ( 2018-12-13 04:23:19 -0600 )edit

minimum is here

i'm probably wrong about the maximum size, but there are hardcoded opencl kernels for certain sizes only

berak gravatar imageberak ( 2018-12-13 04:27:32 -0600 )edit

Thanks a lot for your help. I never heard of the Range feature before. However, it behaves different from my Python code and the adaptiveThreshold seems to ignore the range boundaries.


unsigned int nHeight = oImgInput.size().height;
for (int nY = 0; nY < nHeight; ++nY)
    const auto& oLine = oImgInput(cv::Range(nY, nY + 1), cv::Range::all());
    const auto& oLineResult = oImgOutput(cv::Range(nY, nY + 1), cv::Range::all());
    cv::adaptiveThreshold(oLine, oLineResult, 255, cv::ADAPTIVE_THRESH_MEAN_C, cv::THRESH_BINARY, 9, 0);

Explanation: The loop applies the adaptiveThreshold to each line and stores the result to oImgOutput. But the result image is exactly the same as if I apply the threshold to the entire image. Is the code wrong?

racone gravatar imageracone ( 2018-12-14 04:46:15 -0600 )edit

Question Tools

1 follower


Asked: 2018-12-13 03:36:46 -0600

Seen: 416 times

Last updated: Dec 13 '18