'Binarization for large directional gradient grayscale image
I am trying to binarize grayscale images with large gradients in one direction.
Apparently, normal methods including Otsu's are not good enough to do this job.
I tried to use Sobel gradients and the Bradley adaptive thresholding, by which I get OK results, but there are some issues as indicated in the attached picture.
From the section gradient curve, we could see the gradient difference is very big at the beginning, so I split the Sobel result and do the adaptive thresholding separately, and then fuse the two results together.
My question is:
Are there any other better methods to do this job? To better understand what I do, I post my sample python code here. Thanks for your attention.
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
def bradley_threshold(inputMat,ddepth):
nRows = inputMat.shape[0]
nCols = inputMat.shape[1]
sumMat = cv.integral(inputMat, ddepth)
S = max(nRows, nCols) / 8
T = 0.15
s2 = int(S / 2)
outputMat = np.zeros(inputMat.shape, np.uint8)
for i in range(nRows):
y1 = i - s2
y2 = i + s2
if y1 < 0:
y1 = 0
if y2 >= nRows:
y2 = nRows - 1
y1+=1
y2+=1
for j in range(nCols):
# set the SxS region
x1 = j - s2
x2 = j + s2
if x1 < 0:
x1 = 0
if x2 >= nCols:
x2 = nCols - 1;
x1 += 1
x2 += 1
count = (x2 - x1) * (y2 - y1)
sum = sumMat[y2, x2]-sumMat[y1, x2]-sumMat[y2, x1]+sumMat[y1, x1]
if inputMat[i, j] * count <= sum * (1.0 - T):
outputMat[i, j] = 0
else:
outputMat[i, j] = 255
return outputMat
if __name__ == '__main__':
gray = cv.imread('sample.png', cv.IMREAD_UNCHANGED)
image = cv.cvtColor(gray,cv.COLOR_GRAY2BGR)
blur = cv.medianBlur(gray, 3)
sobel = cv.Sobel(gray, cv.CV_32F, 1, 0, 1);
inverse = -sobel;
inverse[inverse < 0] = 0
thresh = bradley_threshold(inverse, cv.CV_32F)
splitter = 31
part1 = inverse[:,:31]
part2 = inverse[:,31:]
thresh1 = bradley_threshold(part1, cv.CV_32F)
thresh2 = bradley_threshold(part2, cv.CV_32F)
thresh_part = np.concatenate((thresh1, thresh2), axis=1)
cv.imwrite('bad_binary.png',thresh)
cv.imwrite('good_binary.png',thresh_part)
plt.imshow(thresh, cmap='gray')
plt.show()
plt.imshow(thresh_part, cmap='gray')
plt.show()
plt.plot(inverse[inverse.shape[0]-1, :])
plt.show()
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|




