Pages

Thursday 29 August 2013

Meshlab Load Multiple

Quick post about something I've just found out about +MeshLab. I was quickly trying to search for a way to load in multiple point clouds from .ply files into meshlab from the command line.

I'm interested in doing this as I want to trigger meshlab to load a bunch of files from a link in PowerPoint.

To launch external programs/files from PowerPoint...

- Select the text you want to create the link with
- 'Insert Tab'
- In the 'Links' panel click on 'Action'
- Point 'Run program' towards the .exe of the program you wish to launch

With Meshlab it'll look something like this
C:\Program Files\VCG\MeshLab\meshlab.exe pointCloud.ply

The problem was I wanted to load in 3 .ply files. Doing the following just loads in the first point cloud.

C:\Program Files\VCG\MeshLab\meshlab.exe pointCloud1.ply pointCloud2.ply

So the easiest way I can see is to just use a Meshlab project file. You can either load all your point clouds into Meshlab then go to File > Save Project

This creates a .mlp file that contains the following...

<!DOCTYPE MeshLabDocument>
<MeshLabProject>
 <MeshGroup>
  <MLMesh label="PC1.ply" filename="PC1.ply">
   <MLMatrix44>
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
</MLMatrix44>
  </MLMesh>
  <MLMesh label="PC2.ply" filename="PC2.ply">
   <MLMatrix44>
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
</MLMatrix44>
  </MLMesh>
  <MLMesh label="PC3.ply" filename="PC3.ply">
   <MLMatrix44>
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
</MLMatrix44>
  </MLMesh>
 </MeshGroup>
 <RasterGroup/>
</MeshLabProject>

Edit, with your favorite text editor, accordingly with all your .ply files. Then you can direct PowerPoint to
C:\Program Files\VCG\MeshLab\meshlab.exe "C:\work\stuff\projectfile.mlp"

Monday 19 August 2013

Playing with the OpenCV HoG Detector

So... long-time-no-post.

I've just taken my robot for a walk to collect some data, while I wait for the 40GB to copy I thought I'd do a quick post. A few months ago I was playing the HoG detector in +OpenCV and using the PETS2009 data set.

My idea was that I might create a home security system from a bunch of old bits of hardware that are gathering dust.

- 1 x HTC Magic
- 1 x HTC Desire
- 1 x Fat Gecko Suction Mount
- 1 x Old HP Laptop

The plan is to use the two devices as IP Cams using this nifty app. Using the CURL lib I can access the images from C++ really easily and start throwing them at OpenCV

Here's a quick clip of the HoG detector running on the PETS09 data. It's not bad for an out-of-the-box solution.

OpenCV is available for Android so I could try running it directly on the handset, however the Magic isn't the most powerful, neither is the Desire; they are  unlikely to be able to process the images as fast as even a beaten up old lappy.
Now that the images are being fed into OpenCV it's time to think about &nbsp;how I want to process them. Face recognition for the front door? Build a database of visitors? Get it to welcome me home?
Below is the code (mostly taken from CURL examples) to obtain the images from a network location and an example of the OpenCV HoG detector.
struct memoryStruct {
  char *memory;
  size_t size;
};

static void* CURL_realloc(void *ptr, size_t size)
{
  /* There might be a realloc() out there that doesn't like reallocing
     NULL pointers, so we take care of it here */
  if(ptr)
    return realloc(ptr, size);
  else
    return malloc(size);
}

size_t WriteMemoryCallback (void *ptr, size_t size, size_t nmemb, void *data) {
  size_t realsize = size * nmemb;
  struct memoryStruct *mem = (struct memoryStruct *)data;

  mem->memory = (char *)
  CURL_realloc(mem->memory, mem->size + realsize + 1);
  if (mem->memory) {
    memcpy(&(mem->memory[mem->size]), ptr, realsize);
    mem->size += realsize;
    mem->memory[mem->size] = 0;
  }
  return realsize;
}

Mat getNewFrameFromAndroid(CURLcode res, memoryStruct buffer, CURL *curl) {
 while (true) {
   // set up the write to memory buffer
   // (buffer starts off empty)
   buffer.memory = NULL;
   buffer.size = 0;

   curl_easy_setopt(curl, CURLOPT_URL, "http://192.168.0.8:8080/shot.jpg");

   // tell libcurl where to write the image (to a dynamic memory buffer)

   curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
   curl_easy_setopt(curl,CURLOPT_WRITEDATA, (void *) &buffer);

   // get the image from the specified URL
   res = curl_easy_perform(curl);

   // decode memory buffer using OpenCV
   cv::Mat imgTmp;
   imgTmp = cv::imdecode(cv::Mat(1, buffer.size, CV_8UC1, buffer.memory), CV_LOAD_IMAGE_UNCHANGED);

   if (!(imgTmp.empty())) {
    return imgTmp;
   }
 }
}
HOGDescriptor hog;
hog.setSVMDetector(HOGDescriptor::getDefaultPeopleDetector());

vector<Rect> found;
hog.detectMultiScale(img, found, 0, Size(8,8), Size(32,32), 1.05, 2);