Identificar un punto en una imagen VFP 9.0 o VB 6.0

Iniciado por Hcrisel, 4 Noviembre 2021, 16:58 PM

0 Miembros y 1 Visitante están viendo este tema.

Hcrisel

Hola necesito ver si podes darme una mano.

Tengo un Formulario 640x480
Dentro del  Form1 tengo un Objeto image1 con una imagen que es MUCHO más grande que el tamaño del Form1.

* Bien hasta ahora logré con el mouse: Desplazar la imagen dentro del formulario,
* Con la rueda del mouse puedo Ampliar o reducir el tamaño de la imagen (Zoom).

Ahora imaginate que el picture de la image1 es el cuadro de la Gioconda.

Necesito hacerle clic en el OJO DERECHO y un label1, me diga "Ojo Derecho"

Mi problema es que de acuerdo al Desplazamiento de la imagen o Zoom que le haya hecho previamente, las Coordenadas XY del ojo cambian impidiéndome identificar el OJO DERECHO.

¿Te pregunto. Se te ocurre algo o conoces algún método que me permita identificar ese ojo derecho que nunca sabré en qué posición XY estaría?

Muchas Gracias

Serapis

#1
Hay 3 formas:
En todos los casos se parte de la imagen en su tamaño real.

A - Creas recortes para cada zona de tu interés. y de ellas se realizan máscaras, de modo que cada imagen finalmente contenga solo el recorte como zona opaca y valor de máscara en el resto. Pero todas del mismo tamaño. Cada imagen es finalmente (se carga en) un objeto image, la máscara de cada una deja esa zona para esa imagen invisible.
La superposición de todas ellas completan la imagen (típicamente una, sería la que no tiene 'nada' especial'. Esta puede se rla imagen original puesta de fondo... Al ser todas del mismo tamaño y posicionadas en las mismas cordenadas, la zona opaca de cada imagen es la que actúa como receptor del foco, bastaría en ese caso colocar en la propiedad tooltiptext de cada una lo que proceda, ojo derecho, boca, muslo, etc... en la imagen del fondo no s epone tooltiptext, que recibirá el foco justo en las zonas que no ocupa ninguna del resto. Es decir donde no merece la pena indicar nada especial (si es el caso), aunque conviene usarse para indicar: "si mueves el cursor por la imagen al detetar zonas señalará ciertos valores', o el texto que ati te parezca pertinenen al caso.
.
Por supuesto al hacer zoom, debe hacerse para todas y posicionarse todas en las mismas cordenadas.



B - Otra forma consiste en marcar las areas (rectangulares) de cada zona, y anotar para cada una su posición, medidas, texto, etc... relativa a cada una. Una copia de la imagen la trabajas primero en un programa de dibujo para señalar dichas zonas y tener certidumbre de los valores...
Cuando se haga click sobre la imagen (o en el evento mousemove), debes hacer una búsqueda para determinar en que zona está...

Vamos a complicarlo un poquito, y permitir solapes de zonas, incluso permitir zonas completamente dento de otras, aunque se limita que las misma área sea solapada por la confluencia de más de 2 zonas.


estructura datosImg
   entero X
   entero Y
   entero Ancho
   entero Alto
   string Texto
   // estos datos son opcionales. si no se incluyen (en el fichero) deben valer -1.
   entero Solapa            // una zona cubre parcialmente a la zona  que aquí se indica (cuestión dle uso de rectangulos). esta es la que tiene preferencia sobre la solapada.
   entero Solapado         // señala cuantas zonas están solapando a esta.
   entero InluidaEn         // Una zona está completamente de la que aquí se señale.
   entero Excluye           // señala cuantaz zonas contiene esta dentro de sí completamente.
fin estructura

array de datosImg datos()

sub imageX_Click (x, y, ...)
   llamada a DetectarZona(x,y)
fin sub
sub imageX_Mousemove (x, y, ...)
   llamada a DetectarZona(x,y)
fin sub


Un ejemplo... sean los siguientes los parámetros, que constan en el fichero que has creado y demos por supuesto que sabes leer del fichero, etc... (más abajo adjunto una imagen con las zonas que (con aprox,) correponden a estos datos).
----------------------------------------------------------
10 zonas
0, 191,374,34,25, "ojo izquierdo", -1, -1, 8
1, 239,372,40,25, "ojo derecho",-1, -1, 8
2, 211,235,45,25, "boca", -1, -1, 8
3, 114,555,184,154, "manos"
4, 294,128,80,240, "pelo", -1, 9,
5, 187,080, 150,48, "pelo"
6, 166,126,26,240, "pelo"
7, 191,260,45,63,"pelo"          <-------- pelo ocupa varias zonas disitntas.
8, 192,128,103,155,"cabeza", -1, -1, -1, 3   <------- cabeza será si están dentro de la zona cabeza, pero no en ojos ni boca.
9, 253,283,71,40, "cuello", 4   <------- esta zona solapa a la zona 4 (el pelo a la derecha de la imagen).
--------------------------------------


array datosImg  Datos()
entero numzonas


funcion IniciarImagen(string ruta)
  entero k

  abrir fichero
  leer numzonas
 
  dimensionar array Datos(0 a numzonas-1)
  por cada linea siguiente en fichero
       datos(k) = LineaToDatos(linea)
  siguiente
fin funcion

datosImg = funcion LineaToDatos(string linea)
     datosImg  dt
     array de string campos() = split(linea, ",")

     dt.X = campos(0).ToEntero
     dt.y = campos(1).ToEntero
     dt.Ancho = campos(2).ToEntero
     dt.Alto = campos(3).ToEntero
     dt.Texto = campos(4)

     // Datos opcionales.
     si campos.Length = 6
         dt.Solapa = campos(5).ToEntero    
     fin si
     si campos.Length =7
         dt.Solapado = campos(6).ToEntero    
     fin si  
     si campos.Length = 8
         dt.IncluidaEn = campos(7).ToEntero    
     fin si
     si campos.Length = 9
         dt.Excluye = campos(8).ToEntero    
     fin si

     devolver dt
fin funcion


Finalmente la función 'DetectarZona' que detecta sobre qué zona está el ratón... la dejo a tu ingenio y esfuerzo... si pasado un par de días no consigues avances, avisa y te pongo un sencillo/enredoso peudocodigo para resolverlo.
Nota: Si no permites solapes ni zonas dentro de otras, la función es relativamente sencilla. Al menos resuelve ese caso de entrada y cuando te funcione y si te interesa el caso, copia la funcion, renombrala y modifica la copia para acometer la comentada funcionalidad extra...

Una imagen para que te sirva de guía (los datos adjuntados más arriba cuasi corresponden, y digo cuasi, porque los he anotado de memoria y puede que alguno no se ajuste con precisión al valor dado.
nota como los ojos y la boca están encajados dentor d ela zona de 'cara', que se ha pintaod de rojo, para remarcar el hecho de tener zonas en su interior. etc...




C - La última forma es considerar solo un punto para cada zona... el punto en este caso, se considera el 'centro' de la zona, y además del punto se considera un área de influencia, que en vez de dar ancho y alto (para un área rectangular), se da en radio.
Es similar al caso anterior, pero es más fácil la detección. Incluso casos con solapes... y opera con 'circulos en vez de rectángulos.

Un psuedocódio para que sepas por donde andar...

estructura datosImg
   estructura datosImg
   entero X
   entero Y
   entero radio
   string Texto
fin estructura


Abres el fichero, lees la cantidad de zonas y cada zona para pasar los datos al array... (como se señala más arriba)
Igualmente con eventos click o mousemove, invocasa la función detectarZona...
Esta función es más sencilla, que la anterior, incluso con solapes. Te la señalo en pseudocódigo en pocas líneas:


funcion DetectarZona(x,y)
   datosImg zona
   entero z,n,d, index

   establecer un valor para z = ancho + alto de la imagen
   n = -1

   por cada zona en datos()
       // si el punto cae en el circulo que delimita el radio
       esto es:     d = calcular la distancia desde el punto al centro de la zona   // d puede ser un 'float' si se requiere.
       si (d < zona.radio)  // está dentro de la zona.
           si (d < z)    // está más cerca del centro de esta zona que de otra zona previa.
               z = d         // recordamos la distancia al su centro, para descubir si más adelante otra zona la bate.
               n = index  // recordamos que zona es por su indice en el array.
            fin si
       fin si

       index +=1
   Siguiente

   si (n>0)    // si el cursor finalmente se encontró dentro de una zona y buscado la zona cuyo centor queda más cerca...
       image1.tooltiptext = datos(n).Texto
   sino
       image1.tooltiptext = ""   // el cursor no cae en ninguna zona.
   fin si
fin funcion


Como se ve en esta función lo que se trata es ver si el cursor (que se localiza en las cordenadas x,y), cae dentro del radio de alguna zona y en caso de que caiga dentro de más de una zona, trata de ver del centro de cual zona está más cerca el cursor.
Esa zona será la que mande para señalar el texto.
Si no está dentro de ninguna zona, el texto es nulo...  

Bueno, y qué pasa cuando haces zoom?....
Simplemente reescala la posición del cursor en función del zoom realizado, es decir si el zoom es anamorfico:
 x = cursor.x / zoom.x
 y = cursor.y / zoom.y
Esto es más sencillo y rápido que recalcular medidas y posiciones de cada zona de la imagen. Es decir retrotraes la posición actual del cursor al equivalente a si el zoom fuera del 100%. y son esos valores los que debiera recibir la función de detección...
o bien recalcularlo dentro de la propia función, etc.. al gusto.

Y eso es todo, te toca pasar a código de Fox Pro o de VB6, de cualquiera de las 2 soluciones propuestas con pesudocódigo.




p.d.: Por cierto este tema, no va aquí si no en programación. Software es mas bien refrido a programas ya hechos, no a los que hace uno mismo...
A ver si un moderador con permisos lo mueve.

Hcrisel

#2
Buenos Días
Hola Serapis, es un gusto conocerte.
El tiempo que te has tomado (nobleza obliga) lo valoro y agradezco inmensamente. Dicho esto te cuento.

Intro: Soy Jefe Técnico de una dependencia de Vialidad Prov. (lo que se conoce como el empleado que pago con mis impuestos). Cuando viene un vecino Rural a pedirnos una máquina para repasarle el camino. Frecuentemente te dice:

Necesito una maquina en el camino de la Laura (todo ok)  ;-)

Pero muchos otros te dicen:
El camino que va a la chacra de Anselmo al lado del campo de Vergara. (¿Qué?)  :o

Pero hombre! ¿Cómo no va a conocer el camino? es allá donde está la curva... donde se volcó el hijo de Laureano.  :o :rolleyes:

Contra esto Google Heart, mucho menos Google map te sirve para nada. Razón por la cual (como Topógrafo, Analista de Sistema, y Tec. En Electrónica Digital) me dije: tendré que juntar todos mis títulos y crearme mi propio Google heart. Como muestra la imagen.



Ahora toda la información que voy recopilando de la gente, lo incorporo en mi Base de Datos. Entonces cuando vengan y me digan. allá donde mataron un ruiseñor de un escopetazo lograré identificar que se refiere al camino 53 Haré clic y sabré:

Cuantas alcantarillas tengo, donde, con las coord. Georeferenciales, fechas en que pasaron las maquinas, etc, etc, etc.

Toda esta información más otra que no menciono; pero que podrías imaginarte es muy valiosa para mi tarea; porque sabría cuales son los caminos que se cortan cuando llovió 30mm, 100mm o 300mm. Lo que me hace "programar estrategias para resolver el problema" sin esperar a que llueva o que me entere quien era el nene que vino borracho con la 4x4 del padre jaja :laugh:.

Ahora bien regresando al punto de la consulta: concluimos que todo está relacionado a un shape transparente con coordenadas pre establecidas conservadas en una matriz bidimensional que interactúa con un Algoritmo encerrado en una rutina.

Definida esa función, rutina, librería "casera" sería la única solución. Mientras te escribo estoy viéndola en mi cerebro. Lo que nos permite cambiar la imagen y poner un despiece de un motor y funcionaría perfectamente también. Lo que le da una versatilidad absoluta.

Bien tendré que comprar mucho café, yerba y limpiar mi cenicero. Te agradezco mucho tu comentario corroboraste mis miedos. Habrá que hacerlo a pulmón.

Un cordial saludo y como dije ante un gusto de haberte conocido.

No tengo idea porque no se ve la imagen Este es el Link: https://ibb.co/JckD9b2