Dans le cadre de notre projet de conception finale, nous devons concevoir un échantillonneur de Gibbs pour dénouer une image. Nous avons choisi d'utiliser l'algorithme de Metropolis au lieu d'un échantillonneur Gibbs régulier. Une esquisse de l'algorithme est la suivante: tous les pixels ont des valeurs de niveaux de gris comprises entre 0 et 255. En outre, nous utilisons une distribution a priori simple et lisse.L'échantillonnage de Gibbs donne de petites probabilités
main()
get input image as img
originalImg = img
for k = 1 to 1000
beta = 3/log(1+k)
initialEnergy = energy(img,originalImg)
for i = 0 to imageRows
for j = 0 to imageCols
img[i][j] = metropolisSample(beta,originalImg,img,initialEnergy,i,j)
energy(img,originalImg)
for i = 1 to imageRows
for j = 1 to imageCols
ans += (img[i][j] - originalImg[i][j])^2/(255*255)
ans += (img[i][j] - image[i][j+1])^2/(255*255)
ans += (img[i][j] - image[i][j-1])^2/(255*255)
ans += (img[i][j] - image[i+1][j])^2/(255*255)
ans += (img[i][j] - image[i-1][j])^2/(255*255)
return ans
metropolisSample(beta,originalImg,img,initialEnergy,i,j)
imageCopy = img
imageCopy[i][j] = random int between 0 and 255
newEnergy = energy(imageCopy,originalImg)
if (newEnergy < initialEnergy)
initialEnergy = newEnergy
return imageCopy[i][j]
else
rand = random float between 0 and 1
prob = exp(-(1/beta) * (newEnergy - initialEnergy))
if rand < prob
initialEnergy = newEnergy
return imageCopy[i][j]
else
return img[i][j]
Voilà à peu près l'essentiel du programme. Mon problème est que, dans l'étape où je calcule la probabilité
prob = exp(-(1/beta) * (newEnergy - initialEnergy))
La différence dans les énergies est si grande que la probabilité est presque toujours zéro. Quelle est la bonne façon d'atténuer cela? Nous avons également essayé l'approche d'échantillonnage de Gibbs, mais nous rencontrons un problème similaire. Le code de l'échantillonneur Gibbs est le suivant. Au lieu d'utiliser metropolisSample, nous utilisons gibbsSample à la place
gibbsSample(beta,originalImg,img,initialEnergy,i,j)
imageCopy = img
sum = 0
for k = 0 to 255
imageCopy[i][j] = k
energies[k] = energy(imageCopy,originalImg)
prob[k] = exp(-(1/beta) * energies[k])
sum += prob[k]
for k = 0 to 255
prob[k]/sum
for k = 1 to 255
prob[k] = prob[k-1] + prob[k] //Convert our PDF to a CDF
rand = random float between 0 and 1
k = 0
while (1)
if (rand < prob[k])
break
k++
initialEnergy = energy[k]
return k
Nous avions des problèmes similaires avec cette mise en œuvre ainsi. Lorsque nous avons calculé
prob[k] = exp(-(1/beta) * energies[k])
nos énergies étaient si grandes que nos probabilités sont toutes passées à zéro. Théoriquement, cela ne devrait pas poser de problème parce que nous les additionnons tous, puis nous divisons par la somme, mais la représentation en virgule flottante n'est tout simplement pas assez précise. Quel serait un bon moyen de résoudre ce problème?