2010-12-10 26 views
1

Si j'ai une image avec, disons des carrés. Est-il possible de supprimer toutes les formes formées par 10 pixels (non blancs) ou moins et conserver toutes les formes qui sont formées de 11 pixels ou plus? Je veux le faire par programme ou avec une ligne de commande.Supprimer des formes de l'image avec X nombre de pixels ou moins

Merci d'avance!

Répondre

2

Il y a plusieurs façons d'aborder cela. Ce que vous faites référence est communément appelé "Despeckle in Document Imaging Applications". Les scanners de documents introduisent souvent beaucoup de saleté et de bruit dans une image pendant la numérisation et doivent donc être retirés pour améliorer la précision de l'OCR.

Je suppose que vous traitez des images N/B ici ou que vous pouvez convertir votre image en N/B, sinon cela devient beaucoup plus complexe. Le nettoyage se fait en analysant tous les blobs sur la page. Une autre façon de décider de la taille des blobs est de décider de la largeur, de la hauteur et du nombre de pixels combinés. Leptonica.com - Est une bibliothèque basée sur C Open Source qui a les fonctions d'analyse de blob dont vous avez besoin. Avec quelques vérifications et boucles simples, vous pouvez supprimer ces objets plus petits. Leptonica peut également être compilé assez facilement dans un programme en ligne de commande. Il existe de nombreux exemples de programmes et c'est la meilleure façon d'apprendre Leptionica.

Pour tester, vous pouvez essayer ImageMagick. Il a une option de ligne de commande pour le despeckle mais il n'a aucun autre paramètre. http://www.imagemagick.org/script/command-line-options.php#despeckle

L'autre option consiste à rechercher des algorithmes de "dépouillement" dans Google.

3

Recherchez les algorithmes de remplissage d'inondation et modifiez-les pour compter les pixels au lieu de les remplir. Ensuite, si la forme est assez petite, remplissez-la de blanc.

0

Vous souhaitez un algorithme d'étiquetage des composants connectés. Il balaie l'image et attribue un numéro d'identification à chaque forme connectée, et assigne à chaque pixel un numéro d'identification de la forme à laquelle elle appartient. Après avoir exécuté un filtre de composants connectés, comptez simplement les pixels affectés à chaque objet, trouvez les objets ayant moins de 10 pixels et remplacez les pixels de ces objets par du blanc.

3

Il est possible qu'un algorithme appelé Erosion soit utile. Il fonctionne sur les images booléennes, en réduisant toutes les zones de "vrai" en supprimant une couche de leurs pixels de surface. Appliquer plusieurs fois, et les petites zones disparaissent, les plus grandes restent (bien que rétrécies). Diminuer les survivants avec l'algorithme opposé, dilatation (appliquer l'érosion au complément logique de l'image). Trouvez un moyen de définir des images booléennes en testant si un pixel est à l'intérieur d'un "objet" mais vous le définissez, et trouvez un moyen d'appliquer les résultats à l'image originale pour changer les petits objets indésirables en couleur d'arrière-plan.

Pour être plus précis, il faudrait voir des exemples.

+0

Le cycle d'érosion -> dilatation est-il sans perte? –

0

Vous voulez juste déterminer la surface de chaque composant. Un algorithme de suivi à 8 directions pourrait donc aider. J'ai une API pour résoudre ce problème codé en C++. Si vous voulez, envoyez-moi un email.

1

Si vous pouvez utiliser openCV, ce morceau de code fait ce que vous voulez (c'est-à-dire, désépauler). Vous pouvez jouer w/paramètres de taille (3,3) dans la première ligne pour se débarrasser des artefacts bruyants plus gros ou plus petits.

Mat element = getStructuringElement(MORPH_ELLIPSE, Size(3,3)); 
morphologyEx(image, image, MORPH_OPEN, element); 
morphologyEx(image, image, MORPH_CLOSE, element); 
0

ImageMagick, à partir de la version 6.8.9-10, inclut une option -connected-components qui peut être utilisée pour faire ce que vous voulez, cependant à partir du example fourni dans le site officiel, il n'est pas immédiatement évident comment obtenir réellement l'image originale moins les composants connectés enlevés.

Je suis presque sûr qu'il ya un ce chemin, mais plus simple j'ai fait via un script clunky effectuant une série d'étapes:

  • D'abord, je courais la commande de l'exemple des composants connectés:

    convert in.png \ 
        -define connected-components:verbose=true \ 
        -connected-components 8 out.png 
    
  • Ce produit sortie dans le format suivant:

    Objects (id: bounding-box centroid area mean-color): 
    (...) 
    181: 9x9+1601+916 1605.2,920.2 44 gray(0) 
    185: 5x5+1266+923 1268.0,925.0 13 gray(0) 
    274: 5x5+2276+1661 2278.0,1663.0 13 gray(255) 
    
  • Ensuite, j'ai utilisé awk pour filtrer uniquement les lignes contenant une zone (en pixels) de composantes noires (couleur moyenne gray(0) dans mon image) plus petite que mon seuil $ min_cc_area. Notez que connected-components a une option pour filtrer les composants plus petits qu'une zone donnée, mais j'avais besoin de l'opposé. La ligne awk est similaire à ce qui suit:

    {if ($4 < $min_cc_area && $5=="gray(0)") { print $2 }} 
    
  • J'ai alors de créer une ligne de commande pour ImageMagick où je dessinais des rectangles blancs sur le dessus de ces composants connectés. La commande -draw attend les coordonnées sous la forme x1,y1 x2,y2, donc j'utiliser awk à nouveau pour calculer les coordonnées de celles dans le format [w]x[h]+x1+y1 donné par -connected-components:

    awk '{print "white fill rectangle " $3 "," $4 " " $3+$1-1 "," $4+$2-1 }' 
    
  • Enfin, j'ai couru la ligne de commande ImageMagick créée pour créer une nouvelle image combinant tous les rectangles blancs au-dessus de l'original.

En fin de compte, je me suis le script suivant:

# usage: $0 infile min_cc_area outfile 
infile=$1 
min_cc_area=$2 
outfile=$3 
awk_exp="{if (\$4 < $min_cc_area && \$5==\"gray(0)\") { print \$2 }}" 

draw_rects="" 
draw_rects+=$(convert $infile -define connected-components:verbose=true \ 
    -connected-components 8 null: | \ 
    awk "$awk_exp" | tr 'x+' ' ' | \ 
    awk '{print " rectangle " $3 "," $4 " " $3+$1-1 "," $4+$2-1 }') 

convert $infile -draw "fill white $draw_rects" $outfile 

Notez que cette solution peut effacer des pixels noirs près de la CC enlevé, si elles insersect le rectangle de délimitation de l'élément retiré.