Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Gráficos (https://www.clubdelphi.com/foros/forumdisplay.php?f=8)
-   -   Buscar imagen en el escritorio u otra imagen mayor (https://www.clubdelphi.com/foros/showthread.php?t=86881)

ElDuc 17-10-2014 12:08:43

Buscar imagen en el escritorio u otra imagen mayor
 
Buenas, señores, vuelvo a estar por aquí.

Ante todo les diré que trabajo con Delphi 10 bajo Windows Vista.

Tengo un bitmap con una imagen (bmp) de 120 pixels x 50 pixels (aprox) y necesito buscar si se encuentra en el escritorio.

Para ello lo que yo sé hacer es capturar el escritorio en un bitmap (con BitBlt, no sé si hay otra forma mejor) y después recorrer todo el bitmap del escritorio buscando el bitmap de la imagen buscada (pixel por pixel).

Ya sé lo que pensarán, es una burrada, funciona pero puedes ir a cenar con los amigos y al regresar posiblemente el procedimiento haya encontrado la imagen y devuelto su posición (TPoint apuntando a Lef y Top en pantalla)

Es evidente que así no puedo continuar y estoy convencido que a nivel de tarjeta gráfica debe haber algún método que haga esto en un plis, al igual que hace la captura del escritorio, pero no tengo ni idea.

?Alguien puede ayudarme?:)

Gracias por vuestra colaboración.

duilioisola 17-10-2014 12:29:57

No tengo idea de manejo de imágenes, pero aquí va una idea para acelerar el tema:

Yo tomaría el primer pixel de la imagen (1,1).
Luego recorrería la imagen de la captura de pantalla pixel a pixel.
Si el pixel es igual al que busco compararía el resto de pixeles con la imagen que tengo. Esto te ahorrará la comparación de todos los pixeles que no tienen el color original.
Como paso intermedio, antes de comparar la imagen completa, podrías comparar las otras tres puntas (píxeles (120,1) (1,50) y (120,50)) y si son iguales continuar a comparar la imagen completa.

También dejaría de comparar 120pixeles antes de llegar al final derecho y 50 pixeles antes de llegar al fondo, pues la imagen no cabrá en la pantalla.
Creo que es obvio, pero también dejaría de comparar si he encontrado la imagen, a menos que exista la posibilidad de que haya más de una.

Si muestras la parte de código que compara una imagen con la de la captura de pantalla, quizás alguien pueda ayudarte a optimizarla.

ElDuc 17-10-2014 12:51:15

Gracias por tu colaboración duilioisola.

En realidad ya hago lo que tu dices, es decir si el primer pixel no coincide ya no sigo y cambio al siguiente punto de pantalla y también elimino la parte derecha e inferior donde no puede estar, pero todos los comentarios de mi primer escrito ya contaban con estas características en el código y tarda el miserere.

Tal como me sugieres adjunto el código:
Código Delphi [-]
Function FindImage(AMonitor: Byte; B: TBitmap): Tpoint;
Var
    BB: TgvBitMap;
    BBB: TBitmap;
    X, Y, XX, YY: Integer;
    Font: TRect;
    Ok: Boolean;
Begin
Result.X := -1;
Result.Y := -1;
BB := TgvBitMap.Create;
BB.Bitmap := TBitmap.Create;
BB.Bitmap.Canvas.Lock;
BB.Left := 0;
BB.Top := 0;
If (AMonitor = 1) And (Screen.MonitorCount > 0) Then
    begin
    BB.Bitmap.Width := Screen.Monitors[1].Width;
    BB.Bitmap.Height := Screen.Monitors[1].Height;
    end
else
    begin
    BB.Bitmap.Width := Screen.Width;
    BB.Bitmap.Height := Screen.Height;
    end;
GetDeskTop(AMonitor, BB);
For X := 0 To BB.Bitmap.Width - B.Width Do
    Begin
    For Y := 0 To BB.Bitmap.Height - B.Width Do
        Begin
        Ok := True;
        For XX := 0 To B.Width - 1 Do
            Begin
            For YY := 0 To B.Height - 1 Do
                Begin
                If BB.Bitmap.Canvas.Pixels[X, Y] <> B.Canvas.Pixels[XX, YY] Then
                    begin
                    Ok := False;
                    Break;
                    end;
                End;
            If Not Ok Then
                Break;
            End;
        If Ok Then
            begin
            Result.X:=X;
            Result.Y:=Y;
            Break;
            end;
        End;
    If Ok Then
        Break;
    End;
If Assigned(BBB) Then
    begin
    BBB.Canvas.Unlock;
    BBB.Free;
    end;
If Assigned(BB) Then
    begin
    BB.Bitmap.Canvas.Unlock;
    BB.Free;
    end;
End;

Lo del monitor es porque trabajo con 2.

Saludos.

duilioisola 17-10-2014 13:07:35

Aquí explican como comparar dos imágenes:
Mediante Scanline
Código Delphi [-]
function IsSameBitmapUsingScanLine(Bitmap1, Bitmap2: TBitmap): Boolean;
var
 i           : Integer;
 ScanBytes   : Integer;
begin
  Result:= (Bitmap1<>nil) and (Bitmap2<>nil);
  if not Result then exit;
  Result:=(bitmap1.Width=bitmap2.Width) and (bitmap1.Height=bitmap2.Height) and (bitmap1.PixelFormat=bitmap2.PixelFormat) ;

  if not Result then exit;

  ScanBytes := Abs(Integer(Bitmap1.Scanline[1]) - Integer(Bitmap1.Scanline[0]));
  for i:=0 to Bitmap1.Height-1 do
  Begin
    Result:=CompareMem(Bitmap1.ScanLine[i],Bitmap2.ScanLine[i],ScanBytes);
    if not Result then exit;
  End;
end;

escafandra 18-10-2014 01:18:40

Quizás esto te de una idea: resta de imágenes, si la imagen resultante es negra, son iguales.

Saludos.

ElDuc 19-10-2014 10:20:52

Gracias a todos, pero por el momento dimito de este empeño, no es imprescindible para mi aplicación y ya he invertido demasiado tiempo en ello sin conseguir algo aceptable (desde el punto de vista de rapidez)

MIL GRACIAS.


La franja horaria es GMT +2. Ahora son las 19:27:54.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi