I wrote Python code (sorry, not C ++) that would mask the adaptive threshold value. It is not very fast, but it does what you want and you can use it as the basis for C ++ code. It works as follows:
- Sets masked image pixels to zero.
- Defines the number of unmasked neighbors in the convolution block for each pixel.
- Converts and averages it by the number of invisible neighbors inside the block. This gives an average value in a block of pixel neighborhood.
- Thresholds, comparing the image with the average values โโof the neighborhood,
mean_conv - Adds the hidden (non-threshold) part of the image back.

Images show the initial image, mask, final processed image.
Here is the code:
import cv import numpy from scipy import signal def thresh(a, b, max_value, C): return max_value if a > b - C else 0 def mask(a,b): return a if b > 100 else 0 def unmask(a,b,c): return b if c > 100 else a v_unmask = numpy.vectorize(unmask) v_mask = numpy.vectorize(mask) v_thresh = numpy.vectorize(thresh) def block_size(size): block = numpy.ones((size, size), dtype='d') block[(size - 1 ) / 2, (size - 1 ) / 2] = 0 return block def get_number_neighbours(mask,block): '''returns number of unmasked neighbours of every element within block''' mask = mask / 255.0 return signal.convolve2d(mask, block, mode='same', boundary='symm') def masked_adaptive_threshold(image,mask,max_value,size,C): '''thresholds only using the unmasked elements''' block = block_size(size) conv = signal.convolve2d(image, block, mode='same', boundary='symm') mean_conv = conv / get_number_neighbours(mask,block) return v_thresh(image, mean_conv, max_value,C) image = cv.LoadImageM("image.png", cv.CV_LOAD_IMAGE_GRAYSCALE) mask = cv.LoadImageM("mask.png", cv.CV_LOAD_IMAGE_GRAYSCALE)
After writing this, I found this great link that has a good explanation with lots of sample images, I used their text image for the above example.
Note. Unnecessary masks do not seem to be respected by scipy signal.convolve2d() , so the above workarounds were necessary.
fraxel
source share