This method is very useful in finding the optimum threshold value in a binary image where the intensity can be modeled as a Bimodal Histogram. The algorithm is very straight forward. You start with an ideal threshold value (128), divide the histogram into 2 parts based on this value, and then find the average intensities in the 2 parts of the histogram. The threshold value is the average of the 2 threshold values obtained for the 2 Histograms.

You keep on iterating until you find the same vaue consecutively.

Below is a simple openCV function written in C without using any of the standard openCV functions to implement this algorithm :

int find_threshold(IplImage* image)
{
int threshold_final;
int i,j;
int k = 256;
int t_initial = k/2;

int height = image->height;
int width =  image->width;
float new_t;

CvScalar s1,s2;

int intensity_temp1 = 0, intensity_temp2 = 0;

IplImage* temp1 = cvCreateImage(cvGetSize(image),IPL_DEPTH_8U,1);
IplImage* temp2 = cvCreateImage(cvGetSize(image),IPL_DEPTH_8U,1);

int size = (temp1->height)*(temp1->width);

uchar *data_input = image->imageData;
int data_temp1[size],data_temp2[size];
int p=0,q=0;

while (1)
{

for (i = 0; i < height; i++)
{
for (j = 0; j < width; j++)
{
if(data_input[i*(image->widthStep) + j*(image->nChannels)] < t_initial )
{
data_temp1[p] = data_input[i*(image->widthStep) + j*(image->nChannels)];
p++;
}
else
{
data_temp2[q] = data_input[i*(image->widthStep) + j*(image->nChannels)];
q++;
}
}
}
for (i = 0;i<p;i++)
{
intensity_temp1 = intensity_temp1 + data_temp1[i];
}

for (i = 0;i<q;i++)
{
intensity_temp2 = intensity_temp2 + data_temp2[i];
}

float average1 = intensity_temp1/p;
float average2 = intensity_temp2/q;

intensity_temp1 = 0;
intensity_temp2 = 0;
p=0;
q=0;

//calculate new value of threhold as the average of these 2 means
// T = (mu1 + mu2)/2
new_t = (average1 + average2)/2;
threshold_final = (int)new_t;

if (threshold_final == t_initial)
break;
else
t_initial = threshold_final;

}

return(threshold_final);
}

Here is a description of some of the most fundamental and easy to use functions in openCV.

This should be a good starting point for beginners ….

Function CvLoadImage – Used to load an image data into an IplImage array

cvLoadImage(const char* fileName, int iscolor)

file name – Name of the image to load
iscolor -  number of channels of the image
If  iscolor > 0 the image loaded will always have 3 channels
If iscolor < 0 the image will be loaded with the number of channels based on the file
If iscolor = 0 the image will always have 1 channel.

Channel : A channel is the number of numbers used to specify a pixel value…
In RGB say each pixel’s color is specified by it’s R, G, B values. Hence, channels = 3.

IplImage *grayScaleImage;

//Create the image…
grayScaleImage = cvCreateImage(cvSize(320,240),8,1);

Function cvCreateImage – Used to create and allocate image data

cvCreateImage(CvSize size, int bitDepth, int channels);

CvSize is a OpenCV basic structure.
typedef struct CvSize
{
int width;
int height;
}

Size – size of the Image
bitDepth – the bitDepth of the image
Bit Depth:  Bit Depth is the number of bits used to store information about an image.
Alternately for the bitDepth one can also use the OpenCV constants like IPL_DEPTH_8U, IPL_DEPTH_16S etc…
channels – Number of channels in the image

//Convert the original image to grayscale
cvCvtColor(originalImage, grayScaleImage, CV_BGR2GRAY);

Function cvCvtColor – Used to convert Images in one color space to another

cvCvtColor(const CvArr* SourceImage, const cvArr* DestinationImage, int code)

“code” – color conversion operation to be performed.
There are numerous conversion operations listed in OpenCV. They include conversion to and from RGB, YCrCb, HSV and Bayer.
CvArr is just a basic structure in OpenCV. It is used only in functions to specify that the parameter accepts more than one kind of array (there are many types of arrays in OpenCV and IplImage is one such type).

// Edge detection
IplImage * edgeImage; //Declare an image for holding the results of the edge detection perfomed on the grayScaleImage.
edgeImage = cvCreateImage(cvSize(320,240), 8, 1); //Create Image

//Perform edge detection using the canny edge detector
cvCanny(grayScaleImage, edgeImage, 0.5, 0.5, 3);


Function cvCanny – Used to perform edge detection with the Canny Operator

cvCanny(const cvArr *Image1, const cvArr *Image2, double threshold1, double threshold2, int kernel_size)

Image1 – Original Image on which edge detection is to be performed.
Image2 – The results of the edge detected image.
threshold1 and threshold2 – Thresholds for the canny detector.
kernel_size – Size of the sobel kernel – Value of 3 gives a 3 X 3 kernel.

//If all goes well we need to save the results of the edge detection.
cvSaveImage(“Resultant.jpg”,edgeImage);

Function cvSaveImage – Used to save an IplImage as a Image

cvSaveImage(const char*  FileName, const CvArr*   Image);

FileName – Name of the save file
Image  – Image to be saved

//Finally release the memory for the images that were created
cvReleaseImage(&edgeImage);
cvReleaseImage(&grayScaleImage);

Function cvReleaseImage – Used to release the image data

cvReleaseImage(IplImage **Image)

Image  – Image to be released