Eye4Eye – face detect and recognition on frame video [Microsoft Azure]

 

Eye4Eye – face detect and recognition on frame video [Microsoft Azure]

Ok a questa bellissima equazione, togliamo le cazzate. Quindi non esiste che hackeri qualsiasi dispositivo con telecamera, e non esiste che per tutti i flussi video (anche stesso riuscissi a farlo) potrebbero essere analizzati frame per frame per l’identificazione “certa” della persona nei pochi secondi necessari come nel video. Quindi, tolte le minchiate andiamo al sodo.

Per effettuare un analisi del frame video “ovvero detect” dei volti mi sono basato su Microsoft cognitive. che cos’è? vi invito a leggere questa pagina:

https://azure.microsoft.com/it-it/services/cognitive-services/

In questo agglomerato di tool messo a disposizione da Microsoft sussistono diverse possibilità, ma quella che a noi interessa per questo software è:

Detect one or more human faces in an image and get back face rectangles for where in the image the faces are, along with face attributes which contain machine learning-based predictions of facial features. The face attribute features available are: Age, Emotion, Gender, Pose, Smile, and Facial Hair along with 27 landmarks for each face in the image.

Avete ben capito; Grazie alla gestione delle API messe a disposizione da Azure e con un pò di dimestichezza in C# (ma volendo anche python) abbiamo ottenuto un risultato simpatico (che alla lontana tenderà ad assomigliare all’eye of god).

Alla base di questo progetto, ho dovuto scompattare in applicativo C# un flusso video derivante da webcam (così da rendere più facile i test) in frame, ed ho analizzato frame per frame inviando le immagini a microsoft (tramite API) restituendomi in json le informazioni che mi servivano per arricchire l’immagine.

Dunque ricapitolando abbiamo inserito la prima fase, ovvero il Detect ( quindi la facoltà di identificare nell’immagine un volto (già cosa non sempre semplice) ed eventualmente da questa analizzare le informazioni che l’intelligenza artificiale di microsoft ci rileva come emozioni, anni, occhiali, sorriso, capelli etc… Noi in questa fase di progetto dobbiamo semplicemente analizzare il volto trovandolo prima, ed estrando le caratteristiche dopo..

Apriamo Visual Studio e creiamo un nuovo progetto, sbizzarendoci sulla sistemazione dei box ovunque vogliamo.

L’importante è fare l’import su nuget di: 

Vi sottolineo, essenziali per il progetto Aforge ( analizza i flussi video ) e Newtonsoft.json (ci aiuterà a deserializzare le risposte in json).

VideoCaptureDeviceForm form = new VideoCaptureDeviceForm();       
if (form.ShowDialog(this) == DialogResult.OK)
   { OpenVideoSource(form);}

  private void OpenVideoSource(VideoCaptureDeviceForm form)
  {
   videoSource = form.VideoDevice;
   videoSource.NewFrame += new NewFrameEventHandler(video_NewFrame);
   videoSource.Start();
   }

  private void video_NewFrame(object sender, NewFrameEventArgs eventArgs)
        {
            // get new frame
            Bitmap bitmap = eventArgs.Frame;
            MemoryStream ms = new MemoryStream();
            bitmap.Save(ms,System.Drawing.Imaging.ImageFormat.Jpeg);
            this.Invoke((MethodInvoker)delegate ()
            {   pictureBox1.Image = bitmap;
                MakeRequest(ms.ToArray());
            });
            //questo tempo di attesa è necessario per ricevere la  //risposta da microsoft dell'elaborazione
            attendi(3000);
        }
 public void attendi(int tempo) { try { Thread.Sleep(tempo); } catch (ThreadInterruptedException e) { e.StackTrace.ToString(); } }

La funzione MakeRequest ci restituirà il necessario per poter produrre il risultato finale:

 public async void MakeRequest(byte[] byteData)
        {
            var client = new HttpClient();
            var queryString = HttpUtility.ParseQueryString(string.Empty);

            // Request headers
            client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "chiave API ricevuta da azure");

            // Request parameters
            queryString["returnFaceId"] = "true";
            queryString["returnFaceLandmarks"] = "false";
            queryString["returnFaceAttributes"] = "age,gender,emotion,smile,glasses";
            queryString["recognitionModel"] = "recognition_02";
            queryString["returnRecognitionModel"] = "false";
            var uri = "https://westeurope.api.cognitive.microsoft.com/face/v1.0/detect?" + queryString;

            HttpResponseMessage response;

            using (ByteArrayContent content = new ByteArrayContent(byteData))
            {
                if (response.IsSuccessStatusCode)
                {
                    var json = response.Content.ReadAsStringAsync().Result;
                    dynamic account = JsonConvert.DeserializeObject(json);

                    if (response.Content.ReadAsStringAsync().Result.CompareTo("[]") != 0)
                    {
                        this.Invoke((MethodInvoker)delegate ()
                        {

                            richTextBox1.Text += "" + account[0].faceId + "\n";

                            richTextBox1.Text += "Anni: " + account[0].faceAttributes.age + "\n";
                            richTextBox1.Text += "Sesso: " + account[0].faceAttributes.gender + "\n";
                            //richTextBox1.Text += "Emozioni:" +  + "\n";

                            ArrayList emozioni = new ArrayList();
                            emozioni.Add(Convert.ToDouble(account[0].faceAttributes.emotion.ager));
                            emozioni.Add(Convert.ToDouble(account[0].faceAttributes.emotion.contempt));
                            emozioni.Add(Convert.ToDouble(account[0].faceAttributes.emotion.disgust));
                            emozioni.Add(Convert.ToDouble(account[0].faceAttributes.emotion.fear));
                            emozioni.Add(Convert.ToDouble(account[0].faceAttributes.emotion.happiness));
                            emozioni.Add(Convert.ToDouble(account[0].faceAttributes.emotion.neutral));
                            emozioni.Add(Convert.ToDouble(account[0].faceAttributes.emotion.sadness));
                            emozioni.Add(Convert.ToDouble(account[0].faceAttributes.emotion.surprise));


                            for (int i = 0; i < emozioni.Count; i++)
                            {
                                if (Convert.ToDouble(emozioni[i].ToString()) > 0.0)
                                {
                                    switch (i)
                                    {
                                        case 0:
                                            richTextBox1.Text += "Emozioni: Rabbia "+ Convert.ToDouble(emozioni[i].ToString()) + "\n";
                                            break;
                                        case 1:
                                            richTextBox1.Text += "Emozioni: Disprezzo " + Convert.ToDouble(emozioni[i].ToString()) + "\n";
                                            break;
                                        case 2:
                                            richTextBox1.Text += "Emozioni: Disgusto " + Convert.ToDouble(emozioni[i].ToString()) + "\n";
                                            break;
                                        case 3:
                                            richTextBox1.Text += "Emozioni: Paura " + Convert.ToDouble(emozioni[i].ToString()) + "\n";
                                            break;
                                        case 4:
                                            richTextBox1.Text += "Emozioni: Felicità " + Convert.ToDouble(emozioni[i].ToString()) + "\n";
                                            break;
                                        case 5:
                                            richTextBox1.Text += "Emozioni: Neutrale " + Convert.ToDouble(emozioni[i].ToString()) + "\n";
                                            break;
                                        case 6:
                                            richTextBox1.Text += "Emozioni: Disprezzo " + Convert.ToDouble(emozioni[i].ToString()) + "\n";
                                            break;
                                        case 7:
                                            richTextBox1.Text += "Emozioni: Sorpresa " + Convert.ToDouble(emozioni[i].ToString()) + "\n";
                                            break;
                                    }
                                }
                            }

                            if (Convert.ToInt16(account[0].faceAttributes.smile) != 0)
                                richTextBox1.Text += "Sorride\n";
                            else
                                richTextBox1.Text += "Non sorride\n";

                            richTextBox1.Text += "<_______________________>\n";

                         //   richTextBox1.Text += "Occhiali?" + account[0].faceAttributes.glasses + "\n";

                            //  richTextBox1.Text += "" + account[0].faceRectangle + "\n";

                        });

                        int top = Convert.ToInt16(account[0].faceRectangle.top);
                        int left = Convert.ToInt16(account[0].faceRectangle.left);
                        int width = Convert.ToInt16(account[0].faceRectangle.width);
                        int height = Convert.ToInt16(account[0].faceRectangle.height);

                        Graphics g = pictureBox1.CreateGraphics();

                        Rectangle ee = new Rectangle(left, top, width, height);
                        using (Pen pen = new Pen(Color.Red, 2))
                        {
                            g.DrawRectangle(pen, ee);
                        }

                        using (Font myFont = new Font("Times", 14))
                        {
                            g.DrawString("" + account[0].faceAttributes.age, myFont, Brushes.Green, left, top);
                        }
                    }
                }
            }
       }

Inserite le funzioni di base descritte sopra, il risultato sarà il seguente:

Come noterete comunque (al di là del ritaglio), è stato riconosciuto il frame con il volto e quindi il voltodisegnandone il rettangolo rosso. All’interno del rettangolo sussite l’età che secondo Microsoft il volto dovrebbe avere, ed in linea con la realtà dato che è esatta!

Sicuramente il software avrà degli aggiornamenti e questi verranno inseriti su github (come sempre). Attualmente il progetto è privato.

Se avete dubbi o vi servono altre parti di codice, non esitate a contattarmi.

A presto.

Commenti

Post più popolari