Pages - Menu

Saturday, March 27, 2010

Ford Figo : Interactive Advertising using QR Code

Ford Figo have released an interactive application for mobiles to publicize the car. The app. is developed by company called TELibrahma (India). The ad appeared on Times of India Newspaper (Bangalore) on March 15th. 


The app. plays 3GP video when it detects a QR Code which decodes to "Figo".The video below shows how it works.Try it out!!!


Links:


Times of India (March 15th- ePaper)
http://epaper.timesofindia.com/Default/Client.asp?skin=pastissues2&enter=LowLevel&AW=1269699751437


TELiBrahma
http://www.telibrahma.com/
Latest news:
http://telibrahmaindia.blogspot.com/


Video:



Image:

2D Barcodes: From Data Matrix to QR Code

... What once was a method used for sorting/branding/labeling a product is now become the a must have for techno-junkies. The 2D bar code or otherwise known has the Data Matrix, have become increasingly popular thanks to the surge of QR Codes. The biggest step was indeed making it available on a mobile platform. Here is quick look at some of them- 


Numerous QR marker Readers:

1.       Kaywa Reader
                This site has an online marker generation facility and also provides marker reading software for mobile phones.

Enter the following site from your mobile to download this application:
                                                            
2.       3GV-Vision
                This site too has an online marker generation facility and marker reader for mobile phones.

Enter the following site from your mobile to download this application:

3.       BeQRious
Online QR Code generator.

4.       QR Code
Online QR Code generator.

5.       TAG.CX
Online QR Code & Data matrix generator.

6.       Mobile Codes by Nokia
                This site has an online marker generation facility and marker reader for Nokia mobiles.

7.       Semapedia
                A quick linking method for Wikipedia Content .


Special Codes:
1.       Qode

Enter the following site from your mobile to download this application:

2.       Trillcode
Enter the following site from your mobile to download this application:

3.       Upcode:
                This site hosts reader for special codes called Upcode, similar to Data matrix. Upcode generator not available [?].

Enter the following site from your mobile to download this application:

4.       QuickMark
                This site hosts a wide variety of QR Codes. It also provides the SDK and API for developers.
It not only has support for markers like QR Code and Data Matrix but also its own variety called QuickMark. Additionally there is also code reading software for PC.

5.       Beetagg
                This site hosts online generator for QR Codes, Data Matrix and a special code called Beetagg.

Enter the following site from your mobile to download this application:

6.       Microsoft Tag
                A Microsoft Tag is a machine readable web link, when read, the Tag application sends the HCCB (High Capacity Color Barcode) data to a Microsoft server, which then returns the publisher's intended URL. The Tag reader then directs the user's mobile browser to the appropriate website. Now in beta stage, the creation of tags for both commercial and noncommercial use is also free.

Use/Create a Microsoft account and Generate/Manage Tags here-

Enter the following site from your mobile to download this application:

Development:

1.       libdecodeqr
                This is a C/C++ library for decoding QR code based on JIS X 0510 and ISO/IEC18004.
This library is able to decode various image formats whether it's taken from a file, webcam, scanner, or any other image formats available. Best of all, it is based in OpenCV [Yessiree!!!]

2.       libqrencode
                libqrencode is a C library for encoding data in a QR Codes.

3.       Open Source QR Code Library
                This project develops and distributes QR Code decode/encode library under GPL v2.

4.       QRCode library
The library can be used in any .NET 3.5 Windows Application, ASP.NET web application or Windows Mobile device application.

messagingtoolkit-qrcode
This project is the enhancement of the above open source project for QRCode.

                A  library for using the Open Source QR Code library in Processing (Processing is a programming language).

6.       pyqrcode
                This is about a python extension for encoding and decoding the QR Code.


More about 2D Codes:


Image:

Sunday, March 21, 2010

Augmented Coliseum from Inami Laboratory

... Think about controlling robots using projectors or displays like Microsoft surface and simultaneously track them... this is so cool!!


Video:

Friday, March 19, 2010

OpenCV: Pseudo Coloring

Download the Project folder and the source code [2.62 Mb].



**UPDATE**
Please Change the Code from:


ptr_d[3*x] = (int) (temp * 255/180);
to

ptr_d[3*x] = (int) (temp * 255/60);
in line 108, as show below. This improves the upper end of thermal image.





Sample Code:


//______________________________________________________________________________________
// OpenCV Pseudo Coloring of Images
// Author: Bharath Prabhuswamy
//______________________________________________________________________________________
//______________________________________________________________________________________

#include "cv.h"
#include "highgui.h"
#include <stdio.h>
#include <math.h>

int main()
{
        IplImage* img  = cvLoadImage("thermal.jpg");
 int flag;
 
 /* Always check if the program can find a file */
 if( !img ) 
   return -1;

 IplImage* gray = cvCreateImage( cvGetSize(img), 8, 1 );
 IplImage* disp = cvCreateImage( cvGetSize(img), 8, 3 );
 cvZero(disp);

 /*Convert the image to gray*/
 cvCvtColor(img,gray,CV_RGB2GRAY);

 uchar* ptr_d;
 uchar* ptr_g;
 int temp;

 printf("Select an option for Colouring -\n");
 printf("1.MRI Scan\n");
 printf("2.Thermal Image\n");
 scanf("%d",&flag);

 /*Check if the user selects a valid option */
 if(flag !=1 && flag !=2)
 {
  printf("Invalid Input\n");
  printf("Application Exit\n");
  return -1;
 }
  
 for( int y=0; y<gray->height; y++) 
 {
  ptr_g = (uchar*) (gray->imageData + y * gray->widthStep);
  ptr_d = (uchar*) (disp->imageData + y * disp->widthStep);
   
  for(int x=0; x<img->width; x++ ) 
  {
   /*The option is MRI */
   if(flag ==1)
   {
 //Colour pixels that Black and fade to Blue
    if(ptr_g[x] < 25)                          
    {
     temp = ptr_g[x];
     ptr_d[3*x+2] = 0;
     ptr_d[3*x+1] = 0;
     ptr_d[3*x] = (int) (temp * 255/25);
    }
    else
    {
     temp = ptr_g[x] - 25;
//Colour pixels that nearly Grey to Blue and then fade to Green 
     if(temp >=0 && temp < 115)     
                                        //
     {
      ptr_d[3*x+1] = (int) (temp * 255/115);
      ptr_d[3*x] = 255 -(int) (temp * 255/115);
     }
//Starting From Green,Colour pixels that nearly White to Red 
     else if(temp >=116 && temp <= 230)   
     {
      temp = ptr_g[x] - 115;
      ptr_d[3*x+2] = (int) (temp * 255/115);
      ptr_d[3*x+1] = 255 -(int) (temp * 255/115);
     }
    }
   }
   else
   {
//Colour pixels that Black and fade to Purple
    if(ptr_g[x] < 15)      
    {
     temp = ptr_g[x];
     ptr_d[3*x+2] = (int)(temp * 90/15);
     ptr_d[3*x+1] = 0;
     ptr_d[3*x] = (int)(temp * 90/15);
    }
    else
    {
     temp = ptr_g[x] - 15;
//Colour pixels that nearly Grey to Purple and fade to Yellow
     if(temp >=0 && temp < 180)   
     {
      ptr_d[3*x+2] = (int)(90 + (temp * 155/180));
      ptr_d[3*x+1] = (int)(temp * 255/180);
      ptr_d[3*x] = (int)(90 - (temp * 90/180));
     }
//Starting From Yellow,Colour pixels that nearly White to White itself 
     else if(temp >=180 && temp <= 240) 
     {
      temp = ptr_g[x] - 180;
      ptr_d[3*x+2] = 255;
      ptr_d[3*x+1] = 255;
      ptr_d[3*x] = (int) (temp * 255/60);
     }
    }

   }
  }
  
 }

 /* create a window to show the coloured image */
 cvNamedWindow( "Display", 1 );
 cvShowImage( "Display",disp);
 
 /* Save the coloured image if needed*/
 //cvSaveImage("output.jpg",disp);
 cvWaitKey(0);

 cvDestroyWindow( "Display" );
    cvReleaseImage( &img );

    return 0;
}




Images:


OpenCV: Pseudo Coloring of Images

Somehow I have fallen in love with Thermal Imaging. It is quite fascinating to see things differently via Infrared or Thermal Camera. I also like TEM,SEM and AFM (-microscopes) images which reveal a world of its own.


The key to carry out image manipulation such as this, lies in the method in which data is stored in memory and how these values are interpreted. Generally the pixel values of a Image is stored as a Single dimensional array in the memory. However complication/confusion arise when the image is multi channel.Ex: an RGB image.
If a 100x100 px Binay Image is present then it is clear that 100 x 100 = 10000 bits of linear space in memory is required.But if 100x100 px RGB image is to stored, then 100 x 100 x 3(for the channels R,G,B) x  n( Number of bits required to represent the max value) = 30000n bits are required.


The following Diagram explains clearly the arrangement in memory and how a single-channel pixels are mapped to multi-channel pixels.


Image:

Simplest Line follower ::Bruno - The Brainless Bot

With heaps an heaps of websites and forums boasting about robots, one should really feel annoyed. If you like building robots and want something simple to start, here is a solution.


Ashwith, my friend and classmate, has been helping many juniors interested in robotics. His page shows you how to build this simple robot.


http://sites.google.com/site/ashwith/projects/the-simplest-line-follower
http://ashwith.wordpress.com/2010/03/16/the-simplest-line-follower/


This bot is the simplest of all! You just have to solder correctly according to the circuit diagram & works really well. Once you get the hang of this bot, you can introduce a controller in between the motors drives to increase the abilities of your bot.  


Build it Today!!


Objects:

Monday, March 8, 2010

Android Application Icons Set Part 2 !!

I'll tell you... Android is a way of  life !!! I cant stop admiring it myself... :)


Object:

Android Icons Set 2 by ~bharathp666 on deviantART

Friday, March 5, 2010

More blob inventions

Ever interested in owning a Microsoft Surface of your own? Yes, atleast you can make your own.
So if you think you can handle blobs then probably multi-touch is just a finger length away. I would suggest the CCV, touchlib and a whole bunch of multi-touch FLASH applications via NUI (Natural User Interface). Totally awesome tools !!


Do watch the video...


Links:
http://www.nuigroup.com/


Video:

Blob pointer using OpenCV & cvblobslib

Well... i had time to waste on this :P....


Download the source here:
Blob pointer [Source code] 4.61 Mb


Source:


//______________________________________________________________________________________
// OpenCV cursor movent using Blobs
// Author: Bharath Prabhuswamy
//______________________________________________________________________________________
//______________________________________________________________________________________
#include <stdio.h>
#include "cv.h"
#include "highgui.h"
#include "BlobResult.h"

int main()
{
    CvCapture *capture = 0;
    IplImage  *img = 0;
 IplImage  *gray_img = 0;
 IplImage  *thres_img = 0;
    IplImage  *blobs_img = 0;
 int key = 0;
 
    /* Initialize the webcam */
    capture = cvCaptureFromCAM( 0 );
 
    /* Always check if the program can find a device */
    if ( !capture ) 
        return -1;
 
 CBlobResult blobs;
 CBlob *currentBlob;
 CvRect rect;

 int frame_count = 0;
 int i = 0;

 int screen_x = GetSystemMetrics(SM_CXSCREEN);
 int screen_y = GetSystemMetrics(SM_CYSCREEN);
 int mouse_x,mouse_y;
 double x=0;
 double y=0;
 
    /* create a window for the video */
 cvNamedWindow( "Blobs",CV_WINDOW_AUTOSIZE);
 //cvNamedWindow( "Thres",CV_WINDOW_AUTOSIZE);
 
 /* Create required images once */
 if( frame_count == 0 )
    {
        /* Obtain a frame from the device */
        img = cvQueryFrame( capture );

  /* Always check if the device returns a frame */
  if( !img ) 
   return -1;

  gray_img  = cvCreateImage( cvGetSize(img), img->depth, 1);
  thres_img = cvCreateImage( cvGetSize(img), img->depth, 1);
  blobs_img = cvCreateImage( cvGetSize(img), img->depth, 3);
 }
 
    while((char) key != 27 )
    {
        /* Obtain a frame from the device */
        img = cvQueryFrame( capture );

  /* Always check if the device returns a frame */
  if( !img ) 
   return -1;
  
  frame_count = frame_count + 1;
  
  /* Flip image once, after blob processing it is flipped back */
  cvFlip(img,img,NULL);

  /* Convert image from Color to grayscale and 
                   then to binary (thresholded at 180) */
  cvCvtColor(img,gray_img,CV_RGB2GRAY);
  cvThreshold(gray_img,thres_img,200,255,CV_THRESH_BINARY);
  
  /* Find Blobs that are White, Hence 'uchar backgroundColor = 0' (Black) */
  blobs = CBlobResult(thres_img, NULL,0);

  /* Remove blobs if it does not cover minimum area specified below */
  blobs.Filter( blobs, B_EXCLUDE, CBlobGetArea(),B_LESS,5,50);

  /* Number of blobs */
  int j = blobs.GetNumBlobs();
  printf("%d\n",j);
  
  /* 'i' points to blob 0, i.e., first blob */
  /* If some blobs are detected then find the first blob */
  if(i==0 && blobs.GetNumBlobs()>i)
  {
   currentBlob = blobs.GetBlob(i);
   rect = currentBlob->GetBoundingBox();
   x = currentBlob->MinX();
   y = currentBlob->MinY();
   //printf("%d    %d\n",x,y);

   /* Scale the capture size to the Screen 
                        resolution and set the cursor location */
   mouse_x = (int) x*screen_x/img->width;
   mouse_y = (int) y*screen_y/img->height;
   SetCursorPos(mouse_x,mouse_y);

   /* Color the blob*/
   currentBlob->FillBlob( blobs_img, CV_RGB(255,0,0));
  }

  cvShowImage( "Blobs",blobs_img);
  //cvShowImage( "Thres",thres_img);
  
  /* Clear image for next iteration */
  cvZero(blobs_img);
  
  /* Quit execution if 'ESC' key is pressed */
  key = cvWaitKey(1);
 }

 /* Clean up memory */
 cvDestroyWindow( "Blobs" );
    cvReleaseCapture( &capture );
    return 0;
}
Video:

Image:

Camera Calibration using OpenCV

Here is a simple test by which you can look into the parameters of your camera and correct any distortions.

The entire program is as is from the O'Reilly book [link].


The method used is based on pin-hole camera model, correcting intrinsic deviations and also distortions like radial and tangential.


Some of the links which you might be interested in:
Wikipedia     [link]
Zhengyou Zhang: A Flexible New Technique for Camera Calibration    [link]

Jean-Yves Bouguet : (Matlab)    [link]

Download the source code along with the calibration patterns here:

#include <cv.h>
#include <highgui.h>
#include <stdio.h>
#include <stdlib.h>

int n_boards = 0;  //Number of snapshots of the chessboard
int frame_step;   //Frames to be skipped
int board_w;   //Enclosed corners horizontally on the chessboard
int board_h;   //Enclosed corners vertically on the chessboard
int main() 
{
 CvCapture* capture;

 printf("Enter the numbers of spanspots = ");
 scanf("%d",&n_boards);
 
 printf("\rEnter the numbers of frames to skip = ");
 scanf("%d",&frame_step);

 board_w  = 9;
 board_h  = 6;
  
 int board_total  = board_w * board_h;          //Total enclosed corners on the board
 CvSize board_sz = cvSize( board_w, board_h );

 capture = cvCreateCameraCapture( 0 );
 if(!capture) 
 { 
  printf("\nCouldn't open the camera\n"); 
  return -1;
 }

 cvNamedWindow( "Snapshot" );
 cvNamedWindow( "Raw Video");

 //Allocate storage for the parameters according to total number of 
        //corners and number of snapshots
 CvMat* image_points      = cvCreateMat(n_boards*board_total,2,CV_32FC1);
 CvMat* object_points     = cvCreateMat(n_boards*board_total,3,CV_32FC1);
 CvMat* point_counts      = cvCreateMat(n_boards,1,CV_32SC1);
 CvMat* intrinsic_matrix  = cvCreateMat(3,3,CV_32FC1);
 CvMat* distortion_coeffs = cvCreateMat(4,1,CV_32FC1);

 //Note:
 //Intrinsic Matrix - 3x3 Lens Distorstion Matrix - 4x1
 // [fx 0 cx]              [k1 k2 p1 p2   k3(optional)]
 // [0 fy cy]
 // [0  0  1]


 CvPoint2D32f* corners = new CvPoint2D32f[ board_total ];
 int corner_count;
 int successes = 0;
 int step, frame = 0;

 IplImage *image = cvQueryFrame( capture );
 IplImage *gray_image = cvCreateImage(cvGetSize(image),8,1);    //subpixel

 //Loop while successful captures equals total snapshots
 //Successful captures implies when all the enclosed corners 
        //are detected from a snapshot

 while(successes < n_boards)     
 {
  if((frame++ % frame_step) == 0)                             
                //Skip frames
  {
   //Find chessboard corners:
   int found = cvFindChessboardCorners(image, 
                                     board_sz, corners,&corner_count,
                               CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_FILTER_QUADS );

   cvCvtColor(image, gray_image, CV_BGR2GRAY);           
                        
                        //Get Subpixel accuracy on those corners
   cvFindCornerSubPix(gray_image, corners, corner_count, 
                                             cvSize(11,11),cvSize(-1,-1), 
                               cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 30, 0.1 ));

   cvDrawChessboardCorners(image, board_sz, corners, corner_count, found);   
                        //Draw it
   
   // If we got a good board, add it to our data
   if(corner_count == board_total) 
   {
    cvShowImage( "Snapshot", image );            
                                //show in color if we did collect the image
    step = successes*board_total;
    for( int i=step, j=0; j<board_total; ++i,++j ) {
    CV_MAT_ELEM(*image_points, float,i,0) = corners[j].x;
    CV_MAT_ELEM(*image_points, float,i,1) = corners[j].y;
    CV_MAT_ELEM(*object_points,float,i,0) = (float) j/board_w;
    CV_MAT_ELEM(*object_points,float,i,1) = (float) (j%board_w);
    CV_MAT_ELEM(*object_points,float,i,2) = 0.0f;
   }
   CV_MAT_ELEM(*point_counts, int,successes,0) = board_total;    
   successes++;
   printf("\r%d successful Snapshots out of %d 
                                        collected.",successes,n_boards);
   }
   else
   cvShowImage( "Snapshot", gray_image );          
                        //Show Gray if we didn't collect the image
  } 
  
  //Handle pause/unpause and ESC
  int c = cvWaitKey(15);
  if(c == 'p')
  {  
   c = 0;
   while(c != 'p' && c != 27)
   {
    c = cvWaitKey(250);
   }
  }
  if(c == 27)
   return 0;

  image = cvQueryFrame( capture );        
                //Get next image
  cvShowImage("Raw Video", image);
 } 

 //End WHILE loop with enough successful captures

 cvDestroyWindow("Snapshot");

 printf("\n\n *** Calbrating the camera now...\n");
 
 //Allocate matrices according to successful number of captures
 CvMat* object_points2  = cvCreateMat(successes*board_total,3,CV_32FC1);
 CvMat* image_points2   = cvCreateMat(successes*board_total,2,CV_32FC1);
 CvMat* point_counts2   = cvCreateMat(successes,1,CV_32SC1);

 //Tranfer the points to matrices
 for(int i = 0; i<successes*board_total; ++i)
 {
      CV_MAT_ELEM( *image_points2, float, i, 0) = CV_MAT_ELEM( *image_points, float, i, 0);
      CV_MAT_ELEM( *image_points2, float,i,1)   = CV_MAT_ELEM( *image_points, float, i, 1);
      CV_MAT_ELEM(*object_points2, float, i, 0) = CV_MAT_ELEM( *object_points, float, i, 0) ;
      CV_MAT_ELEM( *object_points2, float, i, 1)= CV_MAT_ELEM( *object_points, float, i, 1) ;
      CV_MAT_ELEM( *object_points2, float, i, 2)= CV_MAT_ELEM( *object_points, float, i, 2) ;
 } 
 
 for(int i=0; i<successes; ++i)
 { 
      CV_MAT_ELEM( *point_counts2, int, i, 0)= CV_MAT_ELEM( *point_counts, int, i, 0);   
             //These are all the same number
 }
 cvReleaseMat(&object_points);
 cvReleaseMat(ℑ_points);
 cvReleaseMat(&point_counts);

 // Initialize the intrinsic matrix with both the two focal lengths in a ratio of 1.0

 CV_MAT_ELEM( *intrinsic_matrix, float, 0, 0 ) = 1.0f;
 CV_MAT_ELEM( *intrinsic_matrix, float, 1, 1 ) = 1.0f;

 //Calibrate the camera
 //______________________________________________________
 
 cvCalibrateCamera2(object_points2, image_points2, point_counts2,  
                           cvGetSize( image ), 
                           intrinsic_matrix, distortion_coeffs, NULL, NULL,0 );
                                           
//CV_CALIB_FIX_ASPECT_RATIO
 //______________________________________________________

 //Save values to file
 printf(" *** Calibration Done!\n\n");
 printf("Storing Intrinsics.xml and Distortions.xml files...\n");
 cvSave("Intrinsics.xml",intrinsic_matrix);
 cvSave("Distortion.xml",distortion_coeffs);
 printf("Files saved.\n\n");

 printf("Starting corrected display....");

 //Sample: load the matrices from the file
 CvMat *intrinsic = (CvMat*)cvLoad("Intrinsics.xml");
 CvMat *distortion = (CvMat*)cvLoad("Distortion.xml");

 // Build the undistort map used for all subsequent frames.

 IplImage* mapx = cvCreateImage( cvGetSize(image), IPL_DEPTH_32F, 1 );
 IplImage* mapy = cvCreateImage( cvGetSize(image), IPL_DEPTH_32F, 1 );
 cvInitUndistortMap(intrinsic,distortion,mapx,mapy);

 // Run the camera to the screen, showing the raw and the undistorted image.

 cvNamedWindow( "Undistort" );
 while(image) 
 {
  IplImage *t = cvCloneImage(image);
  cvShowImage( "Raw Video", image );  // Show raw image
  cvRemap( t, image, mapx, mapy );  // Undistort image
  cvReleaseImage(&t);
  cvShowImage("Undistort", image);  // Show corrected image

  //Handle pause/unpause and ESC
  int c = cvWaitKey(15);
  if(c == 'p')
  { 
   c = 0;
   while(c != 'p' && c != 27)
   {
    c = cvWaitKey(250);
   }
  }
  if(c == 27)
   break;

  image = cvQueryFrame( capture );
 } 
 
 return 0;
}
Pattern [Size A4, 3508x2480px, PNG]:












Images:

Monday, March 1, 2010

Double Treat !!

 My blog just hit 1000 views !!... on the other hand my page at dA [link] also has 1000 views !!...Thanks to you =)..