1 respuesta

La mejor respuesta

Aquí hay una forma de binarizar la imagen con la cadena de Markov:

Suponiendo (según la propiedad de Markov) que el valor de un píxel depende solo de sus vecinos (supongamos un 4-nbd), estimamos la probabilidad de que un píxel sea blanco dado que n de sus nbd píxeles son blancos, es decir, para 4-nbd, Primero calculemos las probabilidades condicionales de que P (x (i, j) = 1 | n de sus nbrs también son 1), donde n = 0,1,2,3,4 para 4-nbd (también, usemos un global umbral para calcular las probabilidades como se muestra en el siguiente código, esto se puede considerar como la fase de entrenamiento):

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]

Ahora usemos estas probabilidades estimadas para cambiar cada uno de los píxeles en la imagen coloreada a blanco y negro, dependiendo de su nbd (esto se puede considerar como una fase de prueba):

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()

La imagen binaria obtenida tiene una calidad mucho mejor que el umbral global (compruébalo).

enter image description here

Puede elegir píxeles al azar y calcular la probabilidad de que un valor de píxel sea 1 dado el número de 1 nbrs (umbral), estableciendo en consecuencia el valor de píxel, utilizando el siguiente código con una gran cantidad de iteraciones N, dará como resultado una imagen binaria similar .

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()

enter image description here

La siguiente animación muestra cómo se genera la imagen binaria utilizando el código anterior.

enter image description here

1
Sandipan Dey 10 mar. 2021 a las 16:13