PixelSearch megalento

Tus preguntas. Algoritmos o Grupos de Comandos formando Programas Escripts.
Responder
Avatar de Usuario
Ximorro
Profesional del Autoit
Mensajes: 1500
Registrado: 10 Jul 2009, 12:35
Ubicación: Castellón, España

PixelSearch megalento

Mensaje por Ximorro »

Parece ser que PixelGetColor va extremadalento en vista, un simple programa que mira los puntos de un cuadrado me tarda MIL VECES MÁS en Vista que en XP, y el ordenata del Vista ¡es mucho más rápido! (normalmente el doble, por ejemplo haciendo renders 3D)

Vaya mirar un cuadrado de 30x30 (900 pixelitos) me tarda en el XP 11.82 ms, en Vista cuesta 11082.08 ms, ¡¡11 segundos!!, ¡76 míseros píxeles por segundo en un ordenador que hace millones y millones de operaciones por segundo!

No encuentro solución para resolver esto. Gracias, lo de "quita el Vista" ya lo sé, pero no siempre es posible :smt003

Por el foro inglés encontré una idea aceptable, que es hacer una captura del trozo que se va a mirar y mirar ahí directamente los píxeles con ayuda de la API en gdi32.dll. Incluso hay un udf que explota esa idea:
http://www.autoitscript.com/forum/index ... opic=63318

Pero tengo dos problemas:
a) Estoy mirando una zona cambiante y hay que estar haciendo capturas continuamente...
b) Por ahora la más importante: ¡No funciona! Ni el udf ni una versión que he hecho yo con esa idea me devuelven el color de los píxeles. Puede que yo haya metido la pata pero la udf se supone que está probada.

Abajo del todo os pongo mi código por si veis algún fallo que se pueda arreglar, o a lo mejor resulta que a mí no me va por otra razón, mirad a ver si os funciona...

Entonces, ¿alguien conoce alguna manera alternativa de hacer esto? ¿alguien sabe por qué ocurre? ¡porque no puede ser tan lento!
También he leido por el foro que se puede hacer una Dll que haga el PixelGetColor y usar eso desde AutoIt con DllCall, quizás sea fácil si alguien tiene las herramientas y el conocimiento y quiere probar... ¡que nos lo pase! :smt002

Este es el programita que usa GDIPlus, no me funciona, ni usando la idea de la udf que os he puesto arriba:

Código: Seleccionar todo

#Include <GDIPlus.au3>

#Include <WinAPI.au3>

#include <ScreenCapture.au3>



;El punto a mirar, para simplificar coger unas coordenadas entre 0 y $lado

;Naturalmente con GDI las coordenadas serían relativas al bitmap capturado, para

;PixelGetColor serían globales, pero coloco el cuadrado de captura en 0,0 para

;que coincidan y simplificar el ejemplo

Local $x = 5, $y = 5

$lado = 10 ;Por coger un cuadrito alrededor del pixel, se puede hacer más peque, claro



_GDIPlus_Startup()

$Contexto = _WinAPI_GetDC(0) ;DC del escritorio

; La UDF en vez de GetDC usa CreateCompatibleDC, tampoco funciona:

;$Contexto = _WinAPI_CreateCompatibleDC(0)



$HBITMAP = _ScreenCapture_Capture("", 0, 0, $lado, $lado, false)

_WinAPI_SelectObject($Contexto, $HBITMAP) ;Hay que seleccionar el bitmap para que GetPixel en GDI funcione



$col1 = PixelGetColor($x, $y)

$col2 = DLLCall("gdi32.dll", "int","GetPixel", "int",$Contexto, "int",$x, "int",$y)

MsgBox(0, "Coloritos", "PixelGetColor: <" & $col1 & ">" & @LF & "GetPixel: <" & $col2 & ">" & @LF )



_WinAPI_DeleteObject($HBITMAP)



_WinAPI_ReleaseDC(0, $Contexto)

;En la UDF como crean uno nuevo en vez de liberar, lo borran:

;_WinAPI_DeleteDC($Contexto)



_GDIPlus_ShutDown ()

 
Graciassss
"¿Y no será que en este mundo hay cada vez más gente y menos personas?". Mafalda (Quino)
Avatar de Usuario
Ximorro
Profesional del Autoit
Mensajes: 1500
Registrado: 10 Jul 2009, 12:35
Ubicación: Castellón, España

Re: PixelSearch megalento

Mensaje por Ximorro »

Ah, por cierto, también leí en el foro inglés que recomendaban usar el parámetro hwnd de GetPixelColor o PixelSearch. Lo he hecho pero tampoco me acelera nada, o al menos es imperceptible...
:smt011
"¿Y no será que en este mundo hay cada vez más gente y menos personas?". Mafalda (Quino)
Avatar de Usuario
BasicOs
Site Admin
Mensajes: 2091
Registrado: 21 Nov 2006, 19:24
Ubicación: El Internet - (Canarias, España)
Contactar:

Re: PixelSearch megalento

Mensaje por BasicOs »

No se si te viene bien probar con el W7 o es que has tenido un cambio con drivers o config de la tarjeta gráfica (puede ser un chipset diferente)?? :smt009 :smt009

Tienes muchas opciones, Si te he entendido bien, quieres vigilar un cambio en una zona, y luego cuando ha habido un cambio ir a un pixel específico a ver si cambió??
Una opción muy rápida puede ser guardar el fichero de trozo de pantalla en el disco duro (o en ram), y luego cuando compruebes en el timer más tarde se creará otro fichero, y comprobarlos, o bien por tamaño, o por dentro. Una vez que lo has comparado puedes ir al pixel/s específico a ver si coincide con el cambio que estés buscando.... Otra opción también podría ser aumentar el espaciado del chequeo de los pixeles con lo que es más mucho rápido aunq revisa pixeles alternativos, por ejemplo si hay estos pixeles en pantalla: "xxxxxxxx1xxxxxxx1" revisaría solo el pixel del 1 y no los de las x

(No se si te refiers a esto, sino puedes postear el código para ver como esta eso? Si lo deseas..)

Grabadores del PrintScreen a fichero en jpg, png, etc... aquí:
http://www.autoitscript.com/forum/index ... omsearch=1
Salu2:)
Avatar de Usuario
Chefito
Profesional del Autoit
Mensajes: 2035
Registrado: 21 Feb 2008, 18:42
Ubicación: Albacete/Cuenca (España)

Re: PixelSearch megalento

Mensaje por Chefito »

Nas.
Has tocado dos temas que odio, el win Vista y programación con gráficos :smt005 :smt005 .
Lo que quieres hacer es buscar el color de un pixel determinado en una imagen?? o quieres comparar todos los pixeles de una imagen continuamente por si cambian su color?? (esto sería más lento logicamente).
Bueno, con lo de probar códigos en el Vista me va a ser imposible, porque no lo tengo y no creo que nunca lo tenga (nunca me gustó :smt009 ).
Lo de intentar hacer ese código de distintas formas......con eso a lo mejor te puedo ayudar :smt024 .

Has probado a recorrer los pixeles de la imagen con la api getpixel con dos for....next??? (a la antigua usanza :smt005 ). Uno que se encarge de recorrer las coordenadas del ancho de la imagen y el otro las coordenadas del alto de la imagen.
Incluso si es algo lento y quieres darle velocidad puedes hacer saltos en los for...next quitandole la mitad de los píxeles a mirar (con un step 2). No creo que quitar esos píxeles afecten mucho a que te digan si una parte de la imagen ha cambiado o no, y encima ganas el doble de velocidad!. Incluso puedes ganar más velocidad saliendote de los for....next cuando haya encontrado algún cambio.

Te pongo dos ejemplos mios que he visto al hacer una búsqueda de PixelGetColor, para ver si te ayudan:
http://www.emesn.com/autoitforum/viewto ... olor#p2791
http://www.emesn.com/autoitforum/viewto ... olor#p5333

Este último creo que lo que hacía era revisar si había un pixel de un color determinado y si era adyacente a otro pixel de ese mismo color (un pixel tiene 8 píxeles adyacentes). Muy interesante :smt005 .
Solamante tienes que cambiar la función FixelGetColor por la api GetPixel y listo.

Por cierto, has probado la función PixelSearch para buscar el pixel? Te interesa esta función? Es que he visto que lo titulas así el post y que solo hablas de la función PixelgetColor.

Saludos.
Cita vista en algún lugar de la red: En este mundo hay 10 tipos de personas, los que saben binario y los que no ;).
Avatar de Usuario
Ximorro
Profesional del Autoit
Mensajes: 1500
Registrado: 10 Jul 2009, 12:35
Ubicación: Castellón, España

Re: PixelSearch megalento

Mensaje por Ximorro »

Gracias a los dos pero me parece que no nos hemos entendido muy bien.
El caso es que el tema no es qué hacer con los píxeles o cómo buscar patrones, sino la función concreta que mira el pixel.
El hecho de mirar la imagen y analizarla ya está hecho y funciona, eso no es problema, se puede hacer tanto con PixelGetColor como con PixelSearch, al final lo hice con PixelGetColor porque mirando 3 pixeles concretos ya veo lo que hay, así que es más rápido que PixelSearch que tiene que mirar más pixeles (al principio era con PixelSearch, de ahí el nombre del post, perdón, tenía que haber puesto PixelGetColor).

Pero ese no es el problema, el problema es que el programa, que va perfectamente en XP, va increíblemente lento en Vista (también funciona, pero muy lento). Y el problema es en concreto la función PixelGetColor (o PixelSearch, que o usa internamente PixelGetColor o mira los píxeles igual y también va lento).

Por ejemplo un bucle así:

Código: Seleccionar todo

$lado = 30

$tIni = TimerInit()

for $y = 0 to $lado

    For $x = 0 To $lado

        $var = PixelGetColor($x, $y)

        ;ConsoleWrite($var & " ")

    Next

Next

ConsoleWrite(@LF & TimerDiff($tIni) & " ms" & @LF)
Me da estos resultados según el valor de $lado (vista/xp):
20: 4929.49 ms / 4.31 ms
30: 11082.08 ms / 11.82 ms
40: 19652.16 ms / 25.20 ms

Es decir, en vista va unas MIL veces más lento.

Usando directamente la función GetPixel en gdi32.dll (capturando un bitmap primero) sí va más rápido... ¡pero no funciona!
Si ejecuto el programa que os puse en el post, me sale en el MsgBox:
PixelGetColor: <7769816>
GetPixel: <>

El numerito lógicamente cambiará según lo que haya en la pantalla, ¡pero GetPixel no devuelve nada! Y tampoco me da códigos de error, ni GDIPlus ni la función en sí... :smt013

Usando la udf "_PixelGetColor.au3" que os ponía en el link del foro inglés pasa lo mismo, no me devuelve el color de los píxeles.
Se supone que GetPixel devuelve un entero, aunque no fuera el mismo formato RGB que Autoit daría un número diferente, ¡pero daría algo!

Así que mi consulta es si alguien conoce otra alternativa a PixelGetColor de AutoIt o GetPixel de gdi32.dll que vaya bien en Vista.
O bien si he hecho mal el código que llama a GetPixel y alguien lo ve estaría bien, porque esas llamadas sí van rápido.
O si os funciona el ejemplo a ver si es mi ordenador, aunque el resultado es el mismo en XP y Vista, en dos ordenadores diferentes.

Espero haberlo explicado ahora mejor.
Gracias.
"¿Y no será que en este mundo hay cada vez más gente y menos personas?". Mafalda (Quino)
Avatar de Usuario
Chefito
Profesional del Autoit
Mensajes: 2035
Registrado: 21 Feb 2008, 18:42
Ubicación: Albacete/Cuenca (España)

Re: PixelSearch megalento

Mensaje por Chefito »

Mmmmm....ten cuidado al recibir los resultados de las apis. Casi siempre te devuelven un array con varios elementos. Eso es lo que te pasa, que no recuperas el primer elemento....que es el que te devuelve el color (en tu caso $col2[0]).
Mira tu script un poco toqueteado :smt003 :

Código: Seleccionar todo

#Include <GDIPlus.au3>

#Include <WinAPI.au3>

Local $x = 1, $y = 1

_GDIPlus_Startup()

$Contexto = _WinAPI_GetDC(0)

$col1 = PixelGetColor($x, $y)

$col2 = DLLCall("gdi32.dll", "int","GetPixel", "int",$Contexto, "int",$x, "int",$y)

MsgBox(0, "Coloritos", "PixelGetColor: <" & Hex($col1) & ">" & @LF & "GetPixel: <" & Hex($col2[0]) & ">" & @LF )

_WinAPI_ReleaseDC(0, $Contexto)

_GDIPlus_ShutDown ()

 
Lo que me ha mosqueado es la diferencia de modos de color. Según la ayuda de AutoIt la función PixelGetColor muestra el color en modo RGB, pero según la ayuda de la api también. Lo he tenido que comprobar con un programa de dibujo y parecer ser que PixelGetColor muestra el color en RGB y la api en BGR :smt017 . La verdad, me ha descuadrado totalmente, porque yo todo el tiempo que he utilizado esta api en vb6 creía que lo devolvía en RGB :smt017 . Puede que la llamada a esta api en AutoIt cambien el modo de color???? :smt017 . Ni idea...puede que sí.

Me ha interesado el tema de la velocidad en uno y otro y he buscado en el foro ingles. Mira este post:
http://www.autoitscript.com/forum/index ... ntry686593

Saludos.
Cita vista en algún lugar de la red: En este mundo hay 10 tipos de personas, los que saben binario y los que no ;).
Avatar de Usuario
BasicOs
Site Admin
Mensajes: 2091
Registrado: 21 Nov 2006, 19:24
Ubicación: El Internet - (Canarias, España)
Contactar:

Re: PixelSearch megalento

Mensaje por BasicOs »

  • Una opción que no he probado puede ser guardar el fichero de trozo de pantalla con printscreen (HAY UNA UDF HECHA) que puede ir muy rapido y trabajar sobre el valor que esta en el ClipGet(), no se si lo da directamente o hay q buscarlo... eso por probar algo aleatorio....
  • Sino grabar en disco y comparar los ficheros que se crean con cada printscreen()el valor...una variable (o en ram), y luego cuando compruebes en el timer más tarde se creará otro fichero, y comprobarlos, o bien por tamaño, o por dentro, no me preguntes como puedes traducir la info del fichero a algo como una vectorización de números, por ejemplo.
  • Una vez que lo has comparado que hay un cambio global, puedes ir al pixel/s específico a ver si coincide con el cambio que estés buscando....
  • Otra opción también puede ser aumentar el espaciado del chequeo de los pixeles con lo que es más mucho rápido aunq revisa pixeles alternativos, por ejemplo si hay estos pixeles en pantalla: "xxxxxxxx1xxxxxxx1" revisaría solo el pixel del 1 y no los de las x. Es menos preciso.
  • Otra opción, es pero muchas veces no necesitas en una forma sino revisar el bloque sino algunos de los pixeles de los bordes de la forma o simbolo, no de todos los pixeles de toda la estructura q buscas...
Salu2:)
Avatar de Usuario
Ximorro
Profesional del Autoit
Mensajes: 1500
Registrado: 10 Jul 2009, 12:35
Ubicación: Castellón, España

Re: PixelSearch megalento

Mensaje por Ximorro »

Chefito:
¡Gracias! Mira que me volvía loco GetPixel, no se me había ocurrido lo de la matriz, y es que la ayuda no ayuda :smt013
Según la MSDN de GetPixel (http://msdn.microsoft.com/en-us/library ... 85%29.aspx)
"The GetPixel function retrieves the red, green, blue (RGB) color value of the pixel at the specified coordinates."
Efectivamente, ponen RGB...

"Return Value:
The return value is the RGB value of the pixel. If the pixel is outside of the current clipping region, the return value is CLR_INVALID."

Traduzco: "El valor de retorno es el valor RGB del pixel. Si el pixel está fuera de la región de recorte se devuelve CLR_INVALID."

¡Otra vez dice que está en RGB ¿Será AutoIt el que lo cambia?, ¿cómo? ¡una DLLCALL sólo devuelve lo que recibe!
Y no dice nada de matrices por ningún lado, sino que devuelve el valor (o CLR_INVALID), por eso ni se me ocurrió, como devuelve un int, pues yo esperaba un entero.

Y hay más:
A bitmap must be selected within the device context, otherwise, CLR_INVALID is returned on all pixels.
Esto es: "Debe haber un bitmap seleccionado en el "device context", de lo contrario se devuelve CLR_INVALID para todos los pixeles"

¡Por eso yo capturé y seleccioné el bitmap! (y la udf hacía lo mismo), pero tu ejemplo muestra que no hace falta. ¡Mejor!
Será que ya está seleccionado, pero como digo la ayuda no ayuda...

...
¡He encontrado algo!
Según la ayuda de GetPixel se devuelve un COLORREF. Mirando la ayuda de COLORREF veo:
typedef DWORD COLORREF;

¡Así que es un entero! No veo cómo debo adivinar que se devuelve una matriz.
Pero hay algo "bueno", atención:
When specifying an explicit RGB color, the COLORREF value has the following hexadecimal form: 0x00bbggrr
"Cuando se especifica explícitamente un color RGB, el valor COLORREF tiene la siguiente forma hexadecimal: 0x00bbggrr

¡¡Es decir, sí es BGR!! La gran cagada es que en la ayuda de GetPixel no lo indican, más bien parece que indican lo contrario varias veces.

O sea, que toca hacer la conversión, ya veremos cómo lo hace eso de lento, ¿alguien conoce una forma rápida? porque pasar a cadena con HEX, conmutar parejas de caracteres, y volver a pasar a número, parece que va a ser lento... :-(

Por ejemplo en el enlace que pones (que por cierto no había visto cuando estuve buscando) ¡no pasa de BGR a RGB! y efectivamente si lo pruebas no funciona (aunque ahí sí toma el valor de la matriz, si lo hubiera visto antes...)

Pero algo es algo...
"¿Y no será que en este mundo hay cada vez más gente y menos personas?". Mafalda (Quino)
Avatar de Usuario
Ximorro
Profesional del Autoit
Mensajes: 1500
Registrado: 10 Jul 2009, 12:35
Ubicación: Castellón, España

Re: PixelSearch megalento

Mensaje por Ximorro »

BasicOs:

Efectivamente hacía algo así, capturaba un bitmap con ayuda de la udf ScreenCapture.au3, no lo guardaba en disco (¡eso sería muy lento!) sino que utilizaba directamente el bitmap en memoria.

Al tomar bien el valor de retorno de GetPixel (por lo visto no es el valor directamente, viene en un vector), ya funciona... ¡pero resulta que no hace falta capturar el bitmap!. Resulta que se puede mirar directamente en el device context. Igual es porque el escritorio ya tiene un bitmap seleccionado, si con otras ventanas no me funciona volveré a poner lo del bitmap a ver.

Por cierto tampoco hace falta pasar por el portapapeles, _ScreenCapture_Capture ya devuelve una referencia al bitmap, así que se puede usar directamente en memoria sin copiarlo otra vez.

Gracias por las ideas.
"¿Y no será que en este mundo hay cada vez más gente y menos personas?". Mafalda (Quino)
Avatar de Usuario
Ximorro
Profesional del Autoit
Mensajes: 1500
Registrado: 10 Jul 2009, 12:35
Ubicación: Castellón, España

Re: PixelSearch megalento

Mensaje por Ximorro »

Partiendo de:
$var= DLLCall($GdiDLL, "int","GetPixel", "int",$Contexto, "int",$x, "int",$y)

He encontrado varias maneras de pasar de BGR a RGB, he probado las más prometedoras y la más rápida es ésta:

$var = Hex(BinaryMid($var[0], 1, 3))

Seguida muy de cerca de ésta:
$var = Hex(BitShift( String(Binary($var[0])), 8 ))

Hay otras más lentas que usan más operaciones binarias, y luego están las que trabajan directamente convirtiendo a strings y cambiando los numeritos de posición, esas son las más lentas.

Con la primera opción, en XP esta manera de mirar el pixel es algo más del doble de lento que PixelGetColor, así que no es interesante. Pero eso significa que en Vista será unas 500 veces más rápido que antes (no tengo ahora un Vista para probar, os lo digo mañana).


Una cosa sobre GetPixel, vale, en $var[0] está el color... ¿y qué hay en $var[1]? porque me salen también numeritos...
UBound($var) me sale 4, es un array de 4 elementos... (indizados de 0 a 3)

Huuum, parece ser que $var[2] y $var[3] son la X,Y del punto que has pasado, respectivamente.
¿¿Qué será $var[1]? no parece el color en RGB, ¿estará en otro formato?... ¿Será el handler del contexto? voy a ver...
SI, coincide con el valor de $contexto, curioso, cambia según el pixel que busco.
¿Por qué no pone estas cosas en la ayuda de la API? :smt013
"¿Y no será que en este mundo hay cada vez más gente y menos personas?". Mafalda (Quino)
Avatar de Usuario
BasicOs
Site Admin
Mensajes: 2091
Registrado: 21 Nov 2006, 19:24
Ubicación: El Internet - (Canarias, España)
Contactar:

Re: PixelSearch megalento

Mensaje por BasicOs »

Aqui hay unos con una función de conversión del formato de color:
GBR2RGB()
http://www.autoitscript.com/forum/index ... t&p=741821
Avatar de Usuario
Chefito
Profesional del Autoit
Mensajes: 2035
Registrado: 21 Feb 2008, 18:42
Ubicación: Albacete/Cuenca (España)

Re: PixelSearch megalento

Mensaje por Chefito »

Ximorro escribió:Una cosa sobre GetPixel, vale, en $var[0] está el color... ¿y qué hay en $var[1]? porque me salen también numeritos...
UBound($var) me sale 4, es un array de 4 elementos... (indizados de 0 a 3)

Huuum, parece ser que $var[2] y $var[3] son la X,Y del punto que has pasado, respectivamente.
¿¿Qué será $var[1]? no parece el color en RGB, ¿estará en otro formato?... ¿Será el handler del contexto? voy a ver...
SI, coincide con el valor de $contexto, curioso, cambia según el pixel que busco.
¿Por qué no pone estas cosas en la ayuda de la API?
Has acertado en todo :smt003 . Yo ya sabía que devolvía 4 elementos, pero vi que los 3 últimos no son importantes. Estos 3 elementos contienen los parámetros que le pasas a la función api getpixel. Son parámetros de antemano conocidos. AutoIt hace esto. No se porque.
Cuando yo llamaba a estas apis en vb6 solo te devolvían un entero....como debe ser. Pero como dije antes, AutoIt suele devolver un array casi siempre, con el primer elemento válido, y los demás con parámetros ya conocidos de la función. Ya me ha pasado con varias apis. Pero tengo la impresión que eso no es lo normal, que solo pasa en AutoIt.

Cambiando de tema, yo no conozco otra api para recuperar el color de un pixel. Puede que haya alguna función en la api de directX....quien sabe.
Pero yo me pregunto, para que quieres transformar el resultado a rgb??? Trabaja en bgr y ya está :smt002 . Compara el color de los pixel en bgr con la api getpixel. Si quieres comparar cambios en los píxeles, el valor que te devuelva getpixel va a cambiar si el pixel ha cambiado, aunque sea en modo bgr no? :smt002 .
Lo único que tu lo tienes que tener en cuenta por si quieres hacer algo aparte de comparar los mismos resultados que te devuelva getpixel. Pero como ya sabes que tienes que tener en cuenta el orden del rojo y el azul, pues lo haces y punto.

Pero yo te recomiendo que compares los resultados que te devuelva la función getpixel en todo momento (sin hacer ningún cambio innecesario) para no perder velocidad.

Saludos.
Cita vista en algún lugar de la red: En este mundo hay 10 tipos de personas, los que saben binario y los que no ;).
Avatar de Usuario
Ximorro
Profesional del Autoit
Mensajes: 1500
Registrado: 10 Jul 2009, 12:35
Ubicación: Castellón, España

Re: PixelSearch megalento

Mensaje por Ximorro »

Pues sí que hace raro lo de los parámetros, que te los devuelva en el resultado parece algo interno para hacer debug, a los programadores normales no nos vale para nada, en realidad sería más eficiente que no lo hicieran...

Respecto al modo BGR pues tienes razón, si vas a trabajar con esos píxeles se miran así y ya está. El único problema es cuando tienes también pixeles "normales" en RGB, entonces tienes que convertir uno de los modos, pero puedo decir que el método ese con el BinariMid es muy rápido.

Respecto a la batallita en Vista ha sido desalentador. Me temo que no hay nada que hacer:
El método simplificado de Chefito de tomar el DC del escritorio y mirar ahí directamente el pixel va extremadamente lento en Vista, tanto como PixelGetColor (quizás internamente hagan eso mismo).
En Vista para intentar acelerar las cosas ES NECESARIO crear un CompatibleDC, y sobre ese nuevo DC crear y seleccionar un bitmap sobre el que se capture la zona a investigar. PERO:
Una función pura para mirar píxeles (o sea, que para cada pixel a mirar haga una captura) es tremendamente lenta, incluso capturando sólo el pixel a mirar en un minibitmap de 1x1, y optimizando al máximo (saqué toda la parafernalia fuera de la función, la función sólo hacía el BitBlt para copiar el pixel al bitmap y luego el GetPixel para verlo). Pues así, ¡sigue siendo megalento!.

De esa manera en XP es unas 9 veces más lento que PixelGetColor, en Vista prácticamente igual.

En Vista sólo se consigue mejora si para cada captura se miran varios píxeles, es decir, se toma una zona más grande y sobre esa zona se hacen varias consultas seguidas. Esto es aceptable para analizar imágenes que no cambian, pero si son cambiantes no hay solución. Imaginaos que estáis analizando los emoticonos de la derecha de la página de edición de posts, mirando los píxeles que cambian para ver por dónde anda el emoticono saltarín, por ejemplo...

Además es un engorro... yo trabajaba con coordenadas relativas al cliente del GUI (PixelCoordMode=2), para hacer la captura (BitBlt) tengo que pasar las coordenadas que quiero capturar desde ese modo a coordenadas absolutas de pantalla. ¡Encima luego para mirar los píxeles (GetPixel) tengo que usar coordenadas relativas al bitmap! Un poco coñazo, la verdad.

Leí que M$ en una de sus maravillosas decisiones de diseño, ahora en Vista (y Windows7) la API GDI+ es emulada por software, en vez de hacerlo por HD como era antes... supondrían que como los ordenadores son cada vez más rápidos no se notaría... ¡pues 76 pixeles por segundo es más que ridículo! ¡seguro que la GameBoy miraba más!

¿Qué tal la API DirectX?, sería la parte DirectDraw, que es la que trabaja en 2D ¿no? Como no hay que meterse en 3D igual no es tan complicado... ¿alguien controla el asunto? si ni siquiera quiero dibujar ¡sólo necesito mirar un pixel de la pantalla, por compasióoooooooon!

Talueeeec
Última edición por Ximorro el 04 Nov 2009, 12:01, editado 1 vez en total.
"¿Y no será que en este mundo hay cada vez más gente y menos personas?". Mafalda (Quino)
Avatar de Usuario
Ximorro
Profesional del Autoit
Mensajes: 1500
Registrado: 10 Jul 2009, 12:35
Ubicación: Castellón, España

Re: PixelSearch megalento

Mensaje por Ximorro »

BasicOS no había visto tu post sobre RGB2BGR.

Uy, ese método extrayendo los caracteres del string es lentísimo, aquí os pongo los 4 mejores métodos que he encontrado, ordenados de más rápido a más lento:
(Nota, pasar de RGB a BGR es equivalente a cambiar de BGR a RGB, la función es la misma pues se trata de intercambiar los dos bytes de R y B)
$var contiene el color en uno de los dos formatos y es transformado al otro

$var = BinaryMid($var, 1, 3)

$var = BitShift( String(Binary($var)), 8 )

$var = BitXOR($var, (BitXOR(BitAND($var, 0xFF), ($var / 0x10000)) * 0x10001))

$var = BitOR(BitAND($var, 0x00FF00), BitShift(BitAND($var, 0x0000FF), -16), BitShift(BitAND($var, 0xFF0000), 16))

Los que trabajan con las cadenas son con diferencia los más lentos, tipo:
$var = Hex(String($var), 6)
$var = Number("0x" & StringMid($var, 5, 2) & StringMid($var, 3, 2) & StringMid($var, 1, 2))

Os recomiendo usar el primero, muy rápido y cortito.

Eso sí, TODOS estos métodos pierden el canal alfa, así que si hace falta el primer byte habrá que modificarlos.
"¿Y no será que en este mundo hay cada vez más gente y menos personas?". Mafalda (Quino)
Avatar de Usuario
BasicOs
Site Admin
Mensajes: 2091
Registrado: 21 Nov 2006, 19:24
Ubicación: El Internet - (Canarias, España)
Contactar:

Re: PixelSearch megalento

Mensaje por BasicOs »

Problema solucionado con los Pixel,

Por lo que he mirado en el foro alemán, el estilo del Vista Aero no va bien, se soluciona desactivandolo.
El PixelGetColor trabaja sobre la función gdi32.dll según he leido en ese foro.

Tambien lo han probado en W7 sin Aero ni otros efectos, y va bien
El problema es lo que comentais que lo grafico va por soft no por hard(en ese caso), porque Win7 corre en una máquina virtual.
Créditos para GtaSpider por la función para desactivar aero, al salir del escript te lo vuelve a activar de nuevo :D

Por si alguien quiere probar la velocidad, este es un juego parecido al "Tron" donde se usa la función PixelGetColor

http://www.autoit.de/index.php?page=Thr ... 4&pageNo=1

Código: Seleccionar todo

Global Const $hDwmApiDll = DllOpen("dwmapi.dll")

If _IsAeroEnable() = 0 Then _EnableDisableAero(False)

#Region dwmAPI.au3

;===============================================================================

; Function Name:   _EnableDisableAero()

; Description:    Enables or Disables the Aero design from Vista to the default design.

; Parameter(s):    $bEnable [BOOLEAN]: True enables the Aero, False disables it.

; Requirement(s):  dwmapi.dll, Windows Vista

; Return Value(s): Returnvals of DLLCall

; Author(s):       GtaSpider

;===============================================================================

;

Func _EnableDisableAero($bEnable = True) ;True/False

    Local $aDll = DllCall($hDwmApiDll,"int","DwmEnableComposition","int",$bEnable)

    If @error Then Return SetError(@error,0,0)

    Return $aDll[0]

EndFunc

;===============================================================================

;

; Function Name:   _IsAeroEnable

; Description:    Checks if aero is enable

; Parameter(s):    None

; Requirement(s):  dwmapi.dll, Windows Vista

; Return Value(s): 0 If disabeld, 1 if enabled

; Author(s):       GtaSpider

;===============================================================================

;

Func _IsAeroEnable()

    Local $asDll = DllCall($hDwmApiDll,"int","DwmIsCompositionEnabled","str","")

    If @error Then Return SetError(@error,0,0)

    Return StringReplace(StringReplace(Asc($asDll[1]),"1",True),"0",False)

EndFunc

Func OnAutoItExit()

    DllClose($hDwmApiDll);Close dwmapi

EndFunc

#EndRegion dwmAPI.au3

 
Avatar de Usuario
Ximorro
Profesional del Autoit
Mensajes: 1500
Registrado: 10 Jul 2009, 12:35
Ubicación: Castellón, España

Re: PixelSearch megalento

Mensaje por Ximorro »

¿Dónde está el emoticono de mucha sorpresa?
¡BasicOS como esto funcione te doy dos besos! :smt003 :smt003

Nunca se me hubiera ocurrido mirar en el foro alemán. En el de inglés me defiendo bien, en el de francés no tengo ni idea pero puedo adivinar algunas cosas, ¡pero en el de Alemán no me entero ni de coña!

Ahora estoy sobre un XP, a ver si esta tarde puedo probarlo en un Vista y os cuento.

Aunque si desactivar el Aero implica que de repente cambia todo el entorno cuando ejecutas el programa igual no le gusta al usuario, pero es una opción interesante para cuando no haya otra manera.

Ala, a la carpeta de utilidades.

¡Gracias!
"¿Y no será que en este mundo hay cada vez más gente y menos personas?". Mafalda (Quino)
Avatar de Usuario
Ximorro
Profesional del Autoit
Mensajes: 1500
Registrado: 10 Jul 2009, 12:35
Ubicación: Castellón, España

Re: PixelSearch megalento

Mensaje por Ximorro »

¡Pues sí, funcionar funciona!

El único problema es que efectivamente se ve claramente que de repente cambia el entorno, desaparecen las trasparencias, el suavizado de las ventanas, etc... Al menos la activación/desactivación es muy rápida.

Si es un programa para que lo usen otros mejor se avisa de que va a pasar eso o los dejarás sorprendidos. Lo importante es que al menos hay alguna solución, aunque no sea la más elegante.

Gracias por el hallazgo.
"¿Y no será que en este mundo hay cada vez más gente y menos personas?". Mafalda (Quino)
Responder