我正在努力寻找这个问题的答案,我对马尔可夫链的使用还不太理解,希望能得到一些帮助:
[输入图像] https://i.sstatic.net/r9XCE.png
[输出图像示例] https://i.sstatic.net/3pllU.png
这就是我们开始的地方,经典的设置。
我想将这张图像转换为只有黑白两种颜色,但必须使用马尔可夫链的概率,我对此完全不理解。
有谁能给我一些提示吗?我认为我们需要随机选择N次像素,并应用一些概率魔法来将其转换为黑色或白色(基于概率和邻居像素)。
提前感谢(我不是特别在寻找代码,而是希望了解实现的逻辑)。
回答:
以下是使用马尔可夫链将图像二值化的一种方法:
假设(根据马尔可夫属性)一个像素的值仅依赖于其邻居(假设使用4邻域),我们需要估计在给定其n个邻居像素为白色时,该像素为白色的概率,即,对于4邻域,首先计算条件概率P(x(i,j)=1 | n个邻居也为1),其中n=0,1,2,3,4(此外,我们使用全局阈值来计算概率,如下面的代码所示,这可以被视为训练阶段):
from skimage.io import imreadim = imread('https://i.sstatic.net/r9XCE.png')def count_nbrs(im, i, j, th): # 计算给定像素的邻居像素中有多少个为1,根据阈值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 countth = 140 #np.mean(im) # 全局阈值nnbrs = 5 # 使用4邻域freq = np.zeros(nnbrs)tot = np.zeros(nnbrs)h, w, _ = im.shapefor 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] += 1prob = freq/tot print(prob)# 在图像中,Prob(x(i,j)=1|n个邻居为1)的概率,n=0,1,2,3,4# [0.00775595 0.09712838 0.48986784 0.91385768 0.99566323]
现在让我们使用这些估计的概率来将彩色图像中的每个像素转换为黑白,根据其邻居情况(这可以被视为测试阶段):
h, w, _ = im.shapeim1 = 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) # 计算邻居中白色像素的数量
im1[i,j] = 255*(prob[c] > 0.5) # 使用Prob向量决定像素的值plt.imshow(im1, 'gray')plt.show()
获得的二值图像质量远优于全局阈值处理(可以查看对比)。
您可以随机选择像素,并计算给定邻居中1的数量(经过阈值处理)时像素值为1的概率,相应地设置像素值,使用以下代码进行大量迭代N次,将会得到相似的二值图像。
N = 100000h, w, _ = im.shapeim1 = 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()
下面的动画展示了如何使用上述代码生成二值图像。