Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Gráficos
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 21-03-2007
rochi rochi is offline
Miembro
 
Registrado: nov 2004
Ubicación: mvd, uruguay
Posts: 57
Poder: 20
rochi Va por buen camino
Question Pixles por mm en una imágen

Hola tengo el siguiente problema, quiero calcular la relación pixel por mm de un bmp que está en un TImage. La idea es que el usuario pueda trazar rectas, calcular ángulos, distancias entre puntos, entre puntos y rectas, etc.
Antes de googlear, obtenía esa relación marcando 2 ptos de la imágen e indicando a cuántos mm correspondía. Mediante regla de 3, sacaba la relación, y aplicaba ese factor escala a todas las medidas obtenidas y asi daba el resultado esperado en todos los cálculos.

Quise hacerlo mas automático, sin que el usuario tenga que conocer la distancia, que marque 2 puntos y obtener la información automáticamente a cuantos mm corresponde. Encontré varios links, y opté por aplicar lo leido, pero no me anda, me da una diferencia de unos 2mm, y no se si lo aplico
bien.
Resumo la idea de lo que hago, dados 2 puntos, calculo la distancia en X y en Y que los separa en pixels P1(x1,y1) y P2(x2,y2), deltaX = x2 - x1, idem para y. Esas distancias corresponden a los catetos de un triángulo rectángulo, luego convierto las mismas a mm, obteniendo los 'catetos en mm'. Aplico Pitágoras para obtener la distancia en pixels y mm, ahí tengo la relación mm/pixels.

Código Delphi [-]
img:TImage // contiene al bitmap

// Relación horizontal entre pixels y mm
function TCmdCalcEscala.PixelHorizToMM(deltaX: Double): Double;
var
  hdcDesk:HDC;
Begin   
 
  hdcDesk:= img.Bitmap.Canvas.Handle; // Antes hdcDesk:= img.Canvas.Handle;

  try
     result:= deltaX * (GetDeviceCaps(hdcDesk, HORZSIZE) / GetDeviceCaps(hdcDesk, HORZRES));
  finally
     ReleaseDC(hdcDesk, hdcDesk);
  end;
End;

// Relación vertical entre pixels y mm
function TCmdCalcEscala.PixelVertiToMM(deltaY: Double): Double;
var
  hdcDesk:HDC;
Begin
 
  hdcDesk:= img.Bitmap.Canvas.Handle;

  try
     result:= deltaY * (GetDeviceCaps(hdcDesk, VERTSIZE) / GetDeviceCaps(hdcDesk, VERTRES));
  finally
     ReleaseDC(hdcDesk, hdcDesk);
  end;
End;


// X distancia horizontal, Y distancia vertical
function TCmdCalcEscala.distancia(X,Y: Double): Double;
Begin  
  result:=Abs(Sqrt(Sqr(x) + Sqr(y)));
End;


function TCmdCalcEscala.deltaPixels(X,Y: Double): Double;
Begin
  result := Abs(X - Y);
End;


//Calcula la relación entre pixels y mm.
procedure TCmdCalcEscala.ejecutar(Pto1:TPuntoVisual;Pto2:TPuntoVisual);
Var 
  distXpixel,distYpixelouble;
  distXmm,distYmmouble;
Begin
   
   distXpixel := deltaPixels(pto1.x,pto2.x); // Distancia horizontal
   distYpixel := deltaPixels(pto1.y,pto2.y); // Distancia vertical

   //Paso a mm esas distancias
   distXmm := PixelHorizToMM(distXpixel);
   distYmm := PixelVertiToMM(distYpixel);
   
   //DistPixel, Distmm, FactorEscala son propiedades de TCmdCalcEscala   
   DistPixels := distancia(distXpixel,distYpixel);
   Distmm := distancia(distXmm,distYmm);
   FactorEscala := Distmm/DistPixels;
End;

A DistPixels, le corresponden Distmm, obvio para comprobar yo se cuanto vale Distmm, bueno, con esto no anda. Aclaro que antes al GetDeviceCaps le pasaba el handle de la pantalla, tampoco andaba asi.

Les agradezco cualquier sugerencia, componente, o link.
Saludos, rochi

Última edición por rochi fecha: 21-03-2007 a las 01:10:18.
Responder Con Cita
  #2  
Antiguo 21-03-2007
Avatar de seoane
[seoane] seoane is offline
Miembro Premium
 
Registrado: feb 2004
Ubicación: A Coruña, España
Posts: 3.717
Poder: 24
seoane Va por buen camino
Aclarame una duda que tengo, ¿donde mides la distancia "real"? ¿imprimes la imagen y la mides con una regla? o lo haces sobre la propia pantalla
Responder Con Cita
  #3  
Antiguo 21-03-2007
rochi rochi is offline
Miembro
 
Registrado: nov 2004
Ubicación: mvd, uruguay
Posts: 57
Poder: 20
rochi Va por buen camino
Hola, la 'medida real' la mido sobre la imágen real, a priori de escanear la imágen. Luego marco los puntos correspondiente al segmento medido, y asi calculo la escala (x distancia en pixels -> distenMM). Esa es la forma rústica de hacerlo, pero quiero sacar esta responsabilidad del usuario, y obtenerla desde el bmp propiamente dicho. Buscando encontré GetDeviceCaps una función de las APIs que puede dar la cantidad de pixels o mm vertical y horizontal del dispositivo en cuestión, en mi caso, la imágen.

Si alguien sabe como...

Saludossss

Última edición por rochi fecha: 21-03-2007 a las 02:41:12.
Responder Con Cita
  #4  
Antiguo 21-03-2007
Avatar de seoane
[seoane] seoane is offline
Miembro Premium
 
Registrado: feb 2004
Ubicación: A Coruña, España
Posts: 3.717
Poder: 24
seoane Va por buen camino
Bien, escaneas la imagen. Cuando la escaneas la pasas directamente al programa o la guardas primero en un bmp. Si es lo segundo puedes usar este código:
Código Delphi [-]
procedure GetBitmapInfo(Filename: string; var Info: BITMAPINFOHEADER);
begin
  FillChar(Info,Sizeof(Info),0);
  with TFileStream.Create(Filename,fmOpenRead,fmShareDenyWrite) do
  try
    Seek(Sizeof(BITMAPFILEHEADER),soFromBeginning);
    ReadBuffer(Info,Sizeof(Info));
  finally
    Free;
  end;
end;

// Por ejemplo
var
  Info: BITMAPINFOHEADER;
  Str: string;
begin
  GetBitmapInfo('c:\1.bmp',Info);
  Str:=
    'Ancho = ' + IntToStr(Info.biWidth) + #13 +
    'Alto = ' + IntToStr(Info.biHeight) + #13 +
    'Profundidad en bits = ' + IntToStr(Info.biBitCount) + #13 +
    'Resolucion horizontal = ' + IntToStr(Info.biXPelsPerMeter) + ' Pixeles por metro' + #13 +
    'Resolucion vertical = ' + IntToStr(Info.biYPelsPerMeter) + ' Pixeles por metro' + #13;
  case Info.biCompression of
    BI_RGB: Str:= Str + 'Compresion = Sin comprimir';
    BI_RLE8: Str:= Str + 'Compresion = RL8';
    BI_RLE4: Str:= Str + 'Compresion = RLE4';
    BI_BITFIELDS: Str:= Str + 'Compresion = BITFIELDS';
  end;
  ShowMessage(Str);
end;
si te fijas uno de los parámetros que podemos obtener del bitmap son los "Píxeles por metro", que creo que es lo que estas buscando.

¿Te sirve o buscamos por otro lado?
Responder Con Cita
  #5  
Antiguo 21-03-2007
rochi rochi is offline
Miembro
 
Registrado: nov 2004
Ubicación: mvd, uruguay
Posts: 57
Poder: 20
rochi Va por buen camino
Lightbulb

Muchas gracias seoane, voy a estudiar ese código (desconozco BITMAPINFOHEADER).

Si estoy trabajando con archivos .bmp.

Creo que ya se donde estaba mi error, mi escaso conocimiento de las funciones API tiene mucho que ver. GetDeviceCaps transforma pixels a mm, pero mm de pantalla, que no necesariamente se corresponden con los mm medidos en la imágen sin digitalizar.

O sea que lo que estaba haciendo no tiene sentido si no tengo medidas 'reales'. Ya miro el código para ver si por ahi sale el asunto.

saludos, rochi

Última edición por rochi fecha: 21-03-2007 a las 04:09:58.
Responder Con Cita
  #6  
Antiguo 22-03-2007
rochi rochi is offline
Miembro
 
Registrado: nov 2004
Ubicación: mvd, uruguay
Posts: 57
Poder: 20
rochi Va por buen camino
Hola, no solucionó mi problema, es mas me da mas lejos de lo real, en la versión anterior, al menos obtenía la dist. en mm sobre la pantalla y era correcta. Ahora, ni eso.
Estoy usando una función que retorna elBITMAPINFOHEADER, supuestamente tengo los pixels por metro, ¿metro medido sobre qué?.

Aqui dejo el código:
Código Delphi [-]
Var
  pto1,pto2:TPuntoVisual;

  pixelXpormetro,pixelYpormetro:Integer;

  distXpixel,distYpixel: Double;
  distXmm,distYmm: Double;  
  pixelXpormm,pixelYpormm: Double;
  
Begin

   //función que obtiene dato de tipo BITMAPINFOHEADER    
   getResolucionBitMap(pixelXpormetro,pixelYpormetro);

   // Convierto a cantidad de Pixels por mm    
   pixelXpormm := 0.001*pixelXpormetro;
   pixelYpormm := 0.001*pixelYpormetro;

   imgHdl := fact.getInstanceImgHndl;
   pto1 := imgHdl.getPuntoVisual(p1);
   pto2 := imgHdl.getPuntoVisual(p2);

   // deltaX = Abs(pto1.x - pto2.x)
   distXpixel := deltaPixels(pto1.x,pto2.x);
   distYpixel := deltaPixels(pto1.y,pto2.y);

       
   // Paso la distancia en pixels a mm
   distXmm := distXpixel/pixelXpormm;
   distYmm := distYpixel/pixelYpormm;

  
   // A mm milímetros le corresponden distPixels, distancia = formula Pitágoras

   imgHdl.DistPixels := distancia(distXpixel,distYpixel);
   imgHdl.Distmm := distancia(distXmm,distYmm);
   imgHdl.FactorEscala := (imgHdl.Distmm/imgHdl.DistPixels)*(1.0);
End;
Si alguien sabe que puede pasar, gracias...
Responder Con Cita
  #7  
Antiguo 15-04-2007
rochi rochi is offline
Miembro
 
Registrado: nov 2004
Ubicación: mvd, uruguay
Posts: 57
Poder: 20
rochi Va por buen camino
Hola, que tal? bueno, al final resolví el problema como lo hacía originalmente,
  1. marco 3 puntos en la imagen digitalizada p1,p2,p3 , de modo que formen un angulo recto, p1p2 paralelo al eje Ox y p2p3 al eje Oy.
  2. Ingreso la distancia real en mm entre p1p2 y p2p3.
  3. Calculo la distancia de esos segmentos en pixels, y como la equivalente en mm es conocida por mi (ingresada) obtengo un factor en X y factor en Y.
  4. A cada distancia punto, le multiplico sus cooords. por el factor en X y en Y para obtener el equivalente en mm.
Asi funciona correctamente, medidas de angulos, rectas, proyecciones, etc.
Duda que tengo, mi imagen es un Bitmap, que está dentro de un TImage.
Cambié la resolución de pantalla, y noté que el ancho y alto del objeto TImage y del TBitmap permanecen constantes => los factores de conversión en X y en Y tampoco cambian, aun cuando cambia el valor de Screen.PixelsPerInch. ¿A que se debe eso?
¿El dfm tiene esa información y la usa independientemente de la resolución de la pantalla adaptando (distorcionando) la imagen?
¿Debo controlar la resolución para que no cambie la escala? (aunque no parece haber riesgo).
Entro otras cosas me interesa porque no se si ademas de guardar los factores en X y en Y por imagen, deba guardar la resolución a la que fue hallada.


Saludos, gracias

rochi

Última edición por rochi fecha: 15-04-2007 a las 06:03:26.
Responder Con Cita
  #8  
Antiguo 15-04-2007
rochi rochi is offline
Miembro
 
Registrado: nov 2004
Ubicación: mvd, uruguay
Posts: 57
Poder: 20
rochi Va por buen camino
Me autorespondo, por si le sirve a alguien. Efectivamente la cantidad de pixeles del .bmp no cambia al cambiar la resolución ya que está guardada en el propio bitmap (y en el .dfm si la imagen está en el form).
Asi como el .dfm también guarda información del objeto TImage, que tampoco altera sus dimensiones al cambiar la resolución.

saludos, ro
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Imagen en BDA majosf Conexión con bases de datos 1 13-12-2005 16:17:25
la imagen se ve mal.... User_baja1 Gráficos 0 10-06-2005 16:08:41
Imagen en SQL ramonibk Varios 2 18-02-2005 17:07:50
Borrar una imagen PTW Gráficos 7 27-04-2004 22:19:57
Mantener la imagen muli Varios 1 29-01-2004 11:37:46


La franja horaria es GMT +2. Ahora son las 15:00:23.


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
Copyright 1996-2007 Club Delphi