Détection de segments dans une image

C’est une technique assez vieille et qui consiste à détecter des segments comme des anomalies : l’alignement de points est un événement assez rare dans un nuage de points mais rare comment ? Cette idée mène à la probabilisation d’une image pour quantifier ce qu’est un alignement de points nécessairement rare.

Une image aléatoire

On considère un bruit aléatoire uniforme dans une image et on ajoute des points aléatoires tirés le long d’une ligne selon une loi gaussienne : uniforme sur la ligne, gaussien autour du segment.

[17]:
from mlstatpy.image.detection_segment import random_noise_image, convert_array2PIL

img = random_noise_image((100, 100))
convert_array2PIL(img, mode="binary")
[17]:
../../_images/notebooks_image_segment_detection_2_0.png
[18]:
from mlstatpy.image.detection_segment import random_segment_image

random_segment_image(img, density=3.0, lmin=0.3)
[18]:
{'size': 43,
 'angle': 0.45754951975081887,
 'x1': 8,
 'y1': 43,
 'x2': 46.576920763478554,
 'y2': 61.995293743669706,
 'nbpoints': 129}
[19]:
convert_array2PIL(img, mode="binary")
[19]:
../../_images/notebooks_image_segment_detection_4_0.png
[20]:
random_segment_image(img, density=5.0, lmin=0.3)
random_segment_image(img, density=5.0, lmin=0.3)
convert_array2PIL(img, mode="binary")
[20]:
../../_images/notebooks_image_segment_detection_5_0.png
[21]:
pilimg = convert_array2PIL(img, mode="binary").convert("RGB")
pilimg
[21]:
../../_images/notebooks_image_segment_detection_6_0.png
[22]:
from PIL import ImageFilter


pilimg = (
    pilimg.filter(ImageFilter.BLUR)
    .filter(ImageFilter.BLUR)
    .filter(ImageFilter.BLUR)
    .filter(ImageFilter.BLUR)
)
pilimg
[22]:
../../_images/notebooks_image_segment_detection_7_0.png
[23]:
from PIL import ImageEnhance

enh = ImageEnhance.Sharpness(pilimg)
final_img = enh.enhance(4)
final_img
[23]:
../../_images/notebooks_image_segment_detection_8_0.png

Gradient

La détection des segments est basée sur le gradient.

[24]:
from mlstatpy.image.detection_segment import compute_gradient, plot_gradient

grad = compute_gradient(final_img, color=0)
[25]:
plot_gradient(pilimg.copy(), grad, direction=-2)
[25]:
../../_images/notebooks_image_segment_detection_11_0.png

Détection de segments

[26]:
from mlstatpy.image.detection_segment import detect_segments

seg = detect_segments(final_img, verbose=1, seuil_nfa=1e-1)
len(seg)
n =  1000  ...  81  temps  0.21  sec nalign 277
n =  2000  ...  152  temps  0.34  sec nalign 640
n =  3000  ...  180  temps  0.49  sec nalign 917
n =  4000  ...  290  temps  0.62  sec nalign 1312
n =  5000  ...  315  temps  0.81  sec nalign 1535
n =  6000  ...  330  temps  0.98  sec nalign 1859
n =  7000  ...  426  temps  1.14  sec nalign 2093
n =  8000  ...  457  temps  1.29  sec nalign 2425
n =  9000  ...  604  temps  1.53  sec nalign 2756
[26]:
605
[27]:
from mlstatpy.image.detection_segment import plot_segments

plot_segments(final_img.copy(), seg)
[27]:
../../_images/notebooks_image_segment_detection_14_0.png

Détection de segments sur une image

[28]:
from PIL import Image

egl = Image.open("eglise_zoom2.jpg")
egl
[28]:
../../_images/notebooks_image_segment_detection_16_0.png

On réduit la taille de l’image.

[29]:
egl2 = egl.crop((0, 0, egl.size[0] // 3, 3 * egl.size[1] // 4))
egl2
[29]:
../../_images/notebooks_image_segment_detection_18_0.png
[30]:
grad2 = compute_gradient(egl2, color=0)
plot_gradient(egl2.copy(), grad2, direction=-2)
[30]:
../../_images/notebooks_image_segment_detection_19_0.png
[31]:
seg2 = detect_segments(egl2)
len(seg2)
[31]:
490
[32]:
from mlstatpy.image.detection_segment import plot_segments

res = plot_segments(egl2.copy(), seg2)
res
[32]:
../../_images/notebooks_image_segment_detection_21_0.png

Il faudrait fusionner les segments mais cela a l’air de marcher.


Notebook on github