web-dev-qa-db-fra.com

Comment reconnaître des rectangles dans cette image?

J'ai une image avec des lignes horizontales et verticales. En fait, cette image est le site Web de la BBC converti en lignes horizontales et verticales. Mon problème est que je veux pouvoir trouver tous les rectangles dans l'image. Je veux écrire un programme informatique pour trouver tous les rectangles. Quelqu'un sait-il comment faire cela ou suggère-t-il des idées pour commencer? Cette tâche est facile pour moi en tant que personne de trouver les rectangles visuels, mais je ne sais pas comment le décrire comme un programme.

L'image est le site Web de la BBC ici http://www.bbc.co.uk/


Mise à jour, j'ai écrit le code qui convertit l'image du site Web de la BBC en ligne horizontale et verticale, le problème est que ces lignes ne se rencontrent pas complètement dans les coins et parfois elles ne forment pas complètement un rectangle. Merci!

31
Phil

Opencv (traitement d'images et bibliothèque de vision par ordinateur écrits en c) a une implémentation pour la transformation de Hough (la simple transformation de Hough trouve des lignes dans une image, tandis que la généralisée trouve des objets plus complexes), ce qui pourrait être un bon début. Pour les rectangles qui ont des coins fermés, il existe également des détecteurs de coins tels que cornerHarris qui peuvent vous aider.

J'ai exécuté la démo houghlines fournie avec opencv et voici le résultat sur l'image que vous avez donnée (lignes détectées marquées en rouge): alt text
(source: splintec.com )

22
elijah

Je crois que vous recherchez la transformation de Hough généralisée .

9
rlbond

En vision par ordinateur, il existe un algorithme appelé Generalized Hough Transform qui peut peut-être résoudre votre problème. Il devrait y avoir du code open source ayant implémenté cet algorithme. Recherchez-le.

4
ppan

En supposant que c'est une image raisonnablement exempte de bruit (pas une vidéo d'un écran), alors l'un des algorithmes de remplissage simple devrait fonctionner. Vous devrez peut-être exécuter une dilatation/érosion sur l'image pour combler les lacunes.

La manière normale de trouver des lignes est une transformation de Hough (puis de trouver des lignes à angle droit). L'opencv est la manière la plus simple.

Jetez un oeil à cette question Détection d'objets OpenCV - Point central

3
Martin Beckett

Il existe plusieurs approches différentes à votre problème. J'utiliserais un traitement d'image morphologique comme celui-ci . Vous aurez la possibilité de définir "rectangle" même quelque chose qui n'est pas "exactement fermé" (où l'algorithme de remplissage échouera).

Une autre possibilité pourrait être d'utiliser une approche machine learning , qui est fondamentalement plus axée sur les données que sur la définition comme la précédente. Vous devrez donner à votre algorithme plusieurs "exemples" de ce qu'est un rectangle, et il finira par apprendre (avec un biais et un taux d'erreur).

2
Davide

Pour passer de l'image que vous avez avec les lignes horizontales et verticales presque touchantes aux seuls rectangles:

  1. Convertir en binaire (c'est-à-dire que toutes les lignes sont blanches, le reste est noir)
  2. Effectuer une dilatation binaire (ici, vous faites chaque pixel qui touche un pixel blanc dans l'image source ou est un pixel blanc dans l'image source blanc. Le toucher est droit uniquement (donc chaque pixel "touche" les pixels à sa gauche, à droite, au-dessus et en dessous), cela s'appelle "4-connectés"
  3. répétez l'étape 3 plusieurs fois si les écarts entre les extrémités sont plus grands que 2 pixels de large, mais pas trop souvent!
  4. Effectuez une opération squelette (ici, vous rendez chaque pixel de l'image de sortie noir s'il s'agit d'un pixel blanc de l'image source qui touche au moins un pixel noir et les pixels blancs qu'il touche (dans l'image source) se touchent tous. défini avec connectivité 4. Voir l'exemple ci-dessous.
  5. Répétez l'étape 4 jusqu'à ce que l'image ne change pas après une répétition (tous les pixels blancs sont des extrémités de ligne ou des connecteurs)

Avec un peu de chance, cela montrera d'abord les boîtes avec des lignes de graisse épaisses, laissant des artefacts de graisse épaisse sur toute l'image (après l'étape 3), puis après l'étape 5, tous les artefacts de graisse épaisse auront été supprimés, tandis que toutes les boîtes resteront . Vous devez modifier le nombre de répétitions à l'étape 3 pour de meilleurs résultats. Si vous êtes intéressé par la morphologie de l'image, c'est le livre d'un très bon cours d'introduction que j'ai suivi.

Échantillon: (0 = noir, 1 = blanc, les pixels au centre de chaque bloc 3x3 sont pris en compte, entrée gauche, sortie droite)

011 => 011    
011 => 001  all other white pixels touch, so eliminate      
011 => 011    

010 => 010    
010 => 010  top pixel would become disconnected, so leave      
010 => 010    

010 => 010    
010 => 000  touches only one white pixel, so remove     
000 => 000    

010 => 010    
111 => 111  does not touch black pixels, leave    
010 => 010    

010 => 010    
011 => 011  other pixels do not touch. so leave    
000 => 000    
1
jilles de wit

itérer de gauche à droite jusqu'à ce que vous atteigniez un pixel de couleur, puis utilisez un algorithme de remplissage inondé modifié. plus d'informations sur l'algo fill flood @ wiki

1
data

une autre approche serait de trouver N'IMPORTE QUEL pixel coloré sur l'image puis aller avec

while(pixel under current is colored)
{
  lowest pixel coordinate = pixel under current
  current = pixel under
}

puis faites de même vers le haut. maintenant vous avez défini une seule ligne. puis utilisez les extrémités des lignes pour faire correspondre approximativement les lignes en rectangles. s'ils ne sont pas parfaits en pixels, vous pouvez faire une sorte de seuil.

1
data

Le remplissage d'inondation fonctionnerait, ou vous pourriez utiliser une modification d'un algorithme de suivi d'Edge.

ce que vous faites est de créer un tableau 2d (ou toute autre structure de données d2) - chaque ligne représente une ligne horizontale de pixels à l'écran et chaque colonne une ligne verticale

parcourir tous les pixels, de gauche à droite, et chaque fois que vous en trouvez un de couleur, ajoutez ses coordonnées au tableau

parcourir le tableau et les lignes de recherche et stocker le pixel de début et de fin pour chacun (structure de données différente)

sachant que le début de chaque ligne est son pixel gauche/haut, vous pouvez facilement vérifier si 4 lignes constituent un rectangle

1
Zepee