2015-09-14 2 views
0

Je travaille sur un projet qui nécessite la détection de lignes sur une plaque de sable. Les lignes sont dessinées à la main par l'utilisateur afin qu'elles ne soient pas exactement "droites" (voir photo). Et à cause du sable, les lignes sont assez difficiles à distinguer. J'ai essayé cv2.HoughLines à partir d'OpenCV, mais je n'ai pas obtenu de bons résultats. Donc, toute suggestion sur la méthode de détection? Et bienvenue pour suggestion d'améliorer la clarté des lignes. Je pense à mettre un peu de lumière led autour de la plaque.Suggestion pour détecter des lignes droites sur une plaque de sable, python

Merci

Répondre

4

Le procédé de détection dépend beaucoup de combien généralité vous avez besoin: est l'exposition et le contraste va passer d'une image à une autre? La largeur typique des lignes va-t-elle changer? Dans la suite, je suppose que ces paramètres ne varient pas beaucoup pour vos applications, corrigez-moi si je me trompe.

Je vais utiliser scikit-image, un logiciel commun de traitement d'image pour Python. Si vous n'êtes pas familier avec ce paquet, la documentation peut être trouvée sur http://scikit-image.org/, et le paquet est livré avec toutes les installations de Scientific Python. Cependant, les algorithmes que j'utilise sont également disponibles dans d'autres outils, comme opencv.

Ma solution est écrite ci-dessous. Fondamentalement, le principe est

  • d'abord, dénouer l'image. La vie est généralement plus simple après une étape de débruitage. Ici, j'utilise un filtre de variation totale, car il en résulte une image par morceaux constante qui sera plus facile à franchir. J'améliore les régions sombres en utilisant une érosion morphologique (sur l'image en niveaux de gris).

  • puis d'appliquer un seuil adaptatif qui varie localement dans l'espace, car le contraste varie à travers l'image. Cette opération entraîne une image binaire.

  • érode l'image binaire pour briser les liens parasites entre les régions et ne conserve que les grandes régions.

  • calculer une mesure de l'allongement des régions pour ne garder que les plus allongés. Ici j'utilise le rapport des valeurs propres du tenseur d'inertie.

Les paramètres les plus difficiles à régler sont la taille de bloc pour le seuillage adaptatif et la taille minimale des zones à conserver. J'ai également essayé un filtre Canny sur l'image débruitées (skimage.filters.canny), et les résultats étaient assez bons, mais les bords n'étaient pas toujours fermés, vous pouvez aussi essayer une méthode de détection de bord telle qu'un filtre Canny.

Le résultat est présenté ci-dessous: result image

# Import modules 
import numpy as np 
from skimage import io, measure, morphology, restoration, filters 
from skimage import img_as_float 
import matplotlib.pyplot as plt 

# Open the image 
im = io.imread('sand_lines.png') 
im = img_as_float(im) 

# Denoising 
tv = restoration.denoise_tv_chambolle(im, weight=0.4) 
ero = morphology.erosion(tv, morphology.disk(5)) 

# Threshold the image 
binary = filters.threshold_adaptive(ero, 181) 

# Clean the binary image 
binary = morphology.binary_dilation(binary, morphology.disk(8)) 
clean = morphology.remove_small_objects(np.logical_not(binary), 4000) 
labels = measure.label(clean, background=0) + 1 

# Keep only elongated regions 
props = measure.regionprops(labels) 
eigvals = np.array([prop.inertia_tensor_eigvals for prop in props]) 
eigvals_ratio = eigvals[:, 1]/eigvals[:, 0] 
eigvals_ratio = np.concatenate(([0], eigvals_ratio)) 
color_regions = eigvals_ratio[labels] 

# Plot the result 
plt.figure() 
plt.imshow(color_regions, cmap='spectral')