Comment reconnaître des rectangles dans cette image?
-
08-07-2019 - |
Question
J'ai une image avec des lignes horizontales et verticales. En fait, cette image représente 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. Est-ce que quelqu'un sait comment faire cela ou suggère des idées sur la façon de commencer? Il est facile pour moi, en tant que personne, de trouver les rectangles visuels, mais je ne sais pas comment le décrire en tant que 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 lignes horizontales et verticales. Le problème est que ces lignes ne se rencontrent pas complètement aux angles et qu’elles ne forment parfois pas complètement un rectangle. Merci!
La solution
Opencv (la bibliothèque de traitement d'images et de vision par ordinateur écrite en c) est implémentée pour hough transform ( la transformation hough simple 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 coin tels que cornerHarris qui peuvent aider.
J'ai lancé la démonstration houghlines fournie avec opencv et voici le résultat sur l'image que vous avez donnée (lignes détectées en rouge):
(source: splintec.com )
Autres conseils
Je pense que vous recherchez la transformation de Hough généralisée .
Dans le domaine de la vision par ordinateur, il existe un algorithme appelé Hough Transform généralisé qui peut peut-être résoudre votre problème. . Il devrait y avoir du code source ouvert ayant implémenté cet algorithme. Il suffit de chercher.
En supposant qu’il s’agisse d’une image raisonnablement exempte de bruit (et non d’une vidéo sur un écran), l’un des algorithmes simples de fond d’écran devrait fonctionner. Vous devrez peut-être exécuter un dilatage / érosion sur l'image pour combler les espaces vides.
La méthode normale pour trouver des lignes est une transformation de Hough (puis rechercher des lignes à angle droit) L'openv est le moyen le plus simple.
Regardez cette question Détection d'objet OpenCV - Point central
Il existe plusieurs approches différentes à votre problème. J'utiliserais un traitement d'images morphologiques comme celui-ci . Vous aurez la possibilité de définir le " 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 d'apprentissage automatique , qui est fondamentalement plus basée sur les données. entraîné que par définition comme le précédent. 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) .
itérez de gauche à droite jusqu'à atteindre un pixel de couleur, puis utilisez l'algorithme de remplissage par inondation modifié. plus d'informations sur le remplissage du wiki @ wiki
une autre approche serait de rechercher N'IMPORTE QUEL pixel coloré sur l'image, puis d'aller avec
while(pixel under current is colored)
{
lowest pixel coordinate = pixel under current
current = pixel under
}
alors faites la même chose vers le haut. maintenant vous avez défini une seule ligne. utilisez ensuite les extrémités des lignes pour faire correspondre approximativement les lignes à des rectangles. s’ils ne sont pas parfaits en pixels, vous pouvez effectuer une sorte de seuillage.
L'inondation fonctionnerait ou vous pourriez utiliser une modification d'un algorithme de suivi des contours.
Ce que vous faites est: créer un tableau 2D (ou toute autre structure de données d2) - chaque ligne représente une ligne de pixel horizontale à l'écran, et chaque colonne une ligne verticale
parcourez 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, rechercher des lignes et stocker les pixels de début et de fin pour chacune (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 comportent un rectangle
Pour obtenir de l'image que vous avez avec les lignes horizontales et verticales presque jointives aux rectangles uniquement:
- Convertir en binaire (c'est-à-dire toutes les lignes sont blancs, le reste est noir)
- Effectuez une dilatation binaire (ici vous créez chaque pixel qui touche pixel blanc dans l'image source ou est un pixel blanc dans l'image source blanc.Le toucher est uniquement droit (chaque pixel "touche" ainsi les pixels à gauche, à droite, au-dessus et au-dessous), on l'appelle "connecté en 4". ;
- répétez l'étape 3 plusieurs fois si les espaces entre les extrémités sont plus larges que 2 pixels de large, mais pas trop souvent!
- Effectuez une opération squelette (ici, vous faites en sorte que chaque pixel de l'image de sortie soit noir s'il s'agit d'un pixel blanc de l'image source qui touche au moins un pixel noir et que les pixels blancs qu'elle touche (dans l'image source) se touchent tous mutuellement. Encore une fois, toucher défini avec une connexion 4. Voir l'exemple ci-dessous.
- 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 fins de ligne ou des connecteurs)
Ceci affichera, avec un peu de chance, d’abord les cases avec des lignes épaisses, laissant des artefacts épais sur toute l’image (après l’étape 3), puis après l’étape 5, tous les artefacts épais auront été supprimés. toutes les cases restent. Vous devez modifier le nombre de répétitions à l'étape 3 pour obtenir de meilleurs résultats. Si vous êtes intéressé par la morphologie des images, c'est le livre de un très bon cours d'initiation que j'ai suivi.
Exemple: (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