这是使用马尔可夫链对图像进行二值化的一种方法:
假设(通过马尔可夫属性)一个像素值仅取决于它的邻居(让我们假设一个 4-nbd),让我们估计一个像素是白色的概率,因为它的 nbd 个像素是白色的,即,对于 4 -nbd,让我们首先计算 P(x(i,j)=1 | n 的 nbrs 也是 1) 的条件概率,其中对于 4-nbd,n=0,1,2,3,4 (另外,让我们使用全局阈值来计算概率,如以下代码所示,这可以被认为是训练阶段):
from skimage.io import imread
im = imread('https://i.stack.imgur.com/r9XCE.png')
def count_nbrs(im, i, j, th): # counts number of nbd pixels are 1 given a pixel, with threshold th
count = 0
count += np.mean(im[i-1,j]) > th
count += np.mean(im[i+1,j]) > th
count += np.mean(im[i,j-1]) > th
count += np.mean(im[i,j+1]) > th
return count
th = 140 #np.mean(im) # a global threshold
nnbrs = 5 # use 4-nbd
freq = np.zeros(nnbrs)
tot = np.zeros(nnbrs)
h, w, _ = im.shape
for i in range(1, h-1):
for j in range(1, w-1):
count = count_nbrs(im, i, j, th)
if np.mean(im[i,j]) > th:
freq[count] += 1
tot[count] += 1
prob = freq/tot
print(prob)
# Prob(x(i,j)=1|n of its nbrs are 1) in the image, for n=0,1,2,3,4
# [0.00775595 0.09712838 0.48986784 0.91385768 0.99566323]
现在让我们使用这些估计的概率将彩色图像中的每个像素更改为黑色和白色,具体取决于其 nbd(这可以被认为是测试阶段):
h, w, _ = im.shape
im1 = np.zeros((h, w))
for i in range(1, h-1):
for j in range(1, w-1):
c = count_nbrs(im, i, j, th) # count number of neighbors with white pixel
im1[i,j] = 255*(prob[c] > 0.5) # use Prob vector to determine value of the pixel
plt.imshow(im1, 'gray')
plt.show()
得到的二值图像质量比全局阈值好得多(检查一下)。
您可以随机选择像素并在给定 1 个 nbrs(阈值)的情况下计算像素值为 1 的概率,相应地设置像素值,使用具有大量迭代 N 的以下代码,它将导致相似的二值图像。
N = 100000
h, w, _ = im.shape
im1 = np.zeros((h, w))
for k in range(N):
i = np.random.randint(1,h-1,1)[0]
j = np.random.randint(1,w-1,1)[0]
c = count_nbrs(im, i, j, th)
im1[i,j] = 255*(prob[c] > 0.5)
plt.imshow(im1, 'gray')
plt.show()
下一个动画展示了如何使用上述代码生成二进制图像。