J'ai été surpris quand j'ai envoyé des autorisations de visage depuis iPad avec udp et que je les ai relayées, reçues et affichées avec Python!

J'ai été surpris quand j'ai envoyé des autorisations de visage depuis iPad avec udp et que je les ai relayées, reçues et affichées avec Python!

Ce qui m'a surpris, c'est que je pouvais obtenir les résultats que je voulais avec un code court. La figure ci-dessous montre l'écran (vidéo en temps réel) qui a généré 68 données de repère du visage de dlib avec l'application iPad, les a relayées sur le serveur via Internet et les a affichées sur mac. Le code Python pour cet affichage est [Code] 1] Comme indiqué, il n'y a qu'environ 30 lignes. C'est évident pour les pythonistes, mais c'est incroyable pour les débutants. J'ai senti que c'était le plus fort pour les idées de prototypage.

2020-08-22 11.45のイメージ.jpeg

Envoyer un visage disponible sur iPad via udp

Le côté qui crée les données de repères du visage à partir de l'image du visage de la caméra et l'envoie avec udp, J'ai utilisé le projet git Xcode suivant. (Pour git du même auteur, version Android, Il existe également une version Javascript. )

https://github.com/Tastenkunst/brfv4_ios_examples

Modifiez track_single_face.hpp comme suit.

addr.sin_port = htons(5000); addr.sin_addr.s_addr = inet_addr("XXX.XX.XXX.XXX");

Numéro de port 5000 et L'adresse IP de «XXX.XX.XXX.XXX» correspond à vos paramètres. Lorsque vous créez et lancez un projet Xcode et que vous prenez une photo de votre visage, il enverra les données de position de 68 points de repère de visage au serveur sous forme de 68x2 octets de données.

track_single_face.hpp



#ifndef __brf__cpp__BRFCppExample_hpp
#define __brf__cpp__BRFCppExample_hpp

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

namespace brf {



class BRFCppExample: public BRFBasicCppExample {
    
    int sock;
    struct sockaddr_in addr;
    uint16_t shorts;
    uint8_t  bytes[sizeof(uint8_t)*136*2];

public: BRFCppExample() : BRFBasicCppExample()
{
  
    addr.sin_family = AF_INET;
    addr.sin_port = htons(5000);
    addr.sin_addr.s_addr = inet_addr("XXX.XX.XXX.XXX");
    //sock = socket(AF_INET, SOCK_DGRAM, 0);
}

public: void initCurrentExample(brf::BRFManager& brfManager, brf::Rectangle& resolution) {

	brf::trace("BRFv4 - basic - face tracking - track single face" + brf::to_string("\n")+
		"Detect and track one face and draw the 68 facial landmarks.");
}

public: void updateCurrentExample(brf::BRFManager& brfManager, brf::DrawingUtils& draw) {

	// In a webcam example imageData is the mirrored webcam video feed.
	// In an image example imageData is the (not mirrored) image content.

	brfManager.update();

	// Drawing the results:

	draw.clear();

	// Face detection results: a rough rectangle used to start the face tracking.

	//draw.drawRects(brfManager.getAllDetectedFaces(),    false, 1.0, 0x00a1ff, 0.5);
	//draw.drawRects(brfManager.getMergedDetectedFaces(), false, 2.0, 0xffd200, 1.0);

	// Get all faces. The default setup only tracks one face.

	std::vector< std::shared_ptr<brf::BRFFace> >& faces = brfManager.getFaces();

	for(size_t i = 0; i < faces.size(); i++) {

		brf::BRFFace& face = *faces[i];

		if(		face.state == brf::BRFState::FACE_TRACKING_START ||
				face.state == brf::BRFState::FACE_TRACKING) {

            sock = socket(AF_INET, SOCK_DGRAM, 0);
            for(int i = 0; i < 136; i++){
                shorts = (int)face.vertices[i];
                bytes[i * 2] = (uint8_t) (shorts & 0xFF);
                bytes[(i * 2) + 1] = (uint8_t) (shorts >> 8);
            }
        
            sendto(sock, bytes, sizeof(bytes), 0, (struct sockaddr *)&addr, sizeof(addr));
            close(sock);
			//draw.drawTriangles(	face.vertices, face.triangles, false, 1.0, 0x00a0ff, 0.4);
			draw.drawVertices(	face.vertices, 2.0, false, 0x00a0ff, 0.4);
           
		}
	}
}

};

}
#endif // __brf__cpp__BRFCppExample_hpp

Du côté serveur

Vient ensuite le côté serveur. C'est un code qui envoie uniquement les données de repère du côté LAN. Le numéro de port et l'adresse IP sont adaptés à votre environnement. L'écriture en Python facilite l'écriture côté serveur.

sendBak.py


import socket
import time

print (time.ctime(),flush=True)

host = '192.168.10.101'
port =  5001
bufsize = 512
portFace = 5000

sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
#sock.settimeout(0.01)
sock.bind((host,port))
#
sock2 = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
sock2.settimeout(30.0)
sock2.bind((host,portFace))

while True:
    global data, addr
    string,addr = sock.recvfrom(bufsize)
    print("from:",addr,time.ctime())
    while True:
        try:     
            data, (host, port) = sock2.recvfrom(bufsize)
            result = sock.sendto(data,addr)
            #if result  != 272:
            #     print(result) 
        except socket.error as e:
            #print ('Error: %s' % e)
            break



Version OpenCV [Code 1]

Enfin, le côté réception. Peu importe si Python fonctionne sur Mac, Windows ou Linux. Vous pouvez également utiliser Pythoinista sur iOS.

FaceLineOpenCV.py



import cv2
import socket
import numpy as np
from struct import unpack
from datetime import datetime

host = 'XXXX.com'
port =  5001
message = b'hello'

if __name__ == "__main__" :
    server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    #server.bind(('192.168.2.100', 5000))
    width = 600
    height = 800
    img = np.zeros((height, width, 3), np.uint8)
    server.sendto(message, (host, port))
    
    while True:
       
        data, addr = server.recvfrom(1024)
        cv2.rectangle(img, (0, 0), (600, 700), color=(255, 0, 0), thickness=-1)
        val = unpack('<'+'H'*(len(data)//2), data)
        j = 0
        for i in range(64):
            cv2.circle(img, (int(val[j]), int(val[j+1])), 4, (255, 255, 256), -1)
            j = j + 2

        cv2.imshow('camera capture', img)
        k = cv2.waitKey(1) #
        if k == 27:
            break

    cv2.destroyAllWindows()

Ce qui précède est la version OpenCV, mais cela fonctionne également avec PyQt comme indiqué ci-dessous.

FaceLineQt.py


import sys

from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import QTimer
import socket
import numpy as np
from struct import unpack


host = 'XXXX.com'
port =  5001
bufsize = 512
message = b'hello'


class Widget(QWidget):

    def __init__(self, parent=None):

        super(Widget, self).__init__(parent)
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.update)
        self.timer.start(20)#mise à jour
        #
        self.server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        #self.server.settimeout(0.5)
        #self.server.setblocking(False)
        #self.img = np.zeros((height, width, 3), np.uint8)
        self.server.sendto(message, (host, port))

    def paintEvent(self, event):

        
  
        data, addr = self.server.recvfrom(bufsize)
        val = unpack('<'+'H'*(len(data)//2), data)

        painter = QPainter(self)
        painter.setPen(Qt.red)
        painter.setBrush(Qt.red)
        j = 0
        for i in range(68):
                painter.drawRect(int(val[j]), int(val[j+1]), 5, 5)
                j = j + 2
        
      
def main():

    app = QApplication(sys.argv)
    w = Widget()
    w.show()
    w.raise_()
    app.exec_()


if __name__ == '__main__':

    main()

J'ajouterai une description de code plus tard.

Ajout de la version Pythonista. Pour Pythonista, utilisez une scène rapide.

FalceLinePythonista.py



from scene import *
import socket
import numpy as np
from struct import unpack

host = 'XXXX.com'
port =  5001
bufsize = 512

class FaceLine (Scene):
	def setup(self):
		
		self.landmarks = []
		for i in range(68):
				shape = ShapeNode(ui.Path.oval(0,0,5,5), 'white')
				self.landmarks.append(shape)
				self.add_child(shape)
				
		self.server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
		#
		message = b'hello'
		self.server.sendto(message, (host, port))
		
	def update(self):	
		#
		data, addr = self.server.recvfrom(bufsize)
		val = unpack('<'+'H'*(len(data)//2), data)
		dtx = np.array(val[::2])
		dty = np.array(val[1::2])
		
		for i in range(68):
				self.landmarks[i].position = (dtx[i]+200,800-dty[i])
			

run(FaceLine())


Recommended Posts

J'ai été surpris quand j'ai envoyé des autorisations de visage depuis iPad avec udp et que je les ai relayées, reçues et affichées avec Python!
J'ai défini des variables d'environnement dans Docker et je les ai affichées en Python.
Quand j'essaye matplotlib en Python, il dit 'cairo.Context'
Python: peut être répété en lambda
Quand j'ai essayé d'installer PIL et matplotlib dans un environnement virtualenv, j'en étais accro.
J'ai été surpris de recevoir une belle critique lorsque j'ai écrit Python à CheckIO et son explication
[Python] J'ai installé le jeu depuis pip et j'ai essayé de jouer
J'étais accro aux variables de classe et aux variables d'instance erronées en Python
Lorsque j'ai essayé d'exécuter Python, j'ai été ignoré dans le Microsoft Store
J'ai créé un bot Discord en Python qui se traduit quand il réagit
Utilisez Python de Java avec Jython. J'étais aussi accro.
Le nom du fichier était mauvais en Python et j'étais accro à l'importation