[PYTHON] Optical Flow, l'image dynamique capturée par OpenCV

Je pense qu'il y a des moments où je suis pris dans un crabe et soulevé, mais je veux analyser à quel point le mouvement était violent à ce moment-là! Je ne pense pas qu'il y ait de cas.

image Source: ASIAN KUNG-FU GENERATION "To Your Town" (Solfa Remake Memorial détail / 139427)))

Optical Flow exprime le mouvement entre les images (?). Le flux optique décrit comment chaque point se déplace entre deux images. En calculant cela, il est possible d'analyser le mouvement des points caractéristiques sur l'image comme le montre la figure ci-dessus.

Dans cet article, je voudrais présenter le contexte théorique pour le calcul du flux optique et l'implémentation à l'aide de Python / OpenCV.

Positionnement du flux optique

Il existe différents objectifs et méthodes pour réaliser l'analyse du mouvement entre les images. Ici, je vais d'abord expliquer comment le flux optique y est positionné.

En fait, les barrières à la classification sont ambiguës, comme la méthode d'estimation de flux utilisée pour le suivi, et cela peut sembler un peu chaotique car elle peut être divisée selon la méthode utilisée, mais elle est généralement divisée de cette manière.

Et, comme son nom l'indique, Optical Flow introduit cette fois est une estimation de flux.

Théorie

Maintenant, je vais expliquer le contenu théorique de la façon de calculer le flux optique.

C'est facile à comprendre si vous imaginez un dessin animé flottant, mais à la fin, une vidéo est une image continue.

image

Par conséquent, si vous pouvez analyser le mouvement entre deux images, il semble que vous puissiez les connecter et clarifier le mouvement de la vidéo entière.

Alors, comment pouvez-vous estimer le mouvement entre deux images?

Le fait qu'il y ait du mouvement signifie qu'un point de l'image est passé à un autre. Inversement, si quelque chose d'autre que la position (couleur, etc.) change, il n'y a plus moyen de le suivre, donc la couleur (souvent convertie en échelle de gris pendant le traitement, donc "luminosité") doit être la même entre les deux images. , Et faire l'hypothèse.

image

La formule sortira d'ici, mais soyez assurés qu'elle se déroulera une par une.

Soit $ I (x, y, t) $ la luminosité des points $ x, y $ sur l'image $ I $ à un certain instant $ t $. Si le temps avance de $ \ Delta t $ et que les coordonnées se déplacent $ \ Delta x, \ Delta y $ pendant ce temps, la luminosité de la destination est $ I (x + \ Delta x, y + \ Delta y, t + \ Delta t) $. Puisque nous avons fait l'hypothèse que ceux-ci n'auraient pas dû changer, l'équation suivante est vraie.

I(x, y, t) = I(x + \Delta x, y + \Delta y, t + \Delta t)

À partir de cette équation, il est maintenant possible de déduire enfin $ \ frac {\ Delta x} {\ Delta t}, \ frac {\ Delta y} {\ Delta t} $, qui est la quantité de changement de coordonnées par unité de temps. Ce sera le but du calcul effectué à partir de.

Tout d'abord, utilisez l'expansion de Taylor pour approcher le côté droit. Je pense que l'expansion de Taylor utilise une technique extrêmement difficile, mais elle est simplement transformée en une valeur proche de la valeur réelle. Veuillez consulter ici pour une brève explication.

I(x + \Delta x, y + \Delta y, t + \Delta t) = I(x, y, t) + \frac{\partial I}{\partial x} \Delta x + \frac{\partial I}{\partial y} \Delta y + \frac{\partial I}{\partial t} \Delta t + ...

Cela continuera pendant longtemps après cela, mais au fur et à mesure que cela se poursuivra, il deviendra de plus en plus petit, alors je vais sauter le pas et le couper pour ne faire que le premier développement.

I(x + \Delta x, y + \Delta y, t + \Delta t) = I(x, y, t) + \frac{\partial I}{\partial x} \Delta x + \frac{\partial I}{\partial y} \Delta y + \frac{\partial I}{\partial t} \Delta t

Ce qui se passe alors est le suivant.

I(x, y, t) = I(x + \Delta x, y + \Delta y, t + \Delta t) = I(x, y, t) + \frac{\partial I}{\partial x} \Delta x + \frac{\partial I}{\partial y} \Delta y + \frac{\partial I}{\partial t} \Delta t

Alors $ \ frac {\ partial I} {\ partial x} \ Delta x + \ frac {\ partial I} {\ partial y} \ Delta y + \ frac {\ partial I} {\ partial t} \ Delta t Si ce n'est pas = 0 $, les équations ne tiendront pas, nous les appellerons donc 0. En divisant cette formule par $ \ Delta t $, c'est-à-dire le montant du changement dans le temps, on obtient:

\frac{\partial I}{\partial x} \frac{\Delta x}{\Delta t} + \frac{\partial I}{\partial y} \frac{\Delta y}{{\Delta t}} + \frac{\partial I}{\partial t} = 0

Par souci de simplicité, la notation $ \ frac {\ partial I} {\ partial x} = I_x $ est la suivante.

I_x \frac{\Delta x}{\Delta t} + I_y \frac{\Delta y}{{\Delta t}} + I_t = 0

Enfin, $ \ frac {\ Delta x} {\ Delta t}, \ frac {\ Delta y} {{\ Delta t}} $ est sorti. Résumant la quantité de mouvement par unité de temps pour chacun des $ x et y $ sous la forme du vecteur $ \ bf {v} $, l'équation suivante peut être finalement résolue.

I_x {\bf v_x} + I_y {\bf v_y} + I_t = 0 \\\\ \nabla I^T {\bf v} = - I_t

Cependant, à partir de la conclusion, cette formule ne peut pas être résolue telle quelle. J'ai fait de mon mieux pour suivre la formule jusqu'à présent, mais je ne sais pas! Cependant, cela est inévitable car il n'y a qu'une seule équation alors qu'il y a deux inconnues (bidimensionnelles) telles que $ {\ bf v_x} $ et $ {\ bf v_y} $. Ce problème auquel nous sommes confrontés lors de la recherche d'un flux optique s'appelle le problème d'ouverture (pourquoi nous disons qu'après tout, il nécessite d'autres contraintes pour une longue explication, rien de plus que cela. Je ne l'ai pas dit, alors je vais l'omettre ici).

Maintenant, pour résoudre cette situation, nous devons augmenter au moins une équation contraignante. C'est le sujet principal, et le thème principal des différentes méthodes de détection de mouvement est de savoir comment appliquer cette «contrainte», et diverses idées ont été proposées.

Ici, je voudrais présenter deux méthodes, la méthode Lucas – Kanade, qui est un représentant du type clairsemé, et la méthode Horn – Schunck, qui est une méthode de type dense.

Méthode Lucas – Kanade

La méthode Lucas – Kanade suppose l'intégrité spatiale et la contraint. Le point est de supposer que les points environnants doivent se comporter de la même manière.

image

En supposant que les points périphériques sont $ q_1 ... q_n $ et qu'ils se comportent tous de la même manière, l'équation de contrainte peut être gonflée comme suit:

I_x(q_1) {\bf v_x} + I_y(q_1) {\bf v_y} = - I_t(q_1) \\\\ I_x(q_2) {\bf v_x} + I_y(q_2) {\bf v_y} = - I_t(q_2) \\\\ ... \\\\ I_x(q_n) {\bf v_x} + I_y(q_n) {\bf v_y} = - I_t(q_n) \\\\

Ici, chaque terme est résumé dans une matrice comme suit.

A = \left[ \begin{array}{cc} I_x(q_1) & I_y(q_1) \\\\ I_x(q_2) & I_y(q_2) \\\\ \vdots & \vdots \\\\ I_x(q_n) & I_y(q_n) \end{array} \right] \\ b = \left[ \begin{array}{c} - I_t(q_1) \\\\ - I_t(q_2) \\\\ \vdots \\\\ - I_t(q_1) \end{array} \right]

Ensuite, vous pouvez simplement écrire comme suit.

A{\bf v} = b

Tout ce que vous avez à faire est de résoudre cette équation simultanée. Cela peut être résolu en utilisant la méthode des moindres carrés(En bref||b - A{\bf v}||^2Trouvez le point qui minimise l'erreur quadratique qui peut être exprimée en utilisant la différenciation)Enfin, il peut être exprimé comme suit.

{\bf v} = (A^TA)^{-1} A^Tb

Afin de résoudre cette équation, il est supposé qu'il existe une matrice inverse dans $ A ^ TA $ (réversible) comme indiqué dans l'équation, mais la détection de coin de Harris et Shi, qui sont des méthodes typiques de détection de points caractéristiques, -Il est vrai qu'il peut être détecté par la détection Tomasi.

Méthode Horn – Schunck

La méthode Horn – Schunck limite la «douceur» du mouvement. Le fait est que celui qui parcourt la distance la plus courte est le meilleur $ {\ bf v} $.

image

Soit le coût (énergie) du mouvement $ E ({\ bf v}) $ et définissez-le comme suit. C'est un coût, donc plus il est petit, mieux c'est.

E({\bf v}) = E_{data}({\bf v}) + \alpha E_{smooth}({\bf v})

Ici, $ E_ {data} ({\ bf v}) $ représente la première équation disponible. Comme mentionné ci-dessus, $ I_x {\ bf v_x} + I_y {\ bf v_y} + I_t $ doit être égal à 0, donc plus il est proche de 0, meilleur est $ {\ bf v} $. Dans ce qui suit, l'intégration est prise pour additionner l'image entière.

E_{data}({\bf v}) = \int\int (I_x {\bf v_x} + I_y {\bf v_y} + I_t) ^2 dxdy

Et $ E_ {smooth} ({\ bf v}) $ est la contrainte sur la "douceur".

E_{smooth}({\bf v}) = \int\int || \nabla {\bf v_x} || ^2 + || \nabla {\bf v_y} || ^2 dxdy

Cela signifie que plus la quantité de changement de $ {\ bf v} $ est petite, meilleure est la valeur, c'est-à-dire meilleure est celle qui "atteint le point où la luminosité ne change pas avec une petite quantité de changement". $ \ Alpha $ est un facteur du poids accordé à cette contrainte de lissage.

En résolvant cette équation comme un problème de minimisation, vous obtiendrez le $ {\ bf v} $ souhaité. Je vais omettre le développement ultérieur pour la résolution, mais c'est l'idée de la méthode Horn – Schunck.

Édition pratique

Maintenant, je voudrais mettre en œuvre la détection de flux optique en utilisant OpenCV. Ici, nous utilisons les méthodes Lucas – Kanade et Gunnar Farneback pour lesquelles des implémentations sont fournies. La méthode Gunnar Farneback est une méthode de type dense couramment utilisée (les contraintes utilisent des points voisins comme la méthode Lucas – Kanade ...).

L'exemple réellement implémenté est placé ci-dessous, mais à partir de maintenant, en raison de problèmes de droits d'auteur, Domo-kun dans NHK's CREATIVE LIBRARY en utilisant.

icoxfog417/cv_tutorial/opticalflow

J'utilise Python3.5, numpy1.10.4 et OpenCV3.1.0 (il est plus facile d'utiliser Anaconda / Miniconda). Cependant, seul Matplotlib utilise la version 1.4.3 précédente. Cela est dû à un bug dans l'exécution de nbagg utilisé pour la lecture d'animation dans la dernière version 1.5.1 à partir d'avril 2016 (les chiffres du backend du notebook se ferment spontanément # 6075. matplotlib / matplotlib / issues / 6075)).

Quant à l'implémentation, les bases sont comme dans le tutoriel OpenCV. Tout d'abord, de la méthode Lucas-Kanade.

domo_running_snap.PNG

Vous courez. .. .. Vous pouvez voir que la trajectoire peut être suivie. La méthode Lucas – Kanade détecte les points caractéristiques et estime le flux optique à partir des points qui les entourent. Par conséquent, le traitement important est les deux points suivants.

Notez que les points caractéristiques peuvent ne pas être détectés, bien sûr (s'ils ne sont pas détectés, «Aucun» est renvoyé). De plus, tout ce qui coupe la vidéo depuis le milieu n'a pas été détecté. Gardez à l'esprit que ce que vous suivez doit être visible depuis le début (j'ai beaucoup essayé, mais je ne sais pas pourquoi).

Si vous trouvez un flux optique dense par la méthode Gunnar Farneback, vous pouvez capturer l'ensemble du mouvement plus comme suit.

image

En passant, le VideoCapture utilisé pour charger la vidéo peut également transmettre le fichier image. Je peux le faire. Par exemple, si vous spécifiez ʻimg_% 02d.jpg, les fichiers avec des numéros de série tels que ʻimg_01.jpg, ʻimg_02.jpg` ... seront lus automatiquement. Avec cela, vous pouvez facilement faire un dessin animé para-para, donc c'est amusant de l'essayer.

C'est tout pour l'explication. Essayez de capturer les mouvements mémorables!

Les références

Recommended Posts

Optical Flow, l'image dynamique capturée par OpenCV
J'ai comparé l'identité des images par moment Hu
L'histoire de l'affichage d'images avec OpenCV ou PIL (uniquement)
Ce que j'ai fait quand je ne pouvais pas trouver le point caractéristique avec le flux optique d'opencv et quand je l'ai perdu
Approximation de bas rang des images par HOSVD étape par étape
Approximation de bas rang de l'image par décomposition de Tucker
J'ai vérifié les options de copyMakeBorder d'OpenCV
[OpenCV] À propos du tableau retourné par imread
Un échantillon complet du flux optique d'OpenCV
Détection de visage en collectant des images d'Angers.
Pandas du débutant, par le débutant, pour le débutant [Python]
Reconstruction d'images animées par Autoencoder en utilisant 3D-CNN
Approximation de bas rang des images par décomposition de singularité
Trier les éléments d'un tableau en spécifiant des conditions
Approximation de bas rang des images par HOSVD et HOOI
Minimisez le nombre de polissages en optimisant la combinaison
Juger la finition du mahjong par l'optimisation des combinaisons
Classification des images de guitare par apprentissage automatique, partie 2
Rechercher par la valeur de l'instance dans la liste
Conversion en ondelettes d'images avec PyWavelets et OpenCV
J'ai essayé d'utiliser le filtre d'image d'OpenCV
[Python + OpenCV] Peignez la partie transparente de l'image en blanc