Reconocimiento facial con Delphi Tokyo 10.2.2

Hace unos días me pidieron que hiciese un programa de reconocimiento facial para identificar a los alumnos de una escuela.
Dándole vueltas al tema me di cuenta que tenía que dividirlo en dos partes, la primera sería la extracción de la cara del alumno de la imagen inicial eliminando el fondo y detalles innecesarios y la segunda la del tratamiento de esa imagen para identificar al alumno en cuestión utilizando técnicas de inteligencia artificial.
Inicialmente pensé en utilizar OpenCV (aquí tienen cómo instalarlo), pero por más intentos que hice  no conseguí que funcionase en mi equipo, me decía que no encontraba unas dlls, o que "no era una aplicación win32 válida", así que investigando en Google encontré que Android tiene incorporado un objeto llamado JFaceDetector para hacer reconocimiento facial, que lo podemos utilizar desde la unit Androidapi.JNI.Media.
Para utilizarlo se hace de la siguiente forma:
Desde nuestro Delphi Tokyo 10.2.2 accedo a File - Multi-Device Application y creo un nuevo proyecto.
En Tipo de proyecto seleccionamos Android


Desde la paleta de herramientas "Tool Palette" voy arrastrando hacia el form 3 objetos:  tButton, tLabel, tImage.


En el objeto tImage cargo una imagen de prueba (se hace clic sobre el componente tImage y desde Object Inspector, selecciono la propiedad Multiresbitmap)

para conseguir que quede de la siguiente forma:

En el componente Label1 mostraremos el número de caras que ha detectado el programa.
y dentro del tbutton en el evento Onclic colocaremos el siguiente código:
procedure TForm12.Button1Click(Sender: TObject);
var
  LDetector: JFaceDetector;
  LFaces: TJavaObjectArray;
  LFace: JFaceDetector_Face;
  LSurface: TBitmapSurface;
  LBitmap: JBitmap;
  LMidpoint: JPointF;
  LFaceCount, I: Integer;
  LRect: TRectF;
  LHalfWidth: Single;

begin

  LSurface := TBitmapSurface.Create;
  try
    LSurface.Assign(FaceImage.Bitmap);
    LBitmap := TJBitmap.JavaClass.createBitmap(LSurface.Width, LSurface.Height,
      TJBitmap_Config.JavaClass.ARGB_8888);
    SurfaceToJBitmap(LSurface, LBitmap);
    LMidpoint := TJPointF.Create;
    LFaces := TJavaObjectArray.Create(10);
    LDetector := TJFaceDetector.JavaClass.init(LBitmap.getWidth,
      LBitmap.getHeight, 10);
    LFaceCount := LDetector.findFaces
      (LBitmap.copy(TJBitmap_Config.JavaClass.RGB_565, False), LFaces);
    Label1.Text := LFaceCount.ToString + 'caras';
    for I := 0 to LFaceCount - 1 do
    begin
      LFace := LFaces.Items[I];
      LFace.getMidPoint(LMidpoint);
      LHalfWidth := LFace.eyesDistance * 2;
      LRect := RectF(LMidpoint.x - LHalfWidth, LMidpoint.y - LHalfWidth,
        LMidpoint.x + LHalfWidth, LMidpoint.y + LHalfWidth);
      FaceImage.Bitmap.Canvas.BeginScene;
      try
        FaceImage.Bitmap.Canvas.Stroke.Color := TAlphaColorRec.Red;
        FaceImage.Bitmap.Canvas.Stroke.Thickness := 2;
        FaceImage.Bitmap.Canvas.DrawRect(LRect,0,0,allcorners, 100);
      finally
        FaceImage.Bitmap.Canvas.EndScene;
      end;
    end;
  finally
    LSurface.Free;
  end;
end;



y a continuación ejecutamos el código y veremos cómo nos ha creado un rectángulo rodeando los rostros que ha detectado:




En un próximo post publicaré cómo utilizar redes neuronales para la identificación de imágenes.
Además me gustaría recordarles que si quieren iniciarse en la programación con Delphi pueden utilizar una versión gratuita para siempre llamada Delphi Starter Edition que la pueden descargar desde aquí o también pueden descargar la edición de prueba por 30 días totalmente funcional desde aquí.
Si les ha gustado y quieren compartir el post, pueden pulsar los iconos de twitter, facebook, google+ que tienen un poco más abajo


Javier Pareja
blogdelphimagic@blogspot.com




También les puede interesar: