Transcription
1. Introduction: Voici un échange de visage. Vous l'avez vu dans des photos, des vidéos, des clichés, vous le nommez. C' est idiot, amusant, et parfois terriblement effrayant. Vous pouvez échanger des visages avec votre ami, une célébrité, votre bébé ou même votre chien. Construisons cet échange de visage. Bonjour, je suis Aldo, conférencier en informatique et doctorant à l'UC Berkeley. J' aide à voir l'ordinateur, étudier la vision par ordinateur pour la réalité virtuelle et les voitures autonomes. J' ai coupé plus de 15 000 étudiants et j'ai hâte de te montrer la magie aussi. Dans ce cours, vous apprendrez les bases de la vision par ordinateur. J' ai mis cette classe pour tous ceux qui sont intéressés ; codeurs, designers, chefs d'entreprise, n'importe qui, si vous ne connaissez pas Python, pas de problème. Soyez rattrapé avec mon cours Coding 101, Python pour débutants. Vous ne connaissez pas AML ? C' est aussi bon. Prenez mes outils de masterclass d'intelligence artificielle pour l'apprentissage automatique. À la fin de cette classe, vous comprendrez les images, le traitement des
images, la détection des visages et bien plus encore. Vous disposerez également d'une application de bureau d'échange de visages entièrement fonctionnelle qui peut échanger des visages contre des images encadrer les pièces. Cela ne vous prendra qu'une heure ; rien à installer, pas de configuration compliquée. Vous avez juste besoin d'un ordinateur portable avec Internet. Vous partirez avec un swapper de visage et un savoir-faire en vision par ordinateur en un rien de temps. J' espère que tu es excité parce que je le sais. Faisons ça.
2. Qu'est-ce que la vision par ordinateur ?: Commençons par répondre, qu'est-ce que la vision par ordinateur ? Voici la définition. La vision par ordinateur, au sens
large, est la vue pour l'IA. Il y a un certain nombre de tâches de vision par ordinateur qui reflètent cela, comme la détection d'objets, qui encadre et classe tous les objets de la scène comme la fleur à gauche. Super résolution, qui hallucine les détails pour rendre vos images plus nettes, comme la couleur vive sur la droite, contrastée avec les buissons flous sur la gauche. Estimation du point clé qui identifie les points clés comme les articulations et les membres, comme le danseur antique à gauche. Nous pouvons maintenant répondre à nouveau qu'est-ce que la vision par ordinateur d'une manière appliquée ? La vision par ordinateur consiste plus précisément à extraire des informations à partir ou à générer des images. Pour mieux comprendre ce domaine, examinons le cadre d'
apprentissage automatique que nous avons abordé dans notre master class sur l'IA. Si vous n'avez pas déjà suivi ce cours, je vous recommande de le faire. Dans notre master class sur l'IA, nous avons discuté de compartimenter nos connaissances en ML en quatre catégories. Données, modèle, objectif et algorithme. Les données décrivent les entrées et les extrants, ce que nous apprenons et ce que nous prévoyons. Le modèle décrit comment faire des prédictions. Objectif décrit l'objectif, ce que le modèle optimise. Enfin, l'algorithme décrit comment le modèle apprend. Nous n'avons pas beaucoup discuté de l'algorithme, et nous allons l'ignorer encore cette fois. En vision par ordinateur, les données sont toujours visuelles, à savoir des images et des vidéos. Nous pouvons également utiliser d'autres signaux connexes tels que l'audio ou la profondeur au-dessus des images et des vidéos. Nous allons nous concentrer sur les données de cette leçon. Nos modèles en vision par ordinateur classique et en apprentissage profond extraient
aujourd'hui des modèles de l'image à l'aide d'un outil appelé filtres. Nous en discuterons dans les leçons ultérieures. Enfin, notre objectif est généralement de maximiser la précision. Comme d'habitude, nous allons sauter les algorithmes. Pour comprendre le reste de la vision par ordinateur, nous devons comprendre comment les images sont représentées. Qu' est-ce qu'une image ? Comment une image est-elle représentée sous forme de nombres ? Regardons un exemple. Nous pouvons construire une image en noir et blanc en utilisant des nombres où zéro correspond au noir et un correspond au blanc. Concentrez-vous sur la ligne de division entre les zéros et les uns. Quelle forme voyez-vous ? Enregistrer cette matrice de nombres comme une image nous donne ceci. Il s'avère que c'est un diamant. Et si nous voulons des images en niveaux de gris, pas seulement en noir et blanc ? Eh bien, toujours en utilisant zéro pour le noir et un pour le blanc, nous pouvons également utiliser n'importe quelle valeur entre zéro et une telle que 0.1,0.26, ou 0.74391. nombres plus proches de zéro sont plus sombres et les nombres plus proches d'un ou plus légers. Cela nous permet de représenter le blanc, noir et toute nuance de gris. Considérez ce qui suit, par exemple, pouvez-vous dire ce que c'est ? Encore une fois, chaque nombre correspond à la luminosité d'un pixel. Sauver cette boîte de chiffres comme une image nous donne ceci, une boule de pokey. Il est impossible de le voir à partir des chiffres de la diapositive précédente, mais vous savez maintenant comment les images en noir, blanc et gris sont représentées numériquement. Pour introduire la couleur, nous avons besoin d'un moyen d'encoder plus d'informations. Voici comment. Tout d'abord, chaque image a une hauteur et une largeur. Cette image est h par w. Chaque pixel, comme nous l'avons vu auparavant dans une image en niveaux de gris a une valeur. Nous pouvons dire de façon équivalente que notre image a des dimensions H par W par un. La mise à niveau de cette image en niveaux de gris vers une image en couleur implique ce qui suit. Pour une représentation de couleur, nous représentons la couleur de chaque pixel en utilisant trois valeurs comprises entre zéro et un. Un nombre correspond au degré de rouge, un au degré de vert, et le dernier au degré de bleu. Nous appelons cela l'espace colorimétrique RVB. Cela signifie que pour chaque pixel de notre image, nous avons trois valeurs, R, G et B. Par conséquent, nos images maintenant H par W par trois. C' est comme ça que vous obtenez une image en couleur comme celle-ci. En réalité, chaque valeur varie de 0 à 255 au lieu de 0 à 1. Mais l'idée est la même. Différentes combinaisons de nombres correspondent à différentes couleurs, telles que 171, 180, 190 bleu clair, ou 200, 199,188, brun clair. En résumé, chaque image sera représentée sous la forme d'une boîte de nombres ayant trois dimensions, hauteur, largeur et trois couches de couleur. Manipuler directement cette boîte de nombres équivaut à manipuler l'image, et c'est ainsi que les images sont représentées sous forme de nombres. En résumé, nous avons défini la vision par ordinateur comme extraction d'informations ou la génération d'images. Nous avons couvert les abstractions ML pour la vision par ordinateur, les données, le modèle, l'objectif et l'algorithme. Enfin, nous avons discuté de la façon dont les images sont représentées numériquement. Avec toutes ces connaissances, vous êtes bien équipé pour commencer à travailler avec des images encodées. Pour obtenir une copie de ces diapositives et plus de ressources, consultez cette URL. Cela conclut cette introduction. Faisons le codage dans la prochaine leçon.
3. Bases du code OpenCV: Bienvenue à la première leçon de codage de ce cours. Allons nous salir les mains avec du code. Si vous souhaitez une introduction rapide à la programmation en Python, assurez-vous de consulter mon cours Python pour débutants avant de commencer cette leçon. Vous pouvez mettre la vidéo en pause ici pour accéder à cette URL. À un niveau élevé, nous allons générer une image puis nous allons essayer notre webcam. L' objectif est d'explorer les utilitaires OpenCV fondamentaux. Commencez par accéder à cette URL. Cela créera un environnement pour nous à distance afin que nous n'ayons pas à faire de configuration sur nos ordinateurs. Vous verrez sur le côté droit, j'ai déjà fait ça. Pour ce tutoriel, je recommande fortement d'utiliser Google Chrome. Malheureusement, j'ai testé le code dans quelques navigateurs différents et seul Google Chrome est pris en charge pour le moment. Votre objectif sera de générer cette image. première étape consiste à créer la représentation numérique de l'image comme celle-ci. Rappelez-vous d'avant que ceux et zéros peuvent faire une image en noir et blanc comme nous avons discuté, zéro ici est noir et un est blanc. Cependant, en réalité, les nombres vont de 0 à 255, donc nous allons utiliser 255 pour le blanc et zéro pour le noir. Créons ce tableau dans le code maintenant. Sur le côté droit, je vais cliquer sur le X, eh bien, je suis ici en haut à droite pour que nous puissions fermer cette fenêtre d'aperçu. Sur la gauche, cliquez sur Nouveau fichier et tapez generate.py. Cela va créer un nouveau fichier pour nous. Réduisons maintenant ce navigateur de fichiers. Je vais maintenant zoomer sur mon code afin que vous puissiez mieux voir ce que je fais. Pour commencer, dans votre generate.py, importez numpy, qui contient vos utilitaires d'algèbre linéaire. Par convention, nous avons renommé numpy en np pour plus de commodité plus tard. Ensuite, importez OpenCV, qui contient vos utilitaires de vision et d'image informatiques. Nous allons d'abord créer une représentation numérique de notre image. Allez-y et tapez l'image équivaut à un tableau numpy et ce tableau numpy prendra une liste de listes qui spécifie les nombres que nous avons sur le côté gauche. tapant ces chiffres maintenant. Après avoir entré les nombres, définissez un type de données. Ce type de données va être un entier non signé. Ce type de données ici est important. Nous définissons le type de données sur un entier non signé car tous nos entiers dans cette image sont positifs. Ceci est nécessaire pour OpenCV ou cv2 pour enregistrer correctement votre tableau en tant qu'image. Ensuite, nous allons redimensionner notre image. Voici comment
redimensionner, appeler cv2.resize sur l'image pour redimensionner et passer la taille désirée de l'image. Dans ce cas, notre image est grande. Nous voulons donc une largeur de 90 pixels et une hauteur de 150 pixels. Mais si nous exécutons ce code, nous serions cruellement déçus. Notre huit taille supérieure aurait l'air moche comme ça. Au lieu de cela, nous voulons un huit pointus. Nous allons donc augmenter la taille en utilisant une autre technique de redimensionnement appelée voisins les plus proches. Pour ce faire, nous allons ajouter un troisième argument à notre fonction de redimensionnement. Encore une fois, voici redimensionner. Nous passons l'image pour redimensionner la taille finale et le troisième argument indique à cv2 d'utiliser la technique d'échantillonnage vers le haut voisin le plus proche. Essayons ceci dans le code maintenant. Nous allons maintenant écrire, l'image est égale à cv2.resize image virgule 90, 150. Ensuite, enfin, la méthode d'interpolation, qui est CV2.inter_next. Vous verrez malheureusement que mon code est coupé sur le côté droit. Ce juste ici dit que l'interpolation est égale à CV2.inter_plus proche. Avec notre image redimensionnée, il ne reste plus qu'à la sauvegarder. Pour enregistrer l'image, utilisez cv2.imwrite, comme indiqué ici. Le premier argument est le chemin, et le second argument est l'image. Essayons ça. Après votre code existant, tapez cv2.imwrite fournira le chemin de l'image et de l'image elle-même et c'est tout. Nous sommes maintenant prêts à exécuter ce code. Nous avons fini d'écrire notre code dans un fichier Python appelé generate.py. Dans les leçons Python précédentes, en particulier celles sur Repl.it, nous appuyions sur le bouton vert de course en haut de l'écran pour exécuter le fichier Python. Nous n'avons pas de bouton vert sympa, donc nous allons le faire manuellement et exécuter notre fichier Python à travers la ligne de commande. Pour lancer la ligne de commande, rouvrez votre navigateur de fichiers sur le côté gauche en cliquant sur la flèche. Une fois que vous faites cela, vous verrez la boîte de dialogue d'un outil en bas à gauche, cliquez sur Outils, et dans la liste déroulante, sélectionnez Terminal. Dans ce Terminal, vous verrez une configuration comme je vois ici. Je vais zoomer légèrement. Une fois que vous voyez ce terminal, vous pouvez maintenant entrer votre commande. En particulier, la commande est Python et l'argument est le chemin du fichier, qui est generate.py dans ce cas. Allez-y et tapez Python generate.py et appuyez sur Entrée. Après avoir exécuté votre code, vous devriez voir un 8.png dans votre barre latérale gauche. Cliquez dessus pour voir votre image générée et voilà, vous avez généré votre première image. Commençons maintenant à manipuler les sorties de la webcam. Accédez à cette URL. Une fois que vous avez chargé la page, fermez l'aperçu à droite, en
cliquant sur le X en haut à droite. Sur le côté gauche, nous allons maintenant créer un nouveau fichier. Dans cette partie de la leçon, notre objectif est de connecter nos utilitaires OpenCV à la webcam. Commençons par lancer une application Web minimale à l'aide d'une bibliothèque personnalisée créée juste pour ce cours appelé Web OpenCV. Sur le côté droit, cliquez sur Nouveau fichier et tapez app.py. Ici, je vais minimiser cette barre latérale en cliquant sur la flèche en haut à gauche. Dans cette partie de la leçon, notre objectif est de se connecter à notre webcam en utilisant les utilitaires OpenCV fournis dans cette leçon. Commençons par lancer une application Web minimale à l'aide d'une bibliothèque personnalisée créée juste pour ce cours appelé Web OpenCV. Importer webopencv en tant que WCV. Nous importerons ensuite OpenCV pour nos utilitaires généraux de vision par ordinateur. Donc, importez cv2. Ensuite, nous allons instancier votre application Web. Vous pouvez le faire en tapant l'application est égale à WCV.WebApplication. Enfin, vous pouvez exécuter votre application Web, app.run, et c'est tout. Pour prévisualiser votre nouvelle application, cliquez sur Afficher en haut à gauche. Pour moi, j'ai tellement réduit mon écran que je ne peux voir qu'une paire de lunettes de soleil. Cliquez sur Dans une nouvelle fenêtre. C' est ma nouvelle fenêtre. Malheureusement, le haut est coupé, dans cette nouvelle fenêtre, cliquez sur Afficher, puis cliquez sur Autoriser. Une fois que vous avez terminé, cliquez sur Arrêter pour arrêter la webcam. Si vous êtes préoccupé par la confidentialité, ne vous inquiétez pas, les données de cette webcam ne sont
communiquées que de votre ordinateur à votre propre serveur Glitch, qui est ce que vous codez en ce moment. Donc, seul votre code et le serveur sont en train de traiter votre webcam. Personne d'autre ne le voit. Vous êtes maintenant le développeur. Ajoutez maintenant votre toute première transformation d'image à l'application Web. Cette transformation écrira finalement du texte sur l'image qu'elle reçoit. Mais pour l'instant, allons transformer ça ne fait rien. Créez une fonction appelée Hello. Il prend en deux arguments, l'image et un autre objet appelé le cadre, et retourne l'image. Toutes les transformations sauf les images en entrée et retournent l'image traitée. Nous avons également besoin d'un décorateur appelé app.transform. Nous sauterons les détails techniques du fonctionnement d'un décorateur. Pour l'instant, sachez simplement que ce décorateur enregistre sont transformés avec notre application web. Toute transformation enregistrée apparaîtra dans notre interface Web. En outre, le texte en rose sera utilisé comme nom des transformations. Essayons ceci maintenant dans le code. Sous l'endroit où votre application est définie, ajoutez votre tout nouveau décorateur, avec le nom de transformation Hello. Nous allons maintenant appliquer un argument de mot-clé, la valeur par défaut est true. Cela garantit que la transformation Hello est automatiquement appliquée lorsque la webcam est chargée. Définissez votre fonction hello, qui prend dans l'image et un autre argument appelé le cadre, et enfin, retournez l'image. Maintenant, si vous actualisez la page dans une nouvelle fenêtre, vous verrez que la transformation Hello est choisie par défaut. Ici, nous avons Bonjour. Ensuite, nous allons écrire du texte HelloWorld sur le flux en direct de la webcam. Voici comment faire ça. Voici l'image à annoter. Le texte que nous voulons afficher, la position du texte, la police que nous voulons utiliser et la taille de la police efficacement. Ceci est en fait donné sous forme d'échelle par rapport à la taille de police par défaut. Enfin, nous avons la couleur en RVB. Donc ici 255, 0, 0 signifie rouge. Dans la fonction Hello va maintenant ajouter du texte à l'image juste au-dessus où vous retournez ou type d'image et CV2.putText. Nous allons passer l'image, la chaîne Hello World, la position, la police. Nous allons lui donner une taille de police de 1. Enfin, nous allons utiliser la couleur verte. Ici, nous allons utiliser 0, 255, 0. Maintenant, accédez à votre application Web. Cliquez sur Démarrer et le texte Hello World s'affiche. On y va. Voici les étapes que nous avons parcourues. Nous avons couvert OpenCV, l'écriture d'images et les utilitaires d'ajout de texte. Pas besoin de les mémoriser. Vous pouvez toujours les chercher. Je voulais juste te donner un peu de pratique pour travailler avec ces services publics. Pour obtenir une copie de ces diapositives, du code fini et d'autres ressources, assurez-vous de récupérer cette URL. C' est tout pour les bases d'OpenCV.
4. Comment fonctionnent les échanges de visage ?: Nous allons creuser dans les échanges de visage. Quelque chose qui ressemble à ça. Comment cela fonctionne-t-il ? Laissez-moi vous expliquer. Nous commencerons par décomposer ce visage en échangeant produit
IA en sous-problèmes. Qu'est-ce qu'un échange de visage ? Dans notre version simple de l'échange de face, un échange de face prend deux étapes, détecter toutes les faces et échanger les pixels pour ces faces. Parlons de ces deux étapes plus en détail maintenant. Première étape, la détection de visage, la détection visage
résumée prend une image comme celle-ci et dessine des boîtes autour des visages. Décrivons maintenant ces algorithmes de dessin de boîte plus en détail. Nous allons introduire la détection des visages en décrivant les données associées, modèle, l'objectif et l'algorithme. Voici ce que signifient chacun de ces termes. D' abord, les données. Notre modèle de détection de visage accepte une image et prédit une boîte contenant le visage. Ces cases sont représentées à l'aide de quatre chiffres. Chaque description de la boîte comprend le coin supérieur gauche, x et y, ainsi que la hauteur et la largeur. Ces quatre chiffres définissent une boîte de manière unique. Un modèle de détection de visage prédit ces quatre coordonnées pour une face. Deuxième modèle, le modèle particulier de détection de visage que nous allons utiliser est appelé un classificateur de cascade Haar. Nous discuterons de ce modèle plus en détail dans une leçon ultérieure. Troisième objectif, notre modèle vise à maximiser la précision de détection du visage. Pour mesurer la précision, nous utilisons une métrique appelée intersection sur union ou IOU. Parlons de la façon dont les IOU sont calculées. Voici comment fonctionne l'IOU ou l'intersection sur le syndicat. Dis que cette boîte rouge est notre boîte prédite, le bleu est notre vérité. Intuitivement, moins ces deux boîtes se chevauchent, plus
la précision devrait être faible. Plus ils se chevauchent, plus notre précision devrait être élevée. Nous calculons le chevauchement indiqué en rose pour mélanger vos plus grandes boîtes pour obtenir automatiquement une plus grande précision. Nous divisons également par le syndicat désigné en vert. Cette intersection sur union ou IOU est la façon dont nous mesurons la précision des détecteurs d'objets. Enfin, comme d'habitude, nous allons sauter l'algorithme. Ceci conclut notre introduction à la détection du visage. Nous discuterons plus en détail de la détection du visage dans une leçon ultérieure. Pour l'instant, passons à la deuxième étape de l'échange de visage, l'échange lui-même. La deuxième étape est un échange de pixels, nous devrons effectuer un redimensionnement au cas où les deux faces détectées sont différentes tailles, mais c'est autrement assez simple. Maintenant, voyons un exemple de ces deux étapes ensemble. Tout d'abord, détectez les deux faces, puis échangez-les. Certes, cela n'a pas l'air convaincant. Pour cette classe, nous allons construire ce simple échange de visages, mais permettez-moi d'expliquer comment les échanges de visages de qualité industrielle rendent cela plus réaliste. Refaisons la ventilation du produit IA échangeant face. C' était notre compréhension précédente de l'échange de visage. abord, au lieu de simplement détecter les visages, va maintenant détecter les points clés dans le visage. Voici un exemple visuel de points clés faciaux. Les points clés du visage peuvent correspondre à des parties significatives du visage, comme le pont du nez, zone juste au-dessus d'un sourcil, les fossettes et plus encore. Avec nos points clés, nous déformons ensuite les pixels afin que chaque région de la face soit déformée jusqu'à la région correspondante d'une seconde phase. Pour visualiser cela, disons que nous avons deux visages maintenant, nous avons les points clés faciaux d'avant pour la personne sur la gauche. Nous avons également les mêmes points clés faciaux pour la personne à droite. Concentrons-nous sur les trois points clés autour de leur œil gauche. Ces points clés forment des triangles, pour faire face swap va déformer le triangle sur la gauche vers le triangle sur la droite. Après quelques techniques de fusion d'images, nous aurons alors un échange de visage photoréaliste, quelque chose comme ça. C'est ça. Nous avons couvert une version minimale de l'échange de face qui va construire, qui se compose de deux étapes, détecter les faces et échanger les pixels. Nous avons également couvert les techniques d'échange de visage professionnelles utilisées par les applications
populaires pour une copie de ces diapositives et plus de ressources, assurez-vous de vérifier cette URL et maintenant vous savez comment les échanges de visages fonctionnent. Revenons à coder une fois de plus pour commencer à construire notre propre échange de visage.
5. Détection de visage de code: Dans cette leçon, nous allons expérimenter avec un détecteur de visage. À un niveau élevé, nous détecterons les visages dans une image, puis nous détecterons les visages dans notre webcam. L' objectif est d'explorer les utilitaires de détection spatiale. Commencez par accéder à cette URL comme je l'ai fait sur le côté droit. Cela créera un environnement pour nous à distance afin que, comme avant, nous ne faisons aucune configuration sur nos ordinateurs. Sur le côté droit ici pour être prêt pour notre développement, je vais fermer cet aperçu dans le côté droit en cliquant sur le x en haut à droite. Dans le navigateur de fichiers, je vais cliquer sur Nouveau fichier, puis taper detect.py. Ensuite, cela va automatiquement ouvrir detect.py dans notre éditeur. Je vais minimiser notre navigateur de fichiers en cliquant sur cette flèche gauche. Ensuite, je vais zoomer pour que vous puissiez mieux voir ce que je fais. Nous commencerons par lire et écrire une seule image. Pour lire l'image, utilisez cv2.imread comme indiqué ici. Le premier argument est le chemin de l'image à lire. Essayons ceci, dans votre nouveau fichier Python, commencez par importer OpenCV, importez cv2. Ensuite, lisez l'image, kids.jpg. Ici, nous allons taper l'image est égale à cv2.imread et kids.jpg. Pour enregistrer l'image, utilisez cv2.imwrite, comme indiqué ici. Le premier argument est le chemin et le second argument est l'image. Essayons ceci maintenant, écrivez l'image dans un nouveau fichier appelé out.jpg, cv2.imwrite dans out.jpg, puis incluez l'image à droite. Ensuite, nous allons rouvrir notre navigateur de fichiers et dans le côté gauche, cliquez sur Outils en bas, puis cliquez sur Terminal. Attendez que la configuration se termine. Une fois l'installation terminée, vous serez accueilli avec une invite comme celle-ci. Ici, nous allons taper python detect.py. Appuyez sur Entrée. Cela exécutera le script Python que vous venez d'écrire. Le script va lire kids.jpg
et l'enregistrer dans out.jpg. Pour vérifier, ouvrez out.jpg sur la gauche. Ici, vous verrez que out.jpg correspond à kids.jpg. Instancions maintenant notre détecteur de visage. Si vous souhaitez un rafraîchissement sur ce qu'est l'instanciation ou quels sont les objets, assurez-vous de vérifier ma classe de programmation orientée objet de niveau intermédiaire. Vous pouvez suspendre la vidéo ici pour accéder à cette URL. Instanciez le détecteur de visage et transmettez les paramètres du modèle. Ici, les paramètres du modèle sont stockés dans un fichier appelé parameters.xml. Dans votre navigateur de fichiers, cliquez une fois de plus sur detect.py. Ici, je vais à nouveau fermer mon terminal en bas en cliquant sur le x. Je vais aussi minimiser mon navigateur de fichiers. Vous n'avez pas besoin de faire l'une ou l'autre de ces choses. Je suis juste en train de décollutter la vidéo pour que vous puissiez mieux voir mon code. Juste au-dessus de l'image, nous allons maintenant instancier le détecteur de visage. Detector est égal à CV2.CascadeClassifier. Encore une fois, l'argument est parameters.xml. Utilisons maintenant le détecteur de visage pour détecter les visages. Nous allons le faire en utilisant la méthode DetectMultiScale, passer l'image à cette méthode, et en outre passer un nouvel argument de mot-clé appelé ScaleFactor est égal à 1.3. Nous discuterons de ce que signifie ScaleFactor plus tard. Pour l'instant, nous allons passer
ces deux arguments et la méthode retournera ensuite un tas de rectangles, chaque rectangle correspondant à une face dans l'image. Essayons ça maintenant. Après avoir défini votre détecteur de visage et après avoir chargé dans l'image, nous allons maintenant détecter tous les visages en cours d'exécution, rectangles est égal au détecteur.DetectMultiscale, et comme nous l'avons écrit sur la gauche, nous vont passer dans l'image et le ScaleFactor. Enfin, dessinons des rectangles sur l'image correspondant aux faces détectées. Voici comment faire ça. Appelez la fonction cv2.rectangle. Ici, nous allons passer dans l'image pour dessiner des
rectangles, les coordonnées du coin supérieur gauche du rectangle, les
coordonnées du coin inférieur droit du rectangle, la couleur de la bordure du rectangle. Rappelez-vous, le premier nombre représente ici la quantité de rouge, le second la quantité de vert, et le dernier la quantité de bleu, avec le montant varie de 0 à 255. En conséquence, 0, 255, 0 signifie vert. Il y a une subtilité ici. Le jeu de couleurs n'a pas réellement RVB mais BGR pour OpenCV, mais nous omettons ce détail pour l'instant. Mais si vous essayez de changer ces couleurs, c'est pourquoi le premier numéro contrôle réellement le degré de bleu. Enfin, nous allons définir la largeur de ligne de la bordure du rectangle, qui est de deux pixels de large. Essayons maintenant cela dans le code. Sur le côté gauche, nous allons faire une boucle sur tous les rectangles. Ici, nous savons que le rectangle est un tuple de quatre nombres comme nous avons parlé dans la leçon précédente. Nous pouvons maintenant écrire x, y, w, h est égal au rectangle. Cette syntaxe nous permet d'assigner x au premier nombre, y au second, w au troisième et h au quatrième. Maintenant, dessinez le rectangle en utilisant la fonction dont nous avons discuté. CV2.Rectangle, l'image, la coordonnée de départ, la coordonnée de fin, la couleur verte, et enfin la largeur de bordure. Si vous ne l'avez pas déjà fait, ouvrez le navigateur de fichiers sur la gauche, cliquez sur Outils et sélectionnez Terminal. En bas, vous verrez quelques réglages. Une fois que votre terminal est prêt, tapez python detect.py dans le terminal. Cela exécute le script Python de détection de visage que vous venez d'écrire. Après avoir exécuté ce script, cliquez sur out.jpg sur la gauche, vous verrez que l'image a maintenant des rectangles dessinés autour de chaque face. Nous allons maintenant répéter la détection de visage, mais pour notre propre webcam. Commencez par accéder à cette URL. Une fois que votre page est chargée, comme avant, minimisez votre aperçu en cliquant sur le x en haut à droite. Maintenant, nous avons déjà un fichier créé pour nous. C' est de la leçon précédente. Je vais fermer le navigateur de fichiers sur le côté gauche en cliquant sur la flèche gauche. Pour commencer, nous allons modifier la fréquence d'images de notre flux vidéo basé sur le Web. Cela empêche notre application web de trop traîner. Ajoutez une fréquence d'images d'argument de mot-clé au constructeur comme ceci. Dans notre code, je vais taper framerate égal à 5. En outre, nous allons supprimer CV2.putText, nous le remplacerons plus tard. Comme avant, nous allons instancier le détecteur de visage. Encore une fois, comme avant, transmettez les paramètres du modèle à parameters.xml dans ce CascadeClassifier. Juste au-dessus de la définition de l'application, je vais taper détecteur est égal à CV2.CascadeClassifier parameters.xml. Ensuite, détectez toutes les faces de l'image. Nous configurons légèrement la détection de visage, comme avant de passer l'image pour détecter les visages sur et comme avant de passer en outre dans ScaleFactor est égal à 1.3. Ce ScaleFactor nous permet de détecter des faces de plus grande taille. Voici comment, disons, le détecteur de visage a été formé pour détecter des visages de cette taille. Ici, le carré bleu est l'image, le cercle est une représentation abstraite d'un visage. Au cours de l'inférence, un visage plus grand comme celui-ci serait normalement manqué puisque notre détecteur n'est pas entraîné pour des visages aussi larges. Pour contourner cela, nous réduisons l'image de 30 pour cent et lançons le détecteur dessus. Répétez ensuite ceci, réduisez l'
image 30 % et exécutez à nouveau le détecteur. Dans cette dernière étape, notre visage pendant l'inférence est de la même taille que les visages pendant l'entraînement de sorte que notre détecteur est capable de détecter le visage. C' est ce que signifie DetectMultiscale. Cordons ça maintenant. Tout d'abord, renommons cette transformation de Hello World en Find Faces. Nous allons également renommer la fonction en find_faces. Ensuite, trouvez tous les visages dans l'image comme nous l'avons fait avant. Nous allons également ajouter le facteur d'échelle comme nous l'avons mentionné précédemment, pour rendre le détecteur plus robuste à différentes tailles de visage, rectangles est égal à détecteur.DetectMultiscale, et nous allons passer dans l'image et un ScaleFactor de 1.3. Enfin, dessinez des rectangles autour de tous les visages comme avant. Voici encore une fois, comment dessiner un rectangle dans OpenCV. Faisons ça maintenant. On va boucler tous les rectangles. Nous allons détruire le rectangle en quatre variables comme nous l'avons fait avant. Enfin, nous allons dessiner des rectangles autour de tous les visages. Maintenant, notez que nous pouvons réellement simplifier cette boucle pour. Puisque x, y, w, h est égal au rectangle, nous pouvons en fait remplacer rectangle par ces quatre variables. Je vais maintenant supprimer cette ligne. Ici, nous avons pour x, y, w, h dans les rectangles. Maintenant, cliquez sur Afficher en haut à gauche. Pour moi, malheureusement, ma fenêtre est trop petite, donc ça ressemble à une paire de lunettes de soleil. Cela ouvrira un aperçu de votre application Web. Je vais à nouveau zoomer pour que vous puissiez voir. Je vais ensuite cliquer sur Démarrer et vous verrez un flux de webcam sauf avec votre visage en boîte. Encore une fois, cliquez sur Autoriser si nécessaire. C' est tout pour cette leçon, vous avez maintenant exploré les utilitaires de détection de visage dans OpenCV pour obtenir une copie de ces diapositives, le code fini et d'autres ressources, assurez-vous de vérifier cette URL.
6. Comment fonctionnent les détecteurs de visage ?: Permettez-moi de faire un pas en arrière pour expliquer comment fonctionnent les détecteurs de visage. Nous commencerons par détecter des entités simples comme des arêtes. Prenez notre image de la leçon précédente. Disons que nous voulons extraire de petites entités simples comme des bords. À un niveau élevé, nous voulons trouver ces petites fonctionnalités dans chaque patch possible de l'image. Disons que chaque patch est deux par deux pour commencer. Nous allons commencer par le haut à gauche et demander, avons-nous trouvé la fonctionnalité ici ? Et ici ? Et ici ? Donc, et ainsi de suite jusqu'à ce que vous ayez couvert toute l'image. Maintenant, comment trouver de petites entités comme des arêtes dans chacun de ces patchs deux par deux ? Considérez un patch deux par deux avec une arête et d'autres patchs sans arêtes. Considérons maintenant leurs représentations numériques. Rappelons que le noir est zéro et un est blanc, donc la boîte de gauche contient à la fois des zéros et des zéros. La boîte du milieu contient tous les zéros et la boîte de droite contient tous les zéros. Considérons maintenant un filtre deux par deux, qui est juste une matrice de nombres deux par deux. Multipliez le filtre deux par deux avec notre patch deux par deux. élément, multipliez le négatif rouge 1 par le zéro rouge. Multipliez le négatif noir 1 par le zéro noir. Multipliez les verts
et multipliez les bleus. Enfin, ajoutez-les tous ensemble et nous en obtenons deux. Faites la même chose pour l'image du milieu et nous obtenons zéro. Faites la même chose pour la bonne image et nous obtenons zéro à nouveau. C'est parfait. Notre filtre produit des valeurs positives pour les arêtes
verticales et produit zéro pour les images sans arêtes. C' est juste pour un petit patch deux par deux cependant. Considérons maintenant toute l'image. C' est maintenant la représentation numérique de notre image de diamant. Nous allons parcourir chaque patch deux par deux de l'image. À chaque patch, nous multiplions et additionnons le filtre deux par deux avec un patch deux par deux. Cela nous donne une matrice de sorties où l'on indique un bord avec le noir à gauche et le blanc à droite. Négatif 1 indique une arête dans la direction inverse. Visualisés sous forme d'image, nous avons le blanc comme bord gauche, noir comme bord droit et le gris comme pas de bord. Nous l'appelons ceci convoltant un filtre avec l'image. Cela fonctionne aussi pour les images couleur génériques. Voici un oiseau sur la gauche. Convolter l'image avec le filtre de bord nous permet d'obtenir l'image sur la droite, mettant en surbrillance les bords comme prévu. Pour le détecteur de visage d'aujourd'hui, nous utiliserons des filtres Haar ou des fonctionnalités Haar. Certaines fonctionnalités de Haar trouvent des bords comme celui que nous venons d'essayer. D' autres trouvent des lignes, mais d'autres trouvent des motifs abstraits. Il y a une multitude de filtres possibles et il y a aussi beaucoup, beaucoup de patchs dans une grande image. L' exécution de tous les filtres sur tous les correctifs est coûteuse. Rendons cela plus efficace. Nous avons besoin d'un moyen d'économiser les coûts de calcul. Pour ce faire, le détecteur de visage dans ce cours utilise une méthode appelée en cascade. Pour comprendre comment le calcul CVS en cascade, nous devons comprendre l'intuition. Regarde cette image dans la boîte rouge. Il est fondamentalement vert monotone. Il ne contient certainement pas de visage parce que tout est d'une couleur et assez ennuyeux. Sachant cela, nous pourrions exécuter un simple comme détecteur d'
abord pour trouver toutes les parties sans bordure de l'image. Convolter un filtre de bord avec l'image nous donne cette sortie. Notez que cette partie monotone de l'image encadrée en rouge sur la gauche est toute noire. Nous pouvons maintenant ignorer ces parties de l'image et mettre
au point des filtres plus tard sur les parties les plus intéressantes de l'image indiquées en vert, et c'est l'intuition. Exécutez un petit ensemble de filtres de l'image. Nous appelons cette étape 1. Déterminez les pièces intéressantes en sélectionnant les pixels avec les valeurs de sortie les plus élevées. Ensuite, exécutez l'ensemble de filtres suivant sur les parties intéressantes. Affinez quelles parties de l'image sont considérées comme intéressantes, et répétez pour l'ensemble suivant de filtres, affinant quelles parties de l'image sont à nouveau intéressantes et continuez à le faire. Tu pourrais répéter ça indéfiniment. Dans notre modèle de détection faciale aujourd'hui, le modèle utilise 38 étapes de ce type. Ces filtres en cascade nous permettent alors d'effectuer cette détection. Plus précisément, cette dernière étape des 38 étapes produira des valeurs élevées pour les visages. Dessinez une zone autour des valeurs de l'image qui dépassent un seuil, puis visualisez au-dessus de votre image d'origine, et là vous avez, une détection de visage réussie. Résumons les étapes. En résumé, nous avons discuté de la façon d'extraire des entités simples comme des arêtes à l'aide de filtres. Nous avons ensuite discuté de la façon dont ces fonctionnalités simples sont utilisées pour
trouver itérativement des parties intéressantes de l'image à l'aide d'un motif en cascade. Enfin, la cascade produit des sorties de haute valeur pour les faces. Dans l'étape finale, nous dessinons une boîte autour des sorties de haute valeur, et ces cases identifient les visages dans l'image. Pour obtenir une copie de ces diapositives et d'autres ressources, assurez-vous de consulter cette URL. Maintenant que vous savez comment fonctionnent les détecteurs de visage, terminons et finissons de coder notre échangeur de visage.
7. Échange de visage de code: Maintenant, nous avons du code pour traiter notre webcam et pour détecter les visages, nous sommes prêts à terminer l'échange de visages. À un niveau élevé, nous suivrons le même processus en deux étapes qu'avant. abord, nous allons tester l'échange de visage sur une image , puis nous allons implémenter l'échange de visage pour votre webcam. Commencez par accéder à cette URL comme j'ai sur le côté droit. Cela créera un environnement pour nous à distance, encore une fois, de sorte que nous ne voulons pas faire de configuration sur nos propres ordinateurs. Avant une nouvelle fonction, nous allons créer un nouveau fichier. Sur le côté gauche ici, si votre navigateur de fichiers s'est effondré comme le mien, allez-y et cliquez dessus pour l'agrandir. À l'extrême droite, je vais fermer mon aperçu en cliquant sur le x en haut à droite. Dans ce fichier, je vais cliquer sur detect.py, et c'est le fichier que nous voulons éditer. Allez-y et fermez le fichier en cliquant sur cette flèche gauche en haut à gauche. Dans ce fichier, nous allons créer une nouvelle fonction, échanger des visages pour contenir votre détection de visage et le code de dessin de boîte. Nous allons définir une fonction appelée swap faces au-dessus de notre code actuel. Cette fonction va prendre dans l'image et le détecteur de visage. A l'intérieur, nous allons prendre ce code à
partir du code de détection jusqu'au code de dessin de boîte. Je vais couper ça et le coller dans notre nouvelle fonction. Une fois que vous l'avez collé, vous devrez ajuster l'indentation. Pour moi, les lignes 6 à 10 doivent être indentées une fois de plus. Maintenant, nous allons jumeler les rectangles, ou en d'autres termes, les visages en groupes de deux. Laisse-moi t'expliquer comment on va faire ça. Fais semblant que la liste des rectangles ne contient que des nombres comme celui-ci. Ensuite, les rectangles de 2። 2 sélectionneront tous les autres nombres. Dans ce cas, nous aurions 0, 2, 4. Ensuite, les rectangles, 1። 2 sauteront le premier, puis sélectionneront tous les autres numéros. Dans ce cas, nous aurions 1, 3, 5. L' indexation est un sujet assez compliqué alors ne vous inquiétez pas si vous ne comprenez pas complètement cela, sachez
simplement que c'est conceptuellement ce qui se passe. Enfin, zip recueillera le premier élément des deux listes. Dans ce cas, 0,1 alors il recueillera le deuxième élément des deux listes, dans ce cas, 2,3. Enfin, le troisième élément des deux listes faisant 4,5. Tout cela pour dire que l'expression compliquée, les rectangles
zip avec un tas de colonnes et de chiffres, sélectionnez tous les deux rectangles ou tous les deux faces. Cordons ça maintenant. Dans votre code à gauche, nous allons changer cette boucle pour que nous ayons pour rectangle1,
rectangle2 dans zip, puis l'expression que nous avions avant les rectangles 1። 2, et la virgule. Je vais appuyer sur Entrée et ici je vais écrire, passer et supprimer notre code de dessin original. Extrayons maintenant les deux faces de l'image. Nous allons commencer par définir une fonction d'aide. Sous les faces d'échange, nous allons définir le sélecteur de visage. Cette fonction, avec un rectangle,
retournera un masque pour que nous sélectionnions le visage. abord, nous allons détruire le rectangle en quatre valeurs, comme nous l'avons fait avant. Ici retournera alors un objet de tranche. Un objet de tranche vous permet de sélectionner une partie de la liste. Dans ce cas, deux tranches vous permettent de sélectionner une partie d'un tableau 2D ou, en d'autres termes, une partie de l'image. Ici, nous allons retourner deux objets de tranche. Le premier objet tranche le long de la première dimension ou de l'axe y de y à y plus h. Le second objet tranche le long la deuxième dimension ou de l'axe x de x à x plus la largeur. Maintenant, nous allons utiliser cette fonction get face sélecteur, ci-dessus, en utilisant notre nouvelle fonction d'aide, convertir le premier rectangle en un masque facial à l'intérieur de notre boucle for-. Ici, nous allons écrire mask1 est égal à obtenir le sélecteur de visage rectangle1. Répétez la même chose pour le deuxième rectangle. Maintenant, utilisez les masques pour sélectionner les deux faces de l'image. Face1 est égal à l'image du masque1 et face2 est égal à l'image du masque2. Maintenant, comme les deux visages peuvent être de tailles différentes, nous devons redimensionner chaque face pour s'adapter à l'autre. Voici conceptuellement comment nous allons le faire. Disons que nous essayons d'adapter la boîte verte à l'intérieur de la boîte bleue, remarquez que la hauteur bleue est inférieure à la hauteur verte. Puisque la boîte verte est plus grande, nous allons la raccourcir afin que les hauteurs des deux boîtes soient les mêmes. Dans ce cas, le rapport entre la hauteur bleue et la hauteur verte nous indique combien nous devions rétrécir au rectangle vert. Dites maintenant que la boîte verte est plus large que la boîte bleue, remarquez que la largeur bleue est inférieure à la largeur verte. Nous allons le rétrécir pour que les largeurs des deux rectangles soient les mêmes. Dans ce cas, le rapport entre la largeur bleue et la largeur verte nous indique combien nous avions besoin pour réduire le rectangle vert. Nous ne savons pas vraiment si le rectangle est trop grand ou trop large donc nous prenons le minimum des deux ratios pour être sûr. Cela garantit que le rectangle vert a suffisamment rétréci, qu'il soit trop grand ou trop large, pour s'adapter à l'intérieur du rectangle bleu. Cordons maintenant ça. Tout comme avant que nous allons commencer par définir une fonction d'aide sous obtenir le sélecteur de visage à trouver, redimensionner pour s'adapter. Cette fonction prendra en deux faces, face1 et face2. abord, détruisez la forme du visage pour obtenir la largeur et la hauteur du visage. Nous allons taper face1_height, face1_width, soulignement est que vous avez à face1.shape. Le visage a en fait trois dimensions pour sa forme. Si vous vous souvenez de notre leçon précédente, toutes les images sont h par w par 3. Nous n'avons pas besoin de cette dernière dimension, donc nous utilisons un trait de soulignement. Le soulignement est une convention pour ignorer cette variable. Nous allons aussi répéter cela avec la deuxième face, face2_h, face2_w est égal à face2.shape. Calculez ensuite la quantité requise pour réduire la première face à tenir dans la seconde face. C' est le facteur que nous avons mentionné précédemment. Le facteur est égal au minimum entre la hauteur face2 divisée par la hauteur face1, puis la largeur face2 divisée par la largeur face1. Enfin, nous allons redimensionner face1. Ici, la fonction de redimensionnement que nous allons prendre dans la première face et le deuxième argument est si nécessaire argument bien que nous n'utiliserons pas donc pass in none pour l'instant. Ensuite, nous allons taper le facteur à mettre à l'échelle sur la cote x, puis le facteur à mettre à l'échelle sur la dimension y. Enfin, renvoyez ceci. Maintenant, nous allons utiliser la méthode d'aide, redimensionner pour ajuster, pour redimensionner les deux faces pour s'adapter à l'autre. Commencez avec face1 ci-dessus dans la boucle for-va taper redimensionne1 est égal à redimensionner pour s'adapter à face1, face2. Faites de même pour l'autre face resize2 est égal à redimensionner pour adapter face2 à face1. Maintenant, nous allons réellement coller chaque visage sur l'autre. Conceptuellement va simplement coller le rectangle vert sur le rectangle bleu. Encore une fois, nous allons commencer par la méthode d'aide. Je vais faire défiler vers le bas et redimensionner en dessous pour l'adapter, nous allons définir, assurez-vous de revenir en arrière afin que vous commenciez une nouvelle fonction à l'extérieur, nous allons définir appliquer, qui prend la face redimensionnée et le visage pour la coller. Détruisez la forme de la face dans sa hauteur et sa largeur redimensionnées1 hauteur, redimensionnée1 largeur et soulignement pour ignorer que la troisième dimension est égale à resize1.shape, puis collez la face sur face2. Ici face2, nous allons maintenant coller la face redimensionnée sur face2. Enfin, retournez la deuxième face. Encore une fois, l'indexation est un sujet assez compliqué, donc si vous ne comprenez pas ce que signifie cette ligne, ne vous inquiétez pas. Pour l'instant, vous avez juste besoin de savoir que c'est ainsi qu'il a collé le visage redimensionné sur la deuxième face. Faire défiler jusqu'à la boucle for-que nous allons maintenant utiliser appliquer, pour appliquer chaque face. Collez la face2 redimensionnée sur face1. Mask1 est égal à appliquer resized2 face1. Répétez la même chose pour l'autre image de visage mask2 est égal à appliquer redimensionné1 face2. Pour la dernière étape, nous allons effectivement appliquer notre
fonction de faces d'échange à notre image et au détecteur de visage correspondant, faites défiler jusqu'au bas de votre fichier après avoir instancié votre détecteur et lisez votre image dans. Nous allons maintenant appeler les visages d'échange sur l'image et le détecteur de visage. Maintenant, nous avons fini avec le script. Cliquez sur le navigateur de fichiers à gauche, cliquez sur Outils, puis sur Terminal. Attendez une configuration. Une fois l'installation terminée, tapez Python detect.py. Cela exécutera votre code d'échange de visage. Après avoir exécuté ce script, récupérez out.JPEG sur le côté gauche. On dirait que l'image n'a pas changé peut-être, eh bien, regardez de plus près. Les visages des enfants sont en fait échangés. C' est plus évident lorsque je passe entre l'image originale et l'image échangée. Voici l'image originale et voici l'image échangée. Appliquons maintenant l'échange de visage à notre webcam. Commencez par accéder à cette URL. Une fois cette page chargée, je vais cliquer sur Fermer dans l'aperçu sur le côté droit, je recommande de faire de même pour créer plus d'espace. Sur le côté gauche, je vais fermer le navigateur de fichiers en cliquant sur la flèche en haut à gauche. Pour commencer, copions toutes les fonctions d'aide que nous avons écrites dans la dernière étape. Je vais les coller juste au-dessus de notre instanciation de détecteur de visage. Ici, je vais les coller. Notez que peu importe où vous collez ces fonctions. Si vous voulez coller exactement au même endroit,
je l' ai collé après mes importations, mais avant que le détecteur de visage ne soit instancié. Définissons maintenant une nouvelle transformation pour notre application web à appliquer au flux en direct de la webcam. faisant défiler vers le bas après toutes nos fonctions existantes, je vais créer une nouvelle transformation. Comme dans une leçon précédente, nous utiliserons le décorateur de CV ouvert sur app.transform. Nous allons donner à cette transformation un nom de swap de visage et nous allons également faire cette nouvelle transformation la valeur par défaut en tapant par défaut égal à true. Je vais supprimer cette valeur par défaut égale à true ci-dessous car nous ne pouvons pas avoir deux transformations par défaut. Nous allons maintenant définir une fonction d'échange de face qui prend à la fois l'image et le cadre, puis appeler la méthode d'assistance de swap faces que vous avez écrite dans la dernière section. Tapez les faces d'échange et transmettez à la fois l'image et le détecteur de visage et renvoyez l'image. Enfin, c'est tout. Cliquez sur Afficher en haut à gauche. Pour moi, il semble avoir une icône de lunettes de soleil. Ensuite, sélectionnez dans une nouvelle fenêtre, cela ouvre un aperçu de votre application Web. Je vais zoomer afin que vous puissiez voir ce qui se passe, puis cliquez sur Démarrer. Dans ce cas, je suis en train de me changer avec une photo de moi-même prise dans le passé. Assurez-vous de cliquer sur Démarrer, puis sur Autoriser. Cela conclut notre échange de visage. Vous pouvez maintenant partager cet échange de visage avec vos amis et votre famille. Faites des visages drôles, partagez tant de photos et amusez-vous avec votre propre application de swap de visage. Bon travail pour compléter cette leçon, c'était une longue. Pour obtenir une copie de ces diapositives, le code fini et d'autres ressources, assurez-vous de récupérer cette URL. Consultez la leçon suivante pour connaître les prochaines étapes pour en savoir plus sur la vision par ordinateur.
8. Les prochaines étapes: Félicitations. Tu as fini ton chef-d'œuvre d'échange de visage. Nous avons abordé la façon dont les images sont représentées, comment extraire le sens des images, des modèles de détection de
visage, et plus encore. Si cela a retenu votre intérêt pour l'apprentissage automatique et la vision par ordinateur, suivez-moi sur Skillshare pour être averti lors du lancement de la prochaine classe. Si vous êtes également intéressé par les sujets de science des données, consultez mon cours Data Science 101 ,
le jeu avec les données ou la classe SQL 101 pour interroger et concevoir des bases de données. Merci de vous joindre à moi pour ce cours d'échange de visage. Félicitations une fois de plus faire jusqu'à la fin du cours et jusqu'à la prochaine fois.