lunes, 30 de mayo de 2011

Tiempos - Usando la PixelFly programáticamente

Similar al caso de la Pulnix, se escribe código usando la API provista para PixelFly y se miden los tiempos aproximados. En este caso se cuenta con dos APIs a utilizar: la original de la cámara (para VC++) y un SDK unificado para las PixelFly y las Sensicam llamado Uniform SDK. Se opta por el último por tener una interfaz más clara y no requerir elementos de WinApi para funcionar; según la documentación esta interfaz es más lenta que la original, pero igualmente sirve para computar órdenes de magnitud.

Resultados:
  • Snapshots tomados: 200
  • fps entre Snapshots: 50
  • Tiempo Total: 4000ms
  • Tiempo Promedio: 20 ms (es decir, 50 fps)
Misma conclusión que la obtenida con la Pulnix: transferencia despreciable. Igualmente seguimos teniendo el doble del tiempo previsto para la toma de fotos.
Afortunadamente, la PixelFly presenta una opción de binning que puede reducir los tiempos empleados. El binning consiste en realizar algún procesamiento sobre un conjunto de píxeles y generar un único píxel que contiene información de los anteriores. En el común de los casos la operación consiste en promediar los valores.
Los nuevos resultados:

  • Snapshots tomados: 200
  • fps entre Snapshots: ?
  • Tiempo Total: 2000ms
  • Tiempo Promedio: 10 ms (es decir, 100 fps)
 Conclusión: ya tenemos el tiempo que queríamos !!
Al parecer el binning permite incluso que la cámara tome fotografías en una frecuencia más alta. Queda pendiente evaluar la capacidad de double shutter.
    Aquí el código:


       1:  #define GAIN 1
       2:  #define DELAY 0 //ms
       3:  #define EXPOSURE_TIME 5 //ms
       4:  #define ROIX 2 //from 1 to 20
       5:  #define ROIY 2 //from 1 to 20
       6:   
       7:  int main(int argc, char* argv[]) {
       8:      int totalSnapshots;
       9:      std::cout << "Qty of snapshots to take: ";
      10:      std::cin >> totalSnapshots;
      11:      
      12:      int camId;
      13:      CAMINFO camData[8];
      14:   
      15:      int boardNumber = 0;
      16:      int error;
      17:      if (error = SELECT_CAMERA("pixelfly", boardNumber, &camId, camData))
      18:          showErrorAndClose(error);
      19:      else {
      20:          if (error = SETUP_CAMERA(camId, camData, 0, 0, 0, 1, ROIX, 1, ROIY, 1, 1, GAIN, DELAY, EXPOSURE_TIME))
      21:              showErrorAndClose(error);
      22:          else {    
      23:              time_t beginTime, endTime;
      24:              time(&beginTime);
      25:      
      26:              int snapshotNumber = 0;
      27:              while (! error && snapshotNumber < totalSnapshots) {
      28:                  if (error = SNAP(camId, camData, 0))
      29:                      showErrorAndClose(error);
      30:                  else {
      31:                      if (error = GETIMAGE(camId, camData, 2000))
      32:                          showErrorAndClose(error);
      33:                      else 
      34:                          // image in memory at this point
      35:                  }
      36:                  snapshotNumber++;
      37:              }
      38:              time(&endTime);
      39:              std::cout << std::endl << "Tiempo Promedio por imagen: " << 1000.0 * (double)difftime(endTime, beginTime) / (float)totalSnapshots << "ms." << std::endl;
      40:          }
      41:          CLOSE_CAMERA(camId, camData);
      42:      }
      43:      return 0;
      44:  }

    miércoles, 25 de mayo de 2011

    Tiempos - Usando la Pulnix programáticamente

    Código feo... necesitamos saber si el tiempo de transferencia de la Pulnix con la placa adquisidora es suficiente para alcanzar los 100 fps.
    Usamos la API de Imagenation (muy vieja pero efectiva). Sacamos N snapshots y medimos el tiempo entre cada una de ellas usando time().
    Resultados:
    • Snapshots tomados: 120
    • fps entre Snapshots: 30
    • Tiempo Total: 4000ms
    • Tiempo Promedio: 33.3ms (es decir, 30 fps)

    Conclusión: el tiempo de transferencia es despreciable o bien se compenza con el tiempo de toma de la próxima foto.

    Aquí un snippet del código:


       1:  int main(int argc, char* arg[])
       2:  {
       3:      PXD pxd;
       4:      FRAMELIB frameLib;
       5:      long hFG=0;
       6:      char arcFileName[20];
       7:      static int num=0;
       8:      
       9:      int NO_FRAMES;
      10:      std::cout << "Ingrese el Nro de imágenes a capturar (30 fps)"; std::cin >> NO_FRAMES;
      11:   
      12:      imagenation_OpenLibrary("PXD_32.DLL", &pxd, sizeof(PXD));
      13:      imagenation_OpenLibrary ("frame_32.dll", &frameLib, sizeof(FRAMELIB));
      14:   
      15:      
      16:      //"tm-9701 progressive free-run.cam";
      17:      char configFile[] = {"C:\\PXD\\bin\\default.cam"};
      18:      hFG= pxd.AllocateFG (-1);
      19:   
      20:      CAMERA_TYPE *configInMem = pxd.LoadConfig(configFile);
      21:      pxd.SetCameraConfig(hFG,configInMem);
      22:      pxd.FreeConfig(configInMem);
      23:      time_t beginTime, endTime;
      24:      printf("Inicio de Captura %d imagenes \n\n",NO_FRAMES);
      25:      time(&beginTime);
      26:      for(num= 0; num {
      27:          time(&captureTime);
      28:          FRAME* pFRAME = pFRAME = pxd.AllocateBufferList (pxd.GetWidth(hFG), pxd.GetHeight(hFG), pxd.GetPixelType(hFG), 1 /*solo un frame*/);
      29:          pxd.Grab (hFG, pFRAME,IMMEDIATE);
      30:          sprintf(arcFileName,"30fps%.3d.bmp", num);
      31:          frameLib.ExtractPlane(pFRAME,1);
      32:          //frameLib.WriteBMP ( frameLib.ExtractPlane(pFRAME,1), arcFileName,1);
      33:          frameLib.FreeFrame (pFRAME);
      34:      }
      35:   
      36:      time(&endTime);
      37:      std::cout << std::endl << "Tiempo Promedio por imagen: " << 1000.0 * (double)difftime(endTime, beginTime) / (float)NO_FRAMES << "ms." << std::endl;
      38:      pxd.FreeFG (hFG);
      39:      return 0;
      40:  }
      41:      
      42:      

    miércoles, 4 de mayo de 2011

    Eligiendo la cámara

    Como ya se comentó, es necesario tomar imágenes del sistema bajo estudio para realizar ciertos chequeos y de esa forma alimentar al lazo cerrado. Por lo tanto, el siguente paso será realizar mediciones mediante las distíntas cámaras que se poseen en el laboratorio. Como siempre, realizamos una tabla comparativa:

    Nombre Tipo Resolución Max FPS Cropping / ROI Buffer / Tipo de Transferencia Url
    PXD Frame Grabber Family - Cyber Optics Placa Adq. 32Kx32K 160 (512x512 con 32bits) Si Interfaz  propietaria Link
    PixelFly qe - Cooke Coroporation Cámara 640x480 50 Si Sin buffer. Transf. directa por RJ45 en placa Adq. propietaria Link
    SpeedCam Mini Vis e2 - Weinberger Cámara 512x512 2500 Si2GB buffer. Luego Transf. por placa Ethernet 1 Gbit Link
    TM-9701 - Pulnix Cámara 768x484 30 No Sin buffer. Transf. directa por placa Adq. PXD Link

    Si bien la SpeedCam Minivis es la mejor cámara de las tres disponibles, la mejor opción siempre depende de las características que se necesiten.

    En nuestro caso particular son:

    1. Debe ser programable.
    2. Se necesitan frames con una Dif. de tiempo menor a 10ms. Es decir, 100 fps.
    3. Si bien la Dif. entre frames debe ser menor a 10ms, se puede aceptar un tiempo de transferencia un tanto mayor pero que permita procesar frames de a pares, retornar respuesta al sistema y volver a pedir un par de frames.
    4. Tanto la luminosidad como la resolución no son factores importantes.
    Lamentablemente, los puntos 1 a 3 deben ser confirmados empíricamente con lo cual se demora la elección hasta tener información en el campo práctico sobre todas las cámaras.