#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.