Détection de crête dans un tableau 2D
Je suis à aider la clinique vétérinaire de mesure de la pression en vertu de l'un des chiens de la patte. J'utilise Python pour mon analyse de données et maintenant je suis coincé en essayant de diviser les pattes dans les (anatomique) sous-régions.
J'ai fait un tableau 2D de chaque patte, qui se compose d'un maximum de valeurs pour chaque capteur qui a été chargé par la patte au fil du temps. Voici un exemple d'une patte, où j'ai utilisé Excel pour tracer les domaines que je veux "détecter". Ce sont 2 par 2 cases autour du capteur avec des maxima locaux de l', qui, ensemble, ont la plus grande somme.
J'ai donc essayé quelques tests et tout simplement décider de chercher le maximum de chaque colonne et de la ligne (ne peut pas regarder dans une seule direction à cause de la forme de la patte). Cela semble détecter l'emplacement de la séparer les orteils assez bien, mais il marque également les voisins de capteurs.
Alors quelle serait la meilleure façon de dire à Python qui de ces maximums sont ceux que je veux?
Remarque: La 2x2 places peuvent se chevauchent pas, car ils doivent être séparés les orteils!
Aussi j'ai pris 2x2 comme une commodité, pas plus avancé solution est la bienvenue, mais je suis simplement un homme mouvement scientifique, donc je ne suis ni un vrai programmeur ou un mathématicien, de sorte s'il vous plaît garder "simple".
Voici un version qui peut être chargé avec np.loadtxt
Résultats
J'ai donc essayé @jextee de la solution (voir les résultats ci-dessous). Comme vous pouvez le voir, il fonctionne très sur les pattes de devant, mais ça marche moins bien pour les pattes de derrière.
Plus précisément, il ne peut pas reconnaître le petit pic qui est le quatrième orteil. C'est évidemment inhérente au fait que la boucle regarde de haut en bas vers la valeur la plus basse, sans prendre en compte, lorsque cela est.
Serait ce que quelqu'un sait comment modifier @jextee de l'algorithme, de sorte qu'il pourrait être en mesure de trouver le 4ème orteil trop?
Puisque je n'ai pas traité d'autres essais encore, je ne peux pas fournir tous les autres échantillons. Mais les données que j'ai donné avant étaient les moyennes de chaque patte. Ce fichier est un tableau avec le maximum de données de 9 pattes dans l'ordre qu'ils entrent en contact avec la plaque.
Cette image montre comment ils sont spatialement répartis sur la plaque.
Mise à jour:
J'ai mis en place un blog pour toute personne intéressée et J'ai mis un SkyDrive avec toutes les mesures brutes. Donc de toute personne qui demande plus de données: plus de puissance pour vous!
Nouvelle mise à jour:
Ainsi, après l'aide que j'ai eu avec mes questions sur les patte de détection et patte de tri, j'ai finalement été en mesure de vérifier l'orteil de détection pour chaque patte! S'avère, elle ne fonctionne pas si bien dans quoi que ce soit mais les pattes de taille moyenne comme celle de mon propre exemple. Bien sûr, avec le recul, c'est de ma faute pour le choix de la 2x2 de façon arbitraire.
Voici un bel exemple de l'endroit où ça se passe mal: un clou qui est reconnue comme étant un orteil et le talon d'' est tellement large, il est reconnu deux fois!
La patte est trop grand, afin de prendre une taille 2x2 ne se chevauchent pas, les causes de certains pieds pour être détecté deux fois. À l'inverse, dans les petits chiens, il ne parvient pas à trouver un 5ème orteil, ce qui je pense est causé par la 2x2 zone trop grande.
Après essayez la solution actuelle sur toutes mes mesures je suis venu à la stupéfiante conclusion que, pour presque tous mes petits chiens, il n'a pas trouver un 5ème orteil et que dans plus de 50% de l'impact pour les chiens de grande taille, il trouverait plus!
Donc clairement, j'ai besoin de la changer. Ma part, je crois, était le changement de la taille de la neighborhood
à quelque chose de plus petit pour les petits chiens et les grands pour les grands chiens. Mais generate_binary_structure
ne me laisse pas changer la taille de la matrice.
Donc, je suis en espérant que quelqu'un d'autre a une meilleure suggestion pour localiser les orteils, peut-être d'avoir la zone des orteils à l'échelle avec la patte de la taille?
- - Je considérer que les virgules décimales plutôt que de la valeur des séparateurs?
- Oui, ils sont des virgules. Et @Christian, je suis en train de le coller dans un simple fichier texte lisible, mais même cela échoue sur moi 🙁
- Si quelqu'un a besoin de plus d'informations, j'ai ouvert un salon de discussion pour elle
- Je remarque juste que le bas de l'image en miroir, par rapport à l'exemple d'Excel. Stupide orientation!
- Quel est le but de cette analyse? Vous dites que vous voulez identifier anatomiques sous-régions. Est-il pour ramasser charge anormale distibution? Le positionnement relatif des plaquettes?
- Comme je suis en train de faire une étude de faisabilité, quelque chose se passe vraiment. Donc, je suis à la recherche aussi de nombreuses façons de définir la pression, y compris les sous-régions. J'ai aussi besoin de pouvoir discriminer entre les "gros orteil" et le " petit orteil côté, l'estimation de l'orientation. Mais depuis, il n'a pas été fait avant, il n'y a pas de raconter ce que l'on pourrait trouver 🙂
- Les photos sont tout simplement imshow()'s d'un tableau (à l'exception de la première, qui est à partir d'Excel). @Ron: pour l'instant, je n'ai pas traité d'autres mesures, mais cette mesure a en fait 9 plein de contacts. Je vais les télécharger dans un sec
- l'un des objectifs de cette étude est de voir de quelle taille/poids de chiens le système est adapté, donc oui, alors que ce chien a été d'environ 20 kg. J'ai certains qui sont considérablement plus petits (et les grands) et espérer que je ne serai pas en mesure de faire de même pour les vrais petits.
- Partielle en double: stackoverflow.com/questions/1713335/...
- Cool question. Pourquoi les données liées à un 3-D np tableau au lieu de 2-D?
- les pieds sont mesurés au fil du temps, donc de la 3ème dimension. Cependant, ils ne bougent pas de leur place (relativement parlant), donc je suis surtout intéressé où les orteils sont situés en 2D. L'aspect 3D est gratuit après que
- Pour moi, il n'est pas clair si le Nouvelle mise à jour est déjà abordés dans les réponses ci-dessous?!
Vous devez vous connecter pour publier un commentaire.
Que j'ai détecté les sommets à l'aide d'un maximum local de filtre. Voici le résultat sur votre premier jeu de données de 4 pattes:
J'ai aussi couru le deuxième ensemble de données de 9 pattes et il a travaillé en tant que bien.
Voici comment vous le faites:
Tout ce que vous devez faire est d'utiliser
scipy.ndimage.measurements.label
sur le masque à l'étiquette de tous les objets distincts. Ensuite, vous serez en mesure de jouer avec eux individuellement.Note que la méthode fonctionne bien parce que le fond n'est pas bruyant. Si c'était le cas, vous permettrait de détecter un tas d'autres indésirables sommets en arrière-plan. Un autre facteur important est la taille de la quartier. Vous aurez besoin de l'ajuster si la taille maximale de changements (le devrait rester à peu près proportionnelle).
Solution
Fichier de données: paw.txt. Code Source:
Sortie sans carrés qui se chevauchent. Il semble que les mêmes zones sont sélectionnées comme dans votre exemple.
Certains commentaires
La partie la plus délicate est de calculer la somme de tous les carrés de 2 x 2. Je suppose que vous avez besoin de tous d'entre eux, alors il pourrait y avoir un certain chevauchement. J'ai utilisé des tranches de couper le premier/dernier les colonnes et les lignes de l'original tableau 2D, puis en les superposant tous ensemble et en calculant les sommes.
Pour mieux la comprendre, de l'imagerie d'une matrice 3x3:
Alors vous pouvez prendre ses tranches:
Maintenant, imaginez que vous empilez-les les unes sur les autres et la somme des éléments à la même position. Ces sommes seront exactement les mêmes sommes sur la 2x2 places avec le coin en haut à gauche dans la même position:
Lorsque vous avez le sommes plus 2x2 places, vous pouvez utiliser
max
pour trouver le maximum, ousort
, ousorted
pour trouver les pics.De se rappeler les positions des pics j'chaque couple de valeur (de la somme) avec sa position ordinale dans une stagnation de la matrice (voir
zip
). Puis-je calculer la ligne/colonne de la position encore quand j'ai imprimer les résultats.Notes
- Je le droit de la 2x2 places à se chevaucher. Version modifiée d'un filtre certains d'entre eux tels que seuls les non-cumul des carrés apparaissent dans les résultats.
Le choix de doigts (une idée)
Un autre problème est de savoir comment choisir ce qui est susceptible d'être les doigts de tous les sommets. J'ai une idée qui peut ou peut ne pas fonctionner. Je n'ai pas de temps pour la mettre en œuvre dès maintenant, il suffit donc de pseudo-code.
J'ai remarqué que si le front de doigts sur presque un cercle parfait, l'arrière doigt doit être à l'intérieur de ce cercle. Aussi, le front, les doigts sont plus ou moins espacés de façon égale. On peut essayer d'utiliser ces propriétés heuristiques pour détecter les doigts.
Pseudo-code:
C'est une force brute approche. Si N est relativement petite, je pense que c'est faisable. Pour N=12, il y a C_12^5 = 792 combinaisons, fois 5 façons de sélectionner un arrière doigt, alors 3960 cas à évaluer pour chaque patte.
C'est un problème d'enregistrement de l'image. La stratégie générale est:
Voici une rude approche, "la chose la plus stupide qui pourraient éventuellement travailler":
Pour contrer le problème d'orientation, vous pourriez avoir 8 ou si les réglages initiaux de la base directions (nord, Nord-Est, etc). Exécuter individuellement et jetez tous les résultats au cas où deux ou plusieurs orteils retrouver à la même pixel. Je vais réfléchir à ce un peu plus, mais ce genre de chose est toujours en cours d'étude dans le traitement de l'image - il n'y a pas de bonnes réponses!
Légèrement plus complexe idée: (pondéré a) K-means. Ce n'est pas que mauvais.
Ensuite effectuer une itération jusqu'à convergence:
Cette méthode sera presque certainement vous donner de bien meilleurs résultats, et vous obtenez la masse de chaque cluster, qui peuvent aider à identifier les orteils.
(Encore une fois, vous avez spécifié le nombre de clusters à l'avant. Avec le regroupement, vous devez spécifier la densité d'une manière ou d'une autre: Soit choisir le nombre de clusters, approprié dans ce cas, ou choisir un cluster de rayon et de voir combien vous vous retrouvez avec. Un exemple de ce dernier est mean-shift.)
Désolé pour le manque de détails de mise en œuvre ou d'autres détails. Je voudrais le code de cette place, mais j'ai une date limite. Si rien d'autre n'a fonctionné la semaine prochaine laissez-moi savoir et je vais vous donner un coup de feu.
Ce problème a été étudié en profondeur par les physiciens. Il y a une bonne mise en œuvre dans RACINE. Regardez les TSpectrum classes (surtout TSpectrum2 pour votre cas) et de la documentation pour eux.
Références:
...et pour ceux qui n'ont pas accès à une souscription de NIM:
Ici est une idée: calculer la (discrète) Laplacien de l'image. Je m'attends à ce qu'il soit négative (et) de large à maxima, d'une manière qui est plus dramatique que dans les images d'origine. Ainsi, les maxima pourrait être plus facile à trouver.
Voici une autre idée: si vous savez que la taille typique de la haute pression de spots, vous pouvez d'abord en douceur votre image en pleine convolution avec une Gaussienne de la même taille. Cela peut vous donner des images simples à traiter.
À l'aide de l'homologie persistante à l'analyse de votre ensemble de données, j'obtiens le résultat suivant (cliquez pour agrandir):
C'est de la 2D version de la pointe de détection de la méthode décrite dans cette DONC réponse. La figure ci-dessus montre, tout simplement, 0-dimensions homologie persistante classes triés par la persévérance.
J'ai fait haut de gamme du jeu de données d'origine par un facteur de 2 à l'aide de scipy.misc.imresize(). Toutefois, notez que je n'ai examiner les quatre pattes comme un dataset; de le diviser en quatre, faire plus facilement le problème.
Méthodologie.
L'idée derrière ce assez simple: Considérons la fonction graphique de la fonction qui attribue à chaque pixel de son niveau. Il ressemble à ceci:
Considérons maintenant un niveau d'eau à hauteur de 255 continuellement les descentes vers les niveaux inférieurs. Au maxima locaux les îles pop-up (de la naissance). En selle points deux îles de fusion; nous considérons que le plus faible de l'île de fusion le plus élevé de l'île (la mort). Le soi-disant persistance diagramme (0-th dimensions homologie de classes, nos îles) représente la mort - dessus de la naissance des valeurs de toutes les îles:
La persistance de l'île est alors la différence entre la naissance et de la mort de niveau; la distance verticale d'un point en passant par le gris de la diagonale principale. La figure étiquettes les îles par la diminution de la persistance.
La première photo montre les lieux de naissances les îles. Cette méthode ne donne pas seulement les maxima locaux, mais aussi de quantifier leur "signification" par le ci-dessus mentionné persistance. On aurait alors de filtrer toutes les îles avec une trop faible persistance. Cependant, dans votre exemple, chaque île (c'est à dire, chaque maximum local) est un pic vous recherchez.
Code Python peut être trouvé ici.
Juste un couple des idées sur le dessus de ma tête:
Vous pouvez également jeter un oeil à OpenCV, il a un assez décent, l'API Python et peut avoir certaines fonctions que vous trouvez utiles.
Je suis sûr que vous avez assez d'aller sur maintenant, mais je ne peux pas aider, mais vous suggérons d'utiliser le clustering k-means méthode. k-means est un algorithme de clustering non supervisé qui vous permettra de données (dans un nombre quelconque de dimensions - j'arrive de le faire en 3D) et de l'organiser en k clusters avec des frontières distinctes. C'est bien ici parce que vous savez exactement combien d'orteils de ces canidés (dû).
En outre, il est mis en œuvre dans Scipy qui est vraiment sympa (http://docs.scipy.org/doc/scipy/reference/cluster.vq.html).
Voici un exemple de ce qu'il peut faire pour résoudre spatialement 3D clusters:
Ce que vous voulez faire est un peu différent (2D et comprend les valeurs de la pression), mais je pense toujours que vous pourriez donner un coup de feu.
Physicien solution:
Définir 5 de la patte-marqueurs identifiés par leurs positions
X_i
et init avec des positions aléatoires.Définir une fonction d'énergie en combinant quelques prix pour l'emplacement des marqueurs dans les pattes, de positions avec une peine de chevauchement des marqueurs; disons:
(
S(X_i)
est la force moyenne en 2x2 carrés autour deX_i
,alfa
est un paramètre qui a culminé expérimentalement)Maintenant temps de faire un peu de Metropolis-Hastings magie:
1. Sélectionnez aléatoire marqueur et le déplacer d'un pixel dans la direction aléatoire.
2. Calculer dE, à la différence de l'énergie, ce passage a causé.
3. Obtenir un nombre aléatoire uniforme entre 0 et 1 et de l'appeler r.
4. Si
dE<0
ouexp(-beta*dE)>r
, accepter les déplacer et aller à 1; si non, à l'annulation de la déplacer et aller à 1.Cette procédure doit être répétée jusqu'à ce que les marqueurs vont converger à pattes. Bêta contrôles de la numérisation à l'optimisation de compromis, de sorte qu'il devrait être aussi optimisé expérimentalement; il peut également être constamment augmenté avec le temps de la simulation (recuit simulé).
Heres une autre approche que j'ai utilisé quand on fait quelque chose de similaire pour un grand télescope:
1) Recherche de la plus haute pixel.
Une fois que vous avez cela, la recherche autour pour le meilleur ajustement pour les 2x2 (peut-être la maximisation de la 2x2 somme), ou faire un 2d fit gaussien à l'intérieur de la sous-région de dire 4x4 centré sur la plus haute pixel.
Puis la mettre de 2x2 pixels que vous avez trouvé à zéro (ou peut-être 3x3) autour du centre de pointe
revenir à 1) et répétez jusqu'à ce que le plus haut sommet tombe au-dessous d'un seuil de bruit, ou vous disposez de tous les orteils vous avez besoin
C'est probablement la peine d'essayer avec des réseaux de neurones si vous êtes en mesure de créer des données d'entraînement... mais cela nécessite un grand nombre d'échantillons, annoté de la main.
une ébauche...
vous voudrez probablement utiliser des composants de l'algorithme d'isoler chaque patte de la région. wiki a une bonne description de ce (avec un peu de code) ici: http://en.wikipedia.org/wiki/Connected_Component_Labeling
vous aurez à prendre une décision sur l'opportunité d'utiliser 4 ou 8 connexité. personnellement, pour la plupart des problèmes, je préfère la 6-connexité. de toute façon, une fois que vous avez séparé chaque "empreinte de patte" comme un connectés à la région, il devrait être assez facile à parcourir la région et de trouver les maxima. une fois que vous avez trouvé la maxima, vous pouvez agrandir de manière itérative la région jusqu'à ce que vous atteignez un seuil prédéterminé, afin de l'identifier comme un "orteil".
un subtil problème, c'est que dès que vous commencez à l'aide de techniques de vision par ordinateur pour identifier quelque chose comme un droit/gauche/avant/à l'arrière de la patte et de commencer à examiner les différents orteils, vous devez commencer à prendre la rotation, l'inclinaison, et les traductions en compte. ceci est accompli grâce à l'analyse de soi-disant "moments". il y a quelques instants à considérer dans les applications de vision:
centrale moments: traduction invariant
normalisé moments: mise à l'échelle et à la traduction de l'invariant de
hu moments: la traduction, l'échelle et la rotation de l'invariant de
plus d'informations à propos de moments peuvent être trouvés par la recherche de l'image "moments" sur le wiki.
Peut-être vous pouvez utiliser quelque chose comme Modèles de mélanges Gaussiens. Voici un paquet Python pour faire Mgm (juste fait une recherche Google)
http://www.ar.media.kyoto-u.ac.jp/members/david/softwares/em/
Il semble que vous pouvez tricher un peu en utilisant jetxee de l'algorithme. Il est de trouver les trois premiers orteils fine, et vous devriez être en mesure de deviner d'où le quatrième est en fonction de ça.
Problème intéressant. La solution que je voudrais essayer est la suivante.
Appliquer un filtre passe-bas, comme le produit de convolution avec une 2D gaussien masque. Cela vous donnera un tas de (probablement, mais pas nécessairement à virgule flottante) valeurs.
Effectuer une 2D non de la suppression maximale à l'aide de l'connu rayon approximatif de chaque patte de défilement (ou d'un orteil).
Cela devrait vous donner le maximum de positions sans avoir de multiples candidats qui sont proches. Juste pour préciser, le rayon du masque à l'étape 1 doit également être similaire à celle du rayon utilisé dans l'étape 2. Ce rayon peut être sélectionné, ou le vétérinaire pourrait mesurer explicitement à l'avance (il varie selon l'âge/race/etc).
Certaines des solutions proposées (décalage de la valeur moyenne, les réseaux de neurones, et ainsi de suite) sera probablement fonctionner jusqu'à un certain degré, mais sont trop complexes et probablement pas idéal.
Bien, voici quelques-uns simple et pas très efficace du code, mais pour cette taille d'un ensemble de données, il est très bien.
En gros, je viens de faire un tableau avec la position du coin supérieur gauche et la somme de chaque carré 2x2 et de les trier en fonction de la somme. Je puis prendre la 2x2 carrés avec la plus grande somme de la course, le mettre dans le
best
tableau, et supprimer tous les autres carrés de 2 x 2 qui a utilisé une partie de cette juste enlevé le carré 2x2.Il semble bien fonctionner sauf avec la dernière patte (celui avec la plus petite somme à l'extrême droite dans votre première image), il s'avère qu'il y a deux autres admissible 2x2 places avec une somme plus importante (et ils ont une somme égale les unes des autres). L'un d'eux est encore en sélectionne un carré à partir de votre carré 2x2, mais l'autre est sur la gauche. Heureusement, par chance, nous voyons à être le choix de plus de ce que vous voulez, mais cela peut demander quelques autres idées pour être utilisé pour obtenir ce que vous voulez vraiment tout le temps.
veux juste vous dire les gars, il est une bonne option pour trouver les maxima locaux dans les images avec python.
ou pour skimage 0.8.0
http://scikit-image.org/docs/0.8.0/api/skimage.feature.peak.html
Peut-être une approche naïve est suffisant ici: créer une liste de tous 2x2 places sur votre avion, à l'ordre par leur somme (en ordre décroissant).
Tout d'abord, sélectionnez la plus forte valeur carré dans votre "patte liste". Puis, de façon itérative, de choisir les 4 de la meilleure des places qui ne se coupent avec un de la déjà trouvé des places.
Que si vous procédez étape par étape: vous devez d'abord localiser le maximum global, le processus si nécessaire les environs de points compte tenu de leur valeur, puis définissez la trouvé région à zéro, et répétez l'opération pour l'autre.
Je ne suis pas sûr que cela répond à la question, mais il semble que vous pouvez simplement regarder pour les n sommets les plus élevés qui n'ont pas de voisins.
Voici l'essentiel. Noter que c'est en Ruby, mais l'idée doit être clair.
Il en existe plusieurs et de vastes pièces de logiciel disponible à partir de l'astronomie et de la cosmologie de la communauté - ce qui est une importante zone de recherche, à la fois historiquement et actuellement.
Ne vous inquiétez pas si vous n'êtes pas un astronome - certains sont faciles à utiliser en dehors du terrain. Par exemple, vous pouvez utiliser astropy/photutils:
https://photutils.readthedocs.io/en/stable/detection.html#local-peak-detection
[Il semble un peu rude pour répéter leur court exemple de code ici.]
Incomplète et un peu d'objectivité liste des techniques/packages/les liens qui pourraient être d'intérêt est donné ci - dessous- ne plus ajouter dans les commentaires et je mettrai à jour cette réponse est nécessaire. Bien sûr, il s'agit d'un compromis de précision vs ressources de calcul. [Honnêtement, il y a aussi beaucoup de donner des exemples de code en une seule réponse, comme cela je ne suis pas sûr que cette réponse de la mouche ou pas.]
Extracteur Source https://www.astromatic.net/software/sextractor
MultiNest https://github.com/farhanferoz/MultiNest [+ pyMultiNest]
ASKAP/UEM source-trouver défi: https://arxiv.org/abs/1509.03931
Vous pouvez également rechercher Planck et/ou de WMAP de la source-les défis d'extraction.
...