Basic Image Processing

Untitled Document
Image processing is any form of signal processing for which the input is an image, such as a photograph or video frame; the output of image processing may be either an image or, a set of characteristics or parameters related to the image. This tutorial will mainly involve the use of image processing to use camera feed of a robot and to perform a set of tasks based on what it senses.

Contents

  • Basic Image Processing Concepts
  • Basic Image Processing Techniques
  • Getting to know  the Code
  • Colour Detection
  • Edge Detection
  • Shape Detection
  • Blob Detection
  • Capture from Camera
  • Conclusion
  • Resources

Basic Image Processing Concepts


An Image basically is a two dimensional array of pixels. These are the tiny little dots of colour you see on your screen, and the smallest possible size any image can get. When an image is stored, the image file contains information on every single pixel in that image. This information includes two things: colour, and pixel location. Where a pixel has different number of channels and each channel has some value which specifies the colour of that pixel. In case of a multi channel pixel, the resulting colour of the pixel is the overall result of the values of all the channels in it.


Let us first tell you the meaning of some of the terms so that it will be convenient for you to understand afterwards

 

Resolution

The resolution of an image defines how many pixels are there in the image, for example: if an image has the resolution of [ 350 X 233 ] it means that the image is a two dimensional array of size[350][233] that is 350 pixel in the horizontal direction for each of the 233 pixel in the vertical direction. Check the image shown below.


A higher resolution means greater detail and information. The image below shows the same image in different resolutions scaled to the same size.

 



In image processing, high resolution means greater amount of processing. Thus, for image processing optimum resolution is used large enough to retrieve required data and small enough for quick processing.

Channels

Lets us understand this with the help of an example. If an image is a single channel image that is each pixel contains only one channel then the colour of that pixel will depend only on the value of that particular channel. The unsigned value of any channel varies from 0 to 255. A Grayscale image is an example of a single channel image. Whereas a coloured image is a three channel image which contains the channels blue, green and red. The colour of any pixel depends upon the values between 0 and 255 of these three pixels. The image below shows the three R-G-B channels of an image and their gray scale representation. All channels combined, they form a coloured image.

 

 

 

Popular types of images with different kinds of channels:
BGR – Blue, Green, Red
HSV – Hue, Saturation, Value
CMYK – Cyan, Magenta, Yellow, Alpha

Basic Image Processing Techniques

In Image processing we basically play with the values of the different channels of the pixels in the image. We analyze the values of these channels and then set thresholds accordingly, filtering our images to whatever is required and removing the unwanted part known as noise.

Decreasing Resolution 

The basic concept in decreasing resolution is that you are selectively deleting data from the image. Let's  look into some algorithms in which we can do that.

Here is a matrix example of a binary image of a triangle:

0 0 0 1 0 0 0

0 0 1 0 1 0 0

0 1 0 0 0 1 0

1 1 1 1 1 1 1

0 0 0 0 0 0 0

Here is a matrix example of a greyscale (8 bit) image of a triangle:

0   0  55 255 55 0

0   55 255 55 255 55 0

55 255 55 55 55 255 55

255 255 255 255 255 255 255

55 55 55 55 55 55 55

0 0 0 0 0 0 0

It has a resolution of 7 x 6, with 8 bits stored in each location. Memory required is therefore 7 x 6 x 8 = 336 bits.

As you can see, increasing resolution and information per pixel can significantly slow down your image processing speed.

The first method is just delete 1 pixel out of every group of pixels in both X and Y directions of the matrix. For example, using our greyscale image (2D array of numbers) of a triangle shown above, and deleting one out of every two pixels in the X direction, we would get:

0   55  55  0

0   255 255 0

55  55  55  55

255 255 255 255

55  55  55  55

0   0   0   0

 

and continuing with the Y direction:

0   55  55  0

55  55  55  55

55  55  55  55

and will result in a 4 x 3 matrix, for memory usage of 96 bits which is 4x3 = 12 bytes.
Another way of decreasing resolution would be to choose a pixel, average the values of all surrounding pixels, store that value in the choosen pixel location, then delete all the surrounding pixels. This is what Mona Lisa would look like (below). You can see how pixels are averaged along the edges of her hair.

Grayscale to Binary Conversion

To make our processing the visual data, we try to reduce the information. For example if in a single channel image, say a grayscale image, we want only those pixels to be displayed which have the value above 100 [values ranging from 0 to 255] then we can set 100 as our threshold and assign all pixels having value less than 100 as say 0 ( so that these pixels which are unwanted all appear to be black because 0 value means complete black in a grayscale image) and the rest of the pixels will have a particular value say 255 ( standing for complete white in a grayscale image) and hence a binary image is formed. Example is shown in the Image below which is converted from grayscale to binary image.

-->  

Thresholding

As you saw how the image data was reduced by averaging or deleting pixels, now we would discuss a technique to reduce data by reducing the colour data in each pixel.  Heuristics is when you statistically look at an image as a whole, such as determining the overall brightness of an image, or counting the total number of pixels that contain a certain colour.An example image heuristic plotting pixel count (Y-axis) versus pixel colour intensity (0 to 255, X-axis).


Heuristics can also be used to improve image contrast. The image is analyzed, and then bright pixels are made brighter, and dark pixels are made darker. The following is an example of improving contrasts in the Mona Lisa picture.

   --> 

Softwares


The examples given in this tutorial have been written in C compiled with  openCV in Visual Studio. The links for the required programs:

OpenCV:  http://opencv.willowgarage.com/wiki/
Visual Studio:  http://www.microsoft.com/express/Downloads/

Integrating OpenCV with Visual Studio

Assuming both Visual Studio and OpenCV have been installed in the default directory i.e. in C:\Program Files.
For Visual Studio 2006, go to the Options from Tools menu and then to the Directories Tab.
For Visual Studio 2008, go to 
Options from Tools then in Options from Projects to VC++ Directories Tab.
Then add the following links
In Include Files
C:\Program Files\OpenCV\cv\include
C:\Program Files\OpenCV\cxcore\include
C:\Program Files\OpenCV\cvaux\include
C:\Program Files\OpenCV\otherlibs\cvcam\include
C:\Program Files\OpenCV\otherlibs\highgui

In Library Files

C:\Program Files\OpenCV\lib
C:\Program Files\OpenCV\otherlibs\highgui

In Source Files

C:\Program Files\OpenCV\cv\src
C:\Program Files\OpenCV\cvaux\src
C:\Program Files\OpenCV\cxcore\src
C:\Program Files\OpenCV\otherlibs\cvcam\src

Now add the .dll files in the C:\Program Files\OpenCV\bin directory to the C:\Windows\system directory.
For every new project in Visual Studio 2008, go to Project then to Properties to Linker tab to Input category to Additional Dependencies and append the following in the Object/Modules box

cv.lib cvaux.lib cxcore.lib highgui.lib

Now your OpenCV has been successfully integrated with Visual Studio.
You can now simply go and use OpenCV libraries and functions in your code.

Get to know the code

Loading Images

This is a simple, introductory Open CV program. The program reads an image from a file, and displays the result.

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

int main(int argc, char *argv[])
{
IplImage* img = 0; 
int height,width,step,channels;
uchar *data;
int i,j,k;

if(argc<2){
printf("Usage: main \n\7");
exit(0);
}

// load an image
img=cvLoadImage(argv[1]);
if(!img){
printf("Could not load image file: %s\n",argv[1]);
exit(0);
}
// get the image data
height = img->height;
width = img->width;
step = img->widthStep;
channels = img->nChannels;
data = (uchar *)img->imageData;
printf("Processing a %dx%d image with %d channels\n",height,width,channels); 

// create a window
cvNamedWindow("mainWin", CV_WINDOW_AUTOSIZE); 
cvMoveWindow("mainWin", 100, 100);

// show the image
cvShowImage("mainWin", img );

// wait for a key
cvWaitKey(0);

// release the image
cvReleaseImage(&img );
return 0;
}
  

Allocating an image

  IplImage* cvCreateImage(CvSize size, int depth, int channels);
  size:  cvSize(width,height);
  depth: pixel depth in bits: IPL_DEPTH_8U, IPL_DEPTH_8S, IPL_DEPTH_16U,IPL_DEPTH_16S, IPL_DEPTH_32S, IPL_DEPTH_32F, IPL_DEPTH_64F
  channels: Number of channels per pixel. Can be 1, 2, 3 or 4. The channels are interleaved. The usual data layout of a colour image is b0 g0 r0 b1 g1 r1 ...
Examples:
// Allocate a 1-channel byte image of 640 X 480 resolution.
IplImage* img1=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
// Allocate a 3-channel float image of 640 X 480 resolution.
IplImage* img2=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);

Release an image

IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);//creates image
cvReleaseImage(&img);// releases image 

Clone an image

IplImage* img1=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1); 
IplImage* img2;
img2=cvCloneImage(img1);// img2 is clone of img1

Set/get the region of interest

void  cvSetImageROI(IplImage* image, CvRect rect);
void  cvResetImageROI(IplImage* image);
vRect cvGetImageROI(const IplImage* image);

Set/get the channel of interest

void cvSetImageCOI(IplImage* image, int coi); // 0=all
int cvGetImageCOI(const IplImage* image);

Accessing image elements

Assume that you need to access the k-th channel of the pixel at the i-th row and j-th column. The row index i is in the range [0, height-1]. The column index j is in the range [0, width-1]. The channel index kis in the range [0, nchannels-1].


Indirect access: (General, but inefficient, access to any type image)


For a single-channel byte image:
IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
CvScalar s;
s=cvGet2D(img,i,j); // get the (i,j) pixel value
printf("intensity=%f\n",s.val[0]);
s.val[0]=111;
cvSet2D(img,i,j,s); // set the (i,j) pixel value
For a multi-channel float (or byte) image:
IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);
CvScalar s;
s=cvGet2D(img,i,j); // get the (i,j) pixel value
printf("B=%f, G=%f, R=%f\n",s.val[0],s.val[1],s.val[2]);
s.val[0]=111;
s.val[1]=111;
s.val[2]=111;
cvSet2D(img,i,j,s); // set the (i,j) pixel value

Direct access: (Efficient access, but error prone)


For a single-channel byte image:
IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
((uchar *)(img->imageData + i*img->widthStep))[j]=111;

For a multi-channel byte image:
IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);
((uchar *)(img->imageData + i*img->widthStep))[j*img->nChannels + 0]=111; // B
((uchar *)(img->imageData + i*img->widthStep))[j*img->nChannels + 1]=112; // G
((uchar *)(img->imageData + i*img->widthStep))[j*img->nChannels + 2]=113; // R
For a multi-channel float image:
IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);
((float *)(img->imageData + i*img->widthStep))[j*img->nChannels + 0]=111; // B
((float *)(img->imageData + i*img->widthStep))[j*img->nChannels + 1]=112; // G
((float *)(img->imageData + i*img->widthStep))[j*img->nChannels + 2]=113; // R

Direct access using a pointer: (Simplified and efficient access under limiting assumptions)

For a single-channel byte image:
IplImage* img = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
int height = img->height;
int width = img->width;
int step = img->widthStep/sizeof(uchar);
uchar* data = (uchar *)img->imageData;
data[i*step+j] = 111;
For a multi-channel byte image:
IplImage* img = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);
int height = img->height;
int width = img->width;
int step = img->widthStep/sizeof(uchar);
int channels = img->nChannels;
uchar* data = (uchar *)img->imageData;
data[i*step+j*channels+k] = 111;
For a multi-channel float image (assuming a 4-byte alignment):
IplImage* img = cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);
int height = img->height;
int width = img->width;
int step = img->widthStep/sizeof(float);
int channels = img->nChannels;
float * data = (float *)img->imageData;
data[i*step+j*channels+k] = 111;

BGR / Grayscale / Binary Image Conversion

//loading a 3 channel bgr image 
IplImage *im_rgb = cvLoadImage("image.jpg");

//creating a 1 channel grayscale image
IplImage *im_gray = cvCreateImage(cvGetSize(im_rgb),IPL_DEPTH_8U,1);

//converting bgr image to grayscale image.
cvCvtColour(im_rgb,im_gray,CV_RGB2GRAY);


//creating a single channel image for using it as a binary image.
IplImage* img_bw = cvCreateImage(cvGetSize(im_gray),IPL_DEPTH_8U,1);

//Thresholding and converting the grayscale image into a binary image 
cvThreshold(im_gray, im_bw, 128, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);

//saving the image
cvSaveImage("image_bw.jpg",img_bw);

Histogram

#include "stdafx.h"
#include <cxcore.h>
#include <cv.h>
#include <cvaux.h>
#include <highgui.h>
#include <stdio.h>
#include <sstream>
#include <iostream>

using namespace std;

int main(){

//capturing image from the camera
CvCapture* capture = cvCaptureFromCAM(0);

//if image is not captured properly an error msg is displayed
if(!cvQueryFrame(capture)){
cout<<"Video capture failed, please check the camera."<<endl;
}

else{
cout<<"Video camera capture successful!"<<endl;
};

//getting the size of the captured image. cvQueryFrame() retrieves the image
CvSize sz = cvGetSize(cvQueryFrame(capture));

IplImage* image = cvCreateImage(sz, 8, 3);
IplImage* imgHistogram = 0;
IplImage* gray = 0;
CvHistogram* hist;

cvNamedWindow("Image Source",1);
cvNamedWindow("Histogram",1);

for(;;){

image = cvQueryFrame(capture);

//Size of the histogram -1D histogram
int bins = 256;
int hsize[] = {bins};

//Max and min value of the histogram
float max_value = 0, min_value = 0;

//Value and normalized value
float value;
int normalized;

//Ranges - grayscale 0 to 256
float xranges[] = {0, 256};
float* ranges[] = {xranges};

//Create an 8 bit single channel image to hold a grayscale version of the original picture
gray = cvCreateImage(cvGetSize(image), 8, 1);
cvCvtColour(image, gray, CV_BGR2GRAY);

//Planes to obtain the histogram, in this case just one
IplImage* planes[] = {gray};

//Get the histogram and some info about it
hist = cvCreateHist(1, hsize, CV_HIST_ARRAY, ranges,1);
cvCalcHist(planes, hist, 0, NULL);
cvGetMinMaxHistValue(hist, &min_value, &max_value);
printf("Minimum Histogram Value: %f, Maximum Histogram Value: %f\n", min_value, max_value);

//Create an 8 bits single channel image to hold the histogram and paint it white
imgHistogram = cvCreateImage(cvSize(bins, 50),8,3);
cvRectangle(imgHistogram, cvPoint(0,0), cvPoint(256,50), CV_RGB(255,255,255),-1);

//Draw the histogram
for(int i=0; i < bins; i++){
value = cvQueryHistValue_1D(hist, i);
normalized = cvRound(value*50/max_value);
cvLine(imgHistogram,cvPoint(i,50), cvPoint(i,50-normalized), CV_RGB(0,0,0));
}

cvFlip(image, NULL, 1);// flips the image upside down
cvShowImage("Image Source", image);
cvShowImage("Histogram", imgHistogram);

cvReleaseImage(&image);
cvReleaseImage(&imgHistogram);
cvReleaseImage(&gray);
cvReleaseHist(&hist);

char c = cvWaitKey(10);

//if ASCII key 27 (esc) is pressed then loop breaks
if(c==27) break;

}

cvReleaseImage(&image);
cvReleaseCapture(&capture);
cvDestroyAllWindows();

}

BGR / HSV


In a lot of images, the colour range is too large to get a very accurate image. Forexample, a shiny red ball reflects light which results in a very wide range of red colour. So, How to make sure that we detect Colours Correctly? Adding some arbitrary value in the Image would not Help since it would increase the brightness but not the Contrast. So How to do it…
Here after the Colour Conversion I would like to increase the Strength of the Colours So that the Colours appear good in the image which would again facilitate the Robot to realize Images nicely.
So first we would Colour Convert the Image to the HSV colour Space and then increase the saturation in that colour space and convert it back to the BGR Colour space. You would really find a difference. If you feel that the Image is bright then you may reduce the brightness by subtracting a value (the value depends on the image) from the value component of the HSV Colour Space. First let us look at the Image


.

After adding 30 units of strength to all the Colours available in the Image with the help of this program…



The Code

/*ALL the necessary header files*/
/*If you want to enhance the Videos then instead of loading frames from an
Image you may load frames from a camera.. by using the capture structures*/
#include"math.h"
#include"conio.h"
#include"cv.h"
#include"highgui.h"
#include"stdio.h"
int main()
{

int i,j,k;
int heightc,widthc,stepc,channelsc;

int temp=0;
int units=0;
uchar *data,*datac;
i=j=k=0;

IplImage *frame=cvLoadImage("lena.jpg",1);
IplImage *convert=cvCreateImage( cvGetSize(frame), 8, 3 );
IplImage *result=cvCreateImage( cvGetSize(frame), 8, 3 );
printf("By what value Do you want to increase the strenght of the colour..? ");
scanf("%d", &units);
if(frame==NULL ) {
puts("unable to load the frame");exit(0);}

cvNamedWindow("original",CV_WINDOW_AUTOSIZE);
cvNamedWindow("Result",CV_WINDOW_AUTOSIZE);

heightc = convert->height;
widthc = convert->width;

stepc=convert->widthStep;
channelsc=convert->nChannels;
datac = (uchar *)convert->imageData;

cvCvtColour(frame,convert,CV_BGR2HSV);

for(i=0;i< (heightc);i++) for(j=0;j<(widthc);j++)
{/*Here datac means data of the HSV Image*/
/*Here i want to Increase the saturation or the strength of the Colours in the Image and
then I would be able to perform a good colour detection*/

temp=datac[i*stepc+j*channelsc+1]+units;/*increas the saturaion component is the second arrray.*/

/*Here there is a small problem...when you add a value to the data and if it exceeds 255
it starts all over again from zero and hence some of the pixels might go to zero.
So to stop this we need to include this loop i would not try to explain the loop but
please try and follow it is easy to do so..*/
if(temp>255) datac[i*stepc+j*channelsc+1]=255;
else datac[i*stepc+j*channelsc+1]=temp;/*you may
please remove and see what is happening if the if else loop is not there*/}

cvCvtColour(convert, result, CV_HSV2BGR);
cvShowImage("Result", result);
cvShowImage("original", frame);

cvSaveImage("Enhresult.jpg",result);
cvWaitKey(0);
cvDestroyWindow("original");
cvDestroyWindow("Result");
return 0;
}
You can also use the hue value to accurately select a colour. The hue range for each colour is very small and can be used for detecting the same hue in different  lighting conditions.

Colour Detection


One of the most fundamental aspects of an image is the colours. We can use colours to differentiate between different objects from others. For example, if u take a picture of an apple tree and want to count the number of apples visible in the image. We can simply isolate the red pixels from the image and find out the number of red blobs. We would be learning about blob .detection soon. Let us now concentrate on detecting red colour in the following image


In order to select the red pixels, we will have to work on the red (third channel). For high red value, we can set ( red  > 20+ green or red >20+ blue). Which means we want to select the red pixels whose value is atleast 20 units greater than any other component So lets Analyse the program now. We should also make a note that white is R=G=B=255 so we do not include and equal sign in the condition loop which we are going to analyse in the program below..

/*ALL the necessary header files*/
#include"math.h"
#include"conio.h"
#include"cv.h"
#include"highgui.h"
#include"stdio.h"
int main()
{
int i,j,k;
int height,width,step,channels;
int stepr, channelsr;
int temp=0;
uchar *data,*datar;
i=j=k=0;
IplImage *frame=cvLoadImage("3d-09-5balls.jpg",1);
IplImage *result=cvCreateImage( cvGetSize(frame), 8, 1 );
if(frame==NULL ) {
puts("unable to load the frame");exit(0);}
printf("frame loaded");
cvNamedWindow("original",CV_WINDOW_AUTOSIZE);
cvNamedWindow("Result",CV_WINDOW_AUTOSIZE);

height = frame->height;
width = frame->width;
step =frame->widthStep;
channels = frame->nChannels;
data = (uchar *)frame->imageData;
/*Here I use the Suffix r to diffenrentiate the result data and the frame data
Example :stepr denotes widthStep of the result IplImage and step is for frame IplImage*/

stepr=result->widthStep;
channelsr=result->nChannels;
datar = (uchar *)result->imageData;

for(i=0;i < (height);i++) for(j=0;j <(width);j++)

/*As I told you previously you need to select pixels which are
more red than any other colour
Hence i select a difference of 29(which again depends on the scene).
(you need to select randomly and test*/
if(((data[i*step+j*channels+2]) > (29+data[i*step+j*channels]))
&& ((data[i*step+j*channels+2]) > (29+data[i*step+j*channels+1])))
datar[i*stepr+j*channelsr]=255;
else
datar[i*stepr+j*channelsr]=0;
/*Destroying all the Windows*/
cvShowImage("original",frame);
cvShowImage("Result",result);
cvSaveImage("result.jpg",result);
cvWaitKey(0);
cvDestroyWindow("original");
cvDestroyWindow("Result");
return 0;
}

The result:
:


If you observe carefully only the red parts of the Image have got Highlighted…wherever there is Red it is white in the Monochrome image. You can also use this program on frames from a camera by replacing the frame from the Image by the frame from the camera. You can also use this program for detecting colours and specially objects which are known to be of a particular colour in combination with some more Operations.

Edge Detection


Edge detection is a technique to locate the edges of objects in the scene. This can be useful for locating the horizon, the corner of an object, white line following, or for determing the shape of an object.

sort through the image matrix pixel by pixel

for each pixel, analyze each of the 8 pixels surrounding it

record the value of the darkest pixel, and the lightest pixel

if (darkest_pixel_value - lightest_pixel_value) > threshold) 
then rewrite that pixel as 1; 
else rewrite that pixel as 0

 

--> 

A challenge you may have is choosing a good threshold. This left image has a threshold thats too low, and the right image has a threshold thats too high. You will need to run an image .heuristics program for it to work properly.

--> 


Sometimes, instead of checking the brightness of pixels, you can check the value of particular channels. In this way, you can easily detect the edges of say, a red apple from a surrounding background of same brightness.
Another good  edge detection technique you can use is cvSobel Operation.
<Code to be uploaded soon> I am sure you can write the code using the sample codes and the algorithms provided.

Shape Detection



Shape detection comes to use while detecting various objects of different shapes and projections as viewed by the camera. In this tutorial, we would be understanding on how to detect various simple shapes like quadrilaterals, squares, circles and triangles



The edge detection part is executed and the border line of each shape is recognized.

The number of continuous edges in the image is counted.

If there is a very sharp change in the direction of the line it means that there is a new line in the figure.

The direction of the line is determined by determining the average vector between adjacent pixels.

Now if there are four lines in this image then it is a rectangle. Three lines implies a triangle and one line implies a circle

By measuring the angle between the pixels, we can determine more appropriately, what shape the image is.

 

 

 

There may exist several other algorithms which can be used for detecting more complex shapes and projections of 3D objects.
The following algorithm detects shapes based on the number of vertices present.

 

The edge detection part is executed and the border line of each shape is recognized.

The image is scanned from all four directions and the first edge pixel coordinates is recorded.

The coordinates recorded are checked for coincidence within a certain range.

All but, one coordinates present close to each other are deleted.

The number of coordinates is counted.

If there exist four coordinates then, the shape is a quadrilateral or a circle. Three coordinates implies a triangle

In case of four coordinates, the image is again scanned diagonally.

If a new coordinate is discovered then, the shape considered is a circle. Quadrilateral otherwise.

 

Can you think of some improvements to modify the algorithm to  make it compatible for detecting n-sides polygon?
For reference: http://goo.gl/vXbtJ

Middle Mass and Blob Detection 

While detecting objects through image processing, we need to isolate them into binary images and work with them to extract information. The algorithm used for this purpose is Blob Detection. Blob detection is basically used to determine if a group of pixels near each other are related to each other in some way or the other or not, for example it can be used to determine whether an object of a specific colour is present in the image or not. The basic algorithm involves creation of a binary image by thresholding a property (like colour) in an image. An example of blob detection is the following where the image is thresholded according to the red ball.
In the following image, the colour red is thresholded and a binary image is created. The center coordinates of the blob are calculated by using  the center of mass formula.
X = Sum of x coordinates in the blob / number of pixels in the blob
Y = Sum of y coordinates in the blob / number of pixels in the blob

Here, a blue dot is created at the center of the blob


. -->

There is a problem with this solution. In case of multiple blobs, there will be only one blue dot for multiple blobs.

In order to differentiate different blobs, the algorithm is modified.

Traverse the image pixel by pixel

If the pixel encounters is of the color of the blob then we can mark it as 1.

If the adjacent pixel is also of the blob color then label it as 1 again.

If it is not the adjacent pixel then this means that a new blob is encountered.

Label this as two now.

In this way all the blobs will be labeled and hence the middle masses of each of them are found out individually.

Repeat the steps until we cover all the pixels.

 

What the algorithm does is labels each blob by a number, counting up for every new blob it encounters. Then to find middle mass, you can just find it for each individual blob.
Some videos for better understanding.

Blob Detection in OpenCV


<Sample code to be uploaded soon>


Capture from Camera

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

int main( int argc, char **argv )
{
CvCapture *capture = 0;
IplImage *frame = 0;
int key = 0;

/* initialize camera */
capture = cvCaptureFromCAM( 0 );

/* always check */
if ( !capture ) {
fprintf( stderr, "Cannot open initialize webcam!\n" );
return 1;
}

/* create a window for the video */
cvNamedWindow( "result", CV_WINDOW_AUTOSIZE );

while( key != 'q' ) {
/* get a frame */
frame = cvQueryFrame( capture );

/* always check */
if( !frame ) break;

/* display current frame */
cvShowImage( "result", frame );

/* exit if user press 'q' */
key = cvWaitKey( 1 );
}

/* free memory */
cvDestroyWindow( "result" );
cvReleaseCapture( &capture );

return 0;
}

Conclusion

A lot of codes and algorithms were discussed in this tutorial. It is advisable to run the sample codes on your computers and code the algorithms discussed. Also, check the Nuke-Clear event and complementary tutorials:
Nuke-Clear Event, Nuke-Clear Tutorial, USART Tutorial

Resources

FAQ for comp.graphics.algorithms
Web-based Image Processing
Web-based Image Processing
Open CV Tutorial
Alternate Robotix Tutorial

Untitled Document