viernes, 15 de septiembre de 2017

Tutorial para capturar imagenes

En tutoriales anteriores se mostró como se podían generar nubes de puntos, donde realizamos una nube de forma aleatoria. Si embargo, el gran potencial de PCL es realizar tratamiento de nubes de puntos capturadas por un sensor, los cuales pueden ser de muchos tipos pero en nuestro caso realizaremos la captura a partir de una Kinect de XBox.

Para empezar es necesario tener un sensor de profundidad en nuestro caso Kinect para Xbox 360, no se ha comprobado si la siguiente versión es compatible. Tener en cuenta que no funciona con los puertos USB 2.0 (vienen con la parte interior en azul).


En el código que mostraremos hay que tener en cuenta que hay una parte que es para la captura y guardado en archivo PCL y otra que es para visualizar la nube capturada.


 #include <pcl/io/openni_grabber.h>
 #include <pcl/visualization/cloud_viewer.h> 
 #include <pcl/io/pcd_io.h>
 #include <iostream>
 #include <fstream>
 #include <string.h>
 #include <cstring>
 #include <sstream>
 #include <ctime>
 #include <iostream>
 #include <locale>
 #include <time.h>   
 #include <stdio.h> 
 using std::string;
 static unsigned int pcd_count = 1;
  
 class SimpleOpenNIViewer{
   public:
     SimpleOpenNIViewer () : viewer ("PCL OpenNI Viewer") {}

     void cloud_cb_ (const pcl::PointCloud<pcl::PointXYZ>::ConstPtr &cloud)
     {
        std::locale::global(std::locale("es_ES.utf8"));
        std::time_t rawtime;
        struct tm *timeinfo;
        std::time ( &rawtime );
        timeinfo = std::localtime ( &rawtime );
        char archivo[50] ;
 sprintf(archivo, "%d_%d%d%d_%d%d%d_%d",
    timeinfo->tm_wday,1900 + timeinfo->tm_year,
    timeinfo->tm_mon+1,
             timeinfo->tm_mday, timeinfo->tm_hour,
    timeinfo->tm_min, timeinfo->tm_sec,pcd_count );
 std::strcat(archivo,".pcd");
        std::cout<<"estamos en:"<< archivo  <<std::endl;
 
 if (!viewer.wasStopped()){
  viewer.showCloud (cloud) //guardar archivo

  std::cout<<" en archivo"<<archivo <<std::endl;
  pcl::io::savePCDFileASCII (archivo, *cloud);
  std::cerr << "Saved " << cloud->points.size () 
                          << " data points to: "<< archivo  << std::endl;
                pcd_count++;
                boost::this_thread::sleep (boost::posix_time::seconds (3));
        }

 
 
     }

     void run ()
     {
       pcl::Grabber* interface = new pcl::OpenNIGrabber();

       boost::function<void (const pcl::PointCloud<pcl::PointXYZ>::ConstPtr&)> f =
         boost::bind (&SimpleOpenNIViewer::cloud_cb_, this, _1);
       interface->registerCallback (f);
       interface->start ();

       while (!viewer.wasStopped())
       {
         boost::this_thread::sleep (boost::posix_time::seconds (1));
       }

       interface->stop ();
     }

     pcl::visualization::CloudViewer viewer;
 };

 int main ()
 {
   SimpleOpenNIViewer v;
   v.run ();
   return 0;
 }

En la clase SimpleOpenNIViewer  tenemos dos llamadas la primera que es:

 
void cloud_cb_ 
 
nos servirá para visualizar la nube de puntos y guardarla en una archivo, que en nuestro caso será determinado con fecha y hora ademas de un contador global y la segunda que es:

void run ()
 
Será la llamada que nos permita comunicarnos con el sensor para recibir las nubes de puntos y guardarla en un puntero, y así poderla procesar en la llamada anterior. En esta llamada es importante tener en cuenta que para variar el tiempo entre capturas tendremos que realizarlo en la siguiente línea


boost::this_thread::sleep (boost::posix_time::seconds (tiempo_entre_capturas));

Como ejemplo de nube de puntos  mostramos una nube guardada con el nombre 3_2016518_184530_43.pcd