1
votes

Comment suivre un rayon d'une roue dans deux images vidéo suivantes?

Considérez deux images suivantes d'une vidéo qui se présentent comme suit: fig1

 fig2

Quelle est la possibilité de suivre le mouvement de l'un des rayons?

Je vous pose cette question car je n'ai aucune expérience du traitement vidéo. Tout conseil serait donc utile! Que suis-je suivi? D'après ce que j'ai lu, je devrais généralement détecter l'objet que je souhaite suivre en premier. Et j'utilise un algorithme de détection de coin pour cela, tel que goodfeaturestotrack . Mais comment puis-je m'assurer que je détecte le bon rayon, etc.?

Quelques informations supplémentaires: Le framerate de la vidéo est de 30 ips. La roue tourne uniquement dans le sens des aiguilles d'une montre. Et quand je clique sur la vidéo image par image, il est assez évident qu'un rayon ne bouge pas de plus de la moitié de l'angle entre deux rayons (d'une image à l'autre). Aussi: le rayon de la roue est de 5 cm.

J'ai maintenant essayé la réponse de Mark. J'ai enregistré Tmax et l'horodatage de l'image dans un fichier txt, puis j'ai écrit le code suivant pour calculer la vitesse correspondante:

ListOfVelocities = []
for idx in range(1,len(ListOfAngles)):
    if ListOfAngles[idx] < ListOfAngles[idx-1]:
        rotation = (360-ListOfAngles[idx]) + ListOfAngles[idx-1]
    else: 
        rotation = ListOfAngles[idx] - ListOfAngles[idx-1]
    timePassed = VideoTimestamp[idx]-VideoTimestamp[idx-1]
    velocity = 2*np.pi/360 * rotation * RADIUS * timePassed
    ListOfVelocities.append(velocity)


5 commentaires

Tourne-t-il dans un seul sens? L'intervalle entre les cadres est-il garanti plus court que le temps nécessaire à la roue pour tourner de 1/5 (si unidirectionnel) ou 1/10 (si bidirectionnel) de révolution? Sinon, vous rencontrez essentiellement le même problème d'alias que si vous sous-échantillonniez une forme d'onde périodique. Peindre sur les rayons une couleur différente aiderait à réduire la fréquence d'échantillonnage minimale pour éviter cela (bien que vous ayez toujours un problème pour distinguer le mouvement de 0,2 tour contre 1,2 / 2,2 / ....) Peut-être avec un taux d'exposition fixe, la quantité de mouvement le flou pourrait aider à les distinguer.


Avez-vous réellement une idée des tours par minute de la roue? Et le framerate de la vidéo?


hé les gars, j'ai mis à jour ma question pour répondre à vos remarques. Qu'est-ce que je ne sais toujours pas: comment puis-je détecter un rayon dans un cadre? Puis-je utiliser un algorithme de détection de coin? Honnêtement, je n'ai aucune idée de l'approche générale de ce problème


ne serait-il pas possible de suivre la luminosité d'une manière ou d'une autre? Les rayons sont beaucoup plus lumineux que l'espace entre les rayons. Il devrait y avoir un moyen d'examiner où le bord du clair au sombre se déplace d'une image à l'autre


«Lorsque je clique sur la vidéo image par image, il est assez évident qu’un rayon ne bouge pas de plus de la moitié de l’angle entre deux rayons» Vous ne pouvez pas dire si la roue bouge plus ou non. C'est la nature du crénelage. Avec 30 fps, la roue se déplace très lentement. S'il fait exactement 6 tours par seconde, la roue semblera immobile. Avec 8 tours par seconde, il semblera tourner 2 tours par seconde. Avec 4 tours par seconde, il semblera tourner dans l'autre sens avec 2 tours par seconde.


3 Réponses :


0
votes

Pour les cadres fournis, il est impossible de suivre un seul rayon, car tous les rayons ont une forme et une couleur identiques. La manière pratique d'en suivre un est de marquer physiquement le rayon. Ensuite, tant que votre caméra a du mouvement, vous avez besoin de image enregistrement pour aligner les cadres. Il n'est pas difficile de suivre le rayon par la suite.

Modifier: La marque physique peut être une tache colorée sur le rayon (pour plus de simplicité, utilisez une couleur unique dans l'image). Utilisez ensuite la technique de seuillage pour distinguer la couleur. Vous aurez peut-être besoin d’améliorations pour supprimer les bruits.


1 commentaires

thx Masoud! Quand vous dites marquer "physiquement" un rayon, suffirait-il d'imprimer un morceau de papier coloré sur le rayon que je souhaite suivre? Ou que suggérez-vous? Et supposons que j'ai fait cela: comment puis-je suivre le rayon alors? Quelles sont les méthodes que j'aurais besoin d'appliquer?



2
votes

Je ne perçois pas vraiment cela comme un problème de suivi car la roue est contrainte, donc elle ne peut pas se déplacer sur tout le cadre, elle ne peut changer que sa position angulaire, donc il suffit de savoir où une partie il est dans une image et combien il a tourné dans l'image suivante. Ensuite, comme vous connaissez le framerate, c'est-à-dire le temps entre les images, vous pouvez calculer la vitesse.

La question est donc de savoir quel est le même rayon que vous avez mesuré dans l'image précédente. Comme la zone derrière les rayons est sombre, vous voudriez qu'un rayon clair contraste bien afin que vous puissiez le trouver facilement. Donc, je peindrais quatre des rayons en noir, alors vous cherchez juste un clair sur un fond sombre. J'envisagerais également de peindre le centre de la roue en rouge (ou d'une autre couleur saturée), afin que vous puissiez facilement trouver le milieu.

Maintenant, au début du traitement, trouvez le centre de la roue en recherchant rouge et obtenir ses coordonnées x, y dans l'image. Maintenant, choisissez un rayon en pixels que vous pourrez modifier plus tard et établissez une liste des coordonnées x, y de par exemple 360 ​​points (1 par degré) sur la circonférence du cercle centré sur et autour du point rouge. Ces points et tous les sinus / cosinus ne changeront pas tout au long de votre traitement, alors faites-le en dehors de votre boucle de traitement vidéo principale.

Maintenant, à chaque image, utilisez l'indexation pour capter la luminosité de chacun des 360 points et, au départ au moins, prenez le plus brillant comme rayon.

Donc, j'ai grossièrement peint sur votre image donc le centre est rouge et un seul rayon est blanc:

entrez la description de l'image ici

Le code ressemble maintenant à ceci:

array([ 38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,
        38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,
        38,  38,  38,  38,  38,  43,  49,  47,  46,  45,  44,  43,  43,
        40,  38,  36,  34,  33,  33,  33,  32,  31,  31,  29,  30,  28,
        29,  29,  29,  28,  28,  27,  29,  28,  28,  27,  28,  28,  29,
        31,  36,  42,  51,  60,  70,  81,  89,  98, 105, 111, 117, 122,
       126, 128, 130, 131, 132, 133, 135, 136, 138, 139, 141, 142, 139,
       136, 133, 129, 124, 122, 119, 113, 104,  93,  82,  72,  65,  60,
        59,  56,  56,  55,  55,  54,  54,  53,  52,  52,  50,  49,  47,
        46,  45,  44,  43,  42,  40,  39,  38,  38,  37,  38,  38,  37,
        38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,
        38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,
        38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,
        38,  38,  38,  38,  38,  38,  38,  38,  34,  31,  31,  31,  31,
        31,  31,  32,  33,  34,  35,  36,  37,  38,  42,  43,  44,  45,
        48,  49,  50,  51,  55,  57,  60,  64,  65,  38,  38,  38,  38,
        38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,
        38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,
        38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,
        38,  38,  38,  52,  56,  46,  46,  47,  47,  38,  39,  40,  40,
        36,  36,  36,  36,  36,  35,  35,  34,  34,  34,  32,  33,  33,
        33,  33,  32,  32,  31,  30,  29,  29,  28,  38,  38,  38,  38,
        38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,
        38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,
        38,  38,  38,  38,  38,  38,  40,  40,  39,  38,  39,  39,  39,
        40,  40,  41,  41,  42,  42,  42,  41,  41,  42,  42,  41,  40,
        39,  40,  40,  38,  39,  38,  37,  36,  36,  35,  34,  33,  35,
        38,  38,  38,  38,  38,  38,  38,  38,  38], dtype=uint8)

Et le résultat est comme ceci:

brightnessByTheta = grey[Ys[:],Xs[:]]

Si, dans l'image suivante, la luminosité maximale est maintenant à 100 degrés par rapport à la verticale, vous savez que la roue a tourné de 10 degrés en 1 / (frames_per_second).

Vous devrez peut-être varier le rayon pour de meilleurs résultats - testez! Le rayon blanc indiqué sur l'image correspond au rayon de 60 pixels dans le code.

Plutôt que de prendre la luminosité maximale, vous voudrez peut-être trouver la moyenne et l'écart type de la luminosité des 360 pixels sur le circonférence, puis prenez l'angle comme la moyenne des angles où la luminosité est supérieure à un certain nombre d'écarts types au-dessus de la moyenne. Cela dépend de la résolution / précision dont vous avez besoin.

Vous pouvez également collecter toutes les luminosités autour du cercle indexé par thêta dans un seul tableau de 360 ​​éléments comme ceci:

theta: 0: brightness=38
theta: 5: brightness=38
theta: 10: brightness=38
theta: 15: brightness=38
theta: 20: brightness=38
theta: 25: brightness=38
theta: 30: brightness=38
theta: 35: brightness=45
theta: 40: brightness=38
theta: 45: brightness=33
theta: 50: brightness=30
theta: 55: brightness=28
theta: 60: brightness=28
theta: 65: brightness=31
theta: 70: brightness=70
theta: 75: brightness=111
theta: 80: brightness=130
theta: 85: brightness=136
theta: 90: brightness=139    <--- peak brightness at 90 degrees to vertical as per picture - thankfully!
theta: 95: brightness=122
theta: 100: brightness=82
theta: 105: brightness=56
theta: 110: brightness=54
theta: 115: brightness=49
theta: 120: brightness=43
theta: 125: brightness=38
theta: 130: brightness=38
theta: 135: brightness=38
theta: 140: brightness=38
theta: 145: brightness=38
theta: 150: brightness=38
theta: 155: brightness=38
theta: 160: brightness=38
theta: 165: brightness=38
theta: 170: brightness=38
theta: 175: brightness=38
theta: 180: brightness=31
theta: 185: brightness=33
theta: 190: brightness=38
theta: 195: brightness=48
theta: 200: brightness=57
theta: 205: brightness=38
theta: 210: brightness=38
theta: 215: brightness=38
theta: 220: brightness=38
theta: 225: brightness=38
theta: 230: brightness=38
theta: 235: brightness=38
theta: 240: brightness=38
theta: 245: brightness=38
theta: 250: brightness=52
theta: 255: brightness=47
theta: 260: brightness=36
theta: 265: brightness=35
theta: 270: brightness=32
theta: 275: brightness=32
theta: 280: brightness=29
theta: 285: brightness=38
theta: 290: brightness=38
theta: 295: brightness=38
theta: 300: brightness=38
theta: 305: brightness=38
theta: 310: brightness=38
theta: 315: brightness=38
theta: 320: brightness=39
theta: 325: brightness=40
theta: 330: brightness=42
theta: 335: brightness=42
theta: 340: brightness=40
theta: 345: brightness=36
theta: 350: brightness=35
theta: 355: brightness=38
Mean brightness on circumf: 45.87222222222222
Peak brightness: 142 at theta: 89


6 commentaires

merci beaucoup, Mark! C'est une très bonne idée! ..Avant que vous ne fournissiez cet exemple de code, j'ai essayé un peu et j'ai trouvé qc. similaire: j'ai mis un seuil sur ma roue de telle sorte que les pixels ne soient que 0 ou 255 (pour une raison quelconque, ils ne le sont pas, mais ils devraient l'être). Et puis je détecte les valeurs de pixel dans juste un segment du cercle. ... Ce n'est pas encore fait, mais j'espère que ça marche aussi.


Cool - bonne chance et n'hésitez pas à publier les améliorations que vous proposez.


Mark, lorsque je marque un ROI autour de ma roue et que je prends un seuil dans ce ROI, s.a. ret_thresh, thresh = cv2.threshold (ROI, 80, 255, cv2.THRESH_BINARY) , toutes les valeurs de pixel de ce retour sur investissement doivent être de 0 ou 255, n'est-ce pas? J'ai en outre obtenu une liste de tuples, où chaque tuple donne les coordonnées (x, y) des points sur un arc circulaire autour de l'axe de la roue. Le problème est que les pixels de cet arc ne sont pas seulement 0 ou 255. Est-ce encore possible? Seulement si je fais qc. faux, je suppose


Commencez une nouvelle question (elles sont gratuites) et mettez votre code OpenCV là-dedans pour que nous puissions voir ce qui se passe.


ok, merci Mark! stackoverflow.com/questions/56340555/...


hey Mark, s'il vous plaît voir ma question éditée! Cela peut sembler une question stupide à poser, mais le code que j'ai écrit pour calculer la vitesse de la roue vous semble-t-il correct? Je demande car je doute du résultat



0
votes

Luk, ce que Masoud explique, c'est que vous marquez physiquement la roue. Cela peut être un petit autocollant blanc ou une goutte de peinture. Si vous convertissez en échelle de gris, le blanc serait la meilleure option, IMO. Si c'était moi, je trouverais la roue en utilisant Hough Circle et le seuillage. Une fois que vous avez la roue, créez un masque pour supprimer l'arrière-plan. Cela ne laisse que la roue. Une fois que vous avez la roue localiser l'endroit le plus brillant (devrait être l'autocollant blanc, la goutte de peinture ou tout ce qui est utilisé), enregistrez son emplacement, de préférence le centre et pour chaque cadre, effectuez le même processus et mesurez le changement de l'emplacement et utilisez-le pour déterminer le moment cinétique.

Doug


0 commentaires