2010-02-12 18 views
3

Je me suis cogné la tête pendant longtemps sur celui-ciChaînes de pixels à partir du codage de longueur de séquence

Je fais de l'imagerie. Jusqu'à présent, j'ai binarisé mes images, ce qui signifie que d'une image en niveaux de gris, chaque pixel sous une certaine valeur sont supprimés. Cela me donne seulement quelques régions hors de l'image originale avec beaucoup de "pixels zéro" tout autour de ces régions.

Ensuite, j'ai longuement codé mes régions en "blobs". Les exécutions sont une méthode de compression pour les données. Par exemple, supposons que vous ayez binarisé un carré, vous n'aurez que quelques passages décrivant l'image entière. Les exécutions sont définies par les coordonnées x, y et une longueur. Lors de la recréation de l'image, pour chaque exécution, accédez à la coordonnée x, y et ajoutez des pixels sur l'axe x pour la durée de l'analyse.

Maintenant, je dois prendre les pistes et créer une chaîne qui décrira le contour de la région. Je ne sais pas comment faire ça.

J'ai un tas de x, y, longueurs et je dois "naviguer" sur les bords pour former un chain. Normalement, en imagerie ce processus est fait avec l'image originale mais je ne peux plus utiliser l'image originale ici, donc je dois la calculer avec les images. Je sais que cela ressemble à un grand mur de texte, mais je ne sais pas comment poser cette question mieux. Toute indication ou pointeur sur une implémentation identique serait génial.

EDIT

grâce à se détendre, lien Ill quelques images:

alt text http://www.ph.tn.tudelft.nl/Courses/FIP/images/fip83.gif

Dans cet exemple, ils traitent l'image B dans le contour C (que j'appelle la chaîne). Cependant, je voudrais générer le contour à partir de D, les longueurs de course

+0

Voici un exemple typique où une image indique plus de 1K mots. Votre description est correcte, mais elle serait au moins deux fois plus accessible si vous deviez fournir quelques images. En particulier, le concept de «chaîne» est difficile à comprendre, et un rapide Google n'a rien révélé d'évident. – unwind

+0

(Mise à jour): J'ai pris la liberté de lier le mot «chaîne» à ce que je * pense * est une page appropriée. N'hésitez pas à modifier, ou (mieux!) Insérer des images en ligne dans la question, bien sûr. – unwind

+0

Merci beaucoup. Dans cet exemple, cependant, ils génèrent les chaînes à partir de l'image originale (B), je voudrais le générer à partir des exécutions (D). Mais c'est exactement de cela que je parle. – Eric

Répondre

0

Eh bien, je perdu ce contrat, mais la réponse était d'utiliser le Freeman Chain Coding technique

Le fait qu'il est géré de codage des longueurs n'a rien à voir avec l'algorithme, à la différence que je pensais que précédemment.

0

À première vue, je ne vois pas d'algorithme pratique pour cela. La solution d'un homme pauvre serait développez l'image originale de la longueur codée. Donc, si vos lignes ressemblent à ceci:

A 3B 10A C 8D 
C 4D 3A 6C 9A 

où les personnages renvoient la valeur réelle des pixels (par exemple A = 0, B = 127, ...). Vous pouvez écrire les valeurs de pixels dans un tableau à deux dimensions (ou une autre structure de données de votre choix) .Il ressemble à ceci:

ABBBAAAAAAAAAACDDDDDDDD 
CDDDDAAACCCCCCAAAAAAAAA 

Après votre chaîne générer, supprimer le tableau et conserver les informations de la chaîne. Bien sûr, cela est cher, donc peut-être vous pourriez le faire avant d'encoder la longueur de l'image originale.

0

est ici une solution parfaitement simple et pratique (C++):

#include <iostream> 
#include <vector> 

struct Run { int x, w; }; 
enum { EAST, NORTHEAST, NORTH, NORTHWEST, WEST, SOUTHWEST, SOUTH, SOUTHEAST }; 

int main() { 

    const Run data[] = { 
     { 7, 2 }, 
     { 5, 6 }, 
     { 5, 7 }, 
     { 5, 7 }, 
     { 6, 6 }, 
     { 0, 12 }, 
     { 0, 12 }, 
     { 0, 11 }, 
     { 1, 7 }, 
     { 3, 4 }, 
     { 3, 4 }, 
     { 3, 5 }, 
     { 3, 7 }, 
     { 3, 7 }, 
     { 5, 5 } 
    }; 

    std::vector<Run> runs(data, data + 15); 
    std::vector<int> before; 
    std::vector<int> after; 
    unsigned int i; 
    int j; 

    for (i = 0; i < runs.size() - 1; ++i) { 

     if (runs[i].x < runs[i + 1].x) { 

      for (j = 0; j < runs[i + 1].x - runs[i].x - 1; ++j) 
       before.push_back(WEST); 
      before.push_back(NORTHWEST); 

     } else if (runs[i].x > runs[i + 1].x) { 

      before.push_back(NORTHEAST); 
      for (j = 0; j < runs[i].x - runs[i + 1].x - 1; ++j) 
       before.push_back(EAST); 

     } else { 

      before.push_back(NORTH); 

     } 

     int first_right(runs[i].x + runs[i].w); 
     int second_right(runs[i + 1].x + runs[i + 1].w); 

     if (first_right < second_right) { 

      after.push_back(SOUTHEAST); 
      for (j = 0; j < second_right - first_right - 1; ++j) 
       after.push_back(EAST); 

     } else if (first_right > second_right) { 

      for (j = 0; j < first_right - second_right - 1; ++j) 
       after.push_back(WEST); 
      after.push_back(SOUTHWEST); 

     } else { 

      after.push_back(SOUTH); 

     } 

    } 

    for (j = 0; j < runs.back().w - 1; ++j) 
     after.push_back(WEST); 

    std::reverse(before.begin(), before.end()); 
    after.insert(after.end(), before.begin(), before.end()); 

    for (j = 0; j < int(after.size()); ++j) { 
     switch (after[j]) { 
     case EAST:  std::cout << "EAST\n";  break; 
     case NORTHEAST: std::cout << "NORTHEAST\n"; break; 
     case NORTH:  std::cout << "NORTH\n";  break; 
     case NORTHWEST: std::cout << "NORTHWEST\n"; break; 
     case WEST:  std::cout << "WEST\n";  break; 
     case SOUTHWEST: std::cout << "SOUTHWEST\n"; break; 
     case SOUTH:  std::cout << "SOUTH\n";  break; 
     case SOUTHEAST: std::cout << "SOUTHEAST\n"; break; 
     } 
    } 

} 

Cela fonctionne par itérer sur les pistes, à tester les extrémités gauche et droite pour la direction qu'ils sauter, et en ajoutant le nombre approprié des éléments de la chaîne à deux vecteurs: un en avant, pour le côté droit, et un dans l'ordre inverse, pour la gauche. Il relie ensuite les deux chaînes en ajoutant le nombre approprié de liens pour la dernière ligne de balayage, puis inverse la chaîne latérale gauche et l'ajoute à la droite pour produire la chaîne finale.

J'espère que c'est ce que vous cherchez!

+0

Je ne suis pas sûr de comprendre ce que contient votre structure Run, est-ce que c'est la coordonnée x et la longueur? Je ne comprends pas comment relier cela à la coordonnée y – Eric

+0

Aussi, je ne suis pas sûr que ça va marcher puisque si vous obtenez une forme en U, vous devrez retourner dans votre tableau de données d'une manière ou d'une autre – Eric

+0

Oui, c'est un x et une longueur. La coordonnée y n'a pas d'importance tant que les lignes de balayage sont contiguës; supposons que runs [0] contient le run avec la valeur y la plus basse, et ainsi de suite. Et non, cela ne fonctionne pas s'il y a plusieurs passages avec la même valeur y; vous pouvez facilement résoudre ceci en divisant la forme en deux séries de courses, en trouvant les chaînes et en les rejoignant après. –