Алгоритмы обнаружения мигания глаз

#android #delphi #firemonkey

Вопрос:

Я реализовал распознавание лиц в своем приложении, используя это руководство. И я хочу добавить к этому обнаружение мигания глаз прямо сейчас. к сожалению, в детекторе лиц нет подробных свойств о мигании глаз в Android. Решение, о котором я думал, таково : подсчитайте процент черного цвета (радужной оболочки) в обоих глазах Rects , нарисованных в коробке с красками, если это возможно, больше черного цвета означает, что глаз открыт, а меньше черного цвета означает, что глаз закрыт. Я не уверен, как это реализовать. Поскольку я не знаю способа получить параметры цвета из Paintbox.

вот код, если рисовать :

 procedure TCameraView.PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
  var
    SrcRect, DstRect, Rect: TRectF;
    Scale, DstWidth, DstHeight: Single;
    Face: TgoFace;

    procedure PaintEye(const APosition: TPointF; const AColor: TAlphaColor);
    var
      P: TPointF;
      R: TRectF;
      Radius: Single;
    begin
    try
      { Exit if eye position is not available }
      if (APosition.X = 0) and (APosition.Y = 0) then
        Exit;

      P.X := APosition.X * Scale;
      P.Y := APosition.Y * Scale;
      P.Offset(DstRect.TopLeft);

      Radius := Face.EyesDistance * Scale * 0.2;
      R := RectF(P.X - Radius, P.Y - Radius, P.X   Radius, P.Y   Radius);
      Canvas.Stroke.Color := AColor;
      Canvas.DrawEllipse(R, 1);
      Except on E  :Exception do
      begin
    // ShowMessage(e.Message);
      end;
      end;
    end;

  begin
  try
    { Paint bitmap to fit the paint box while preserving aspect ratio. }
    SrcRect := RectF(0, 0, FBitmap.Width, FBitmap.Height);
    Scale := Min(PaintBox1.Width / FBitmap.Width, PaintBox1.Height / FBitmap.Height);
    DstWidth := Round(FBitmap.Width * Scale);
    DstHeight := Round(FBitmap.Height * Scale);
    DstRect.Left := Floor(0.5 * (PaintBox1.Width - DstWidth));
    DstRect.Top := Floor(0.5 * (PaintBox1.Height - DstHeight));
    DstRect.Width := DstWidth;
    DstRect.Height := DstHeight;
    Canvas.DrawBitmap(FBitmap, SrcRect, DstRect, 1);

    Canvas.Stroke.Kind := TBrushKind.Solid;
    Canvas.Stroke.Thickness := 2;

    { Paint each face with its features }
    for Face in FFaces do
    begin
      { Paint bounds around entire face }
      Rect := Face.Bounds;
      Rect.Left := Floor(Rect.Left * Scale);
      Rect.Top := Floor(Rect.Top * Scale);
      Rect.Right := Ceil(Rect.Right * Scale);
      Rect.Bottom := Ceil(Rect.Bottom * Scale);
      Rect.Offset(DstRect.TopLeft);

      Canvas.Stroke.Color := TAlphaColors.Lime;
      Canvas.DrawRect(Rect, 4, 4, AllCorners, 1);

      { Paint the eyes }
      PaintEye(Face.LeftEyePosition, TAlphaColors.Magenta);
      PaintEye(Face.RightEyePosition, TAlphaColors.Cyan);
    end;
     Except on E  :Exception do
      begin
     // ShowMessagE(E.message);
      end;
      end;
  end;
 

Комментарии:

1. Немного не по теме, но все же: вы должны удалить свои try..except блоки. Даже без них вы получите уведомление об ошибке, поэтому вам не нужно, чтобы эти блоки были уведомлены. Однако эти блоки не только не нужны: они также вредны, поскольку они заставляют выполнение продолжаться после исключения.

2. Попытка обнаружить закрытые / открытые глаза может быть затруднена, так как частота кадров камеры может быть даже недостаточно быстрой, чтобы уловить ее, или могут возникнуть проблемы с размытием при движении. Почему бы вместо этого не попытаться обнаружить быстрые изменения в изображении, локализованном вокруг положения глаз. Высокая скорость изменений в этих областях, а не в окружающих областях, указывает на мигание. Это также можно сделать без информации о цвете. Ваше предложение также может не сработать для людей с темной кожей.

3. Спасибо вам за совет, нелегко обнаружить быстрые изменения в изображении, я даже не знаю, с чего начать. @XylemFlow

4. В каждом кадре сохраняйте растровые изображения для каждого глаза, центрированные в положениях глаз, с заданной шириной и высотой ожидаемого размера области вокруг глаз. Затем сравните их с тем же набором изображений из предыдущего кадра, взяв абсолютную разницу в каждом пикселе. Любые большие значения в результирующей разнице указывают на высокую скорость изменения. Если вы получаете высокие значения сразу в обоих глазах, то вы обнаруживаете мигание. В Delphi FMX вы можете получить быстрый доступ к данным пикселей с помощью TBitmapData.