Thursday, May 21, 2009

opencv#8: Find the vertical projection of an image

Often, it will be necessary to find the sum of pixels in each column of an image. This is called the vertical projection. An application may in optical character recognition (OCR), where we can use the vertical projection to separate connected characters. The troughs in vertical projection mostly correspond to the junction of two characters.

This piece of code find the sum of column elements of a binary/gray image and stores it in a vector. It also finds the maximum value of vertical projection.

IplImage* img;
// find the vertical projection
std::vector v_vl_proj; // holds the column sum values
double max_vl_proj = 0; // holds the maximum value
for( int i=0;i<img->width;++i )
{
CvMat col;
CvScalar col_sum;
cvGetCol( img, &col, i ); // get individual columns
col_sum = cvSum( &col ); // find the sum of ith column
v_vl_proj.push_back( col_sum.val[0] ); // push back to vector
if( col_sum.val[0]>max_vl_proj ) max_vl_proj = col_sum.val[0];
}

The same logic can be used to find the row sum of the image.

Tuesday, May 19, 2009

Matlab: Window based Otsu thresholding

This function divides the gray level image into a predefined set of subimages (This can be controlled). Calculates the otsu threshold on each subimage and threshold it accordingly. The function returns a BW image that is thresholded according to window based otsu thresholding.

function IMBw = LocalOtsuThresh( IMGray, NW )

[M N] = size( IMGray );
IMBw = zeros(M, N);

if nargin < 2
NW = 4;
end

for m = 1:NW
for n = 1:NW
IMTmp = uint8(IMGray( 1+(m-1)*floor(M/NW):m*floor(M/NW),...
1+(n-1)*floor(N/NW):n*floor(N/NW) ));
IMTmpBw = im2bw( IMTmp, graythresh( IMTmp ) );

IMBw( 1+(m-1)*floor(M/NW):m*floor(M/NW),...
1+(n-1)*floor(N/NW):n*floor(N/NW) ) = IMTmpBw;
end
end

NW defines the number of subimages. Default is 4. So in default case the gray level image will be divided into 16 subimages.

Thursday, May 14, 2009

OpenCV#7: Simple motion detection

This is a simple motion detection algorithm using frame difference method. This example assumes that the video frames are stored in your system in a particular directory.

#include <iostream>
#include <sstream>

#include "cv.h"
#include "highgui.h"

using namespace std;

int main()
{

IplImage* frame_prev = cvLoadImage( "dir_name/frame0.jpg", CV_LOAD_IMAGE_GRAYSCALE );
int M = frame_prev->width;
int N = frame_prev->height;
IplImage* frame_curr;
IplImage* frame_diff = cvCreateImage( cvGetSize(frame_prev), 8, 1 );

for( int i=1; i<=500; ++i )
{
ostringstream oss;
oss << "dir_name/frame";
oss << i;
oss << ".jpg";

// motion detection - simple frame difference algorithm
frame_curr = cvLoadImage( oss.str().c_str(), CV_LOAD_IMAGE_GRAYSCALE );
cvAbsDiff( frame_curr, frame_prev, frame_diff );
cvThreshold( frame_diff, frame_diff, 30, 255, CV_THRESH_BINARY );
cvCopy( frame_curr, frame_prev );

cvNamedWindow( "Motion Detection", CV_WINDOW_AUTOSIZE );
cvShowImage( "Motion Detection", frame_diff );
if( (cvWaitKey(25) & 255) == 27 ) break; // wait for some time or 'ESC' key press
}

cvReleaseImage( &frame_prev );
cvDestroyWindow( "Motion Detection" );

return 0;
}

Wednesday, May 13, 2009

OpenCV#6: Find the cross correlation of two opencv images

This function calculates the cross correlation between two images of the type IplImage*. Returns the resulting value.

double cross_correlation( IplImage* img1, IplImage* img2 )
{
double corr;

int M = img1->width;
int N = img1->height;

BwImage img_1( img1 ); // using opencv wrapper for accessing image pixels
BwImage img_2( img2 );

CvScalar img1_avg = cvAvg( img1, NULL );
CvScalar img2_avg = cvAvg( img2, NULL );

double sum_img1_img2 = 0;
double sum_img1_2 = 0;
double sum_img2_2 = 0;

for( int m=0; m<M; ++m )
{
for( int n=0; n<N; ++n )
{
sum_img1_img2 = sum_img1_img2 + (img_1[m][n]-img1_avg.val[0])*(img_2[m][n]-img2_avg.val[0]);
sum_img1_2 = sum_img1_2 + (img_1[m][n]-img1_avg.val[0])*(img_1[m][n]-img1_avg.val[0]);
sum_img2_2 = sum_img2_2 + (img_2[m][n]-img2_avg.val[0])*(img_2[m][n]-img2_avg.val[0]);
}
}

corr = sum_img1_img2/sqrt(sum_img1_2*sum_img2_2);

return corr;
}

Thursday, May 7, 2009

OpenCV#5: Copy a portion from an image

1. set an ROI in the source image

cvSetImageROI( img_src, cvRect roi );

2. create a new image with the same size as the ROI

IplImage* img_dst = cvCreateImage( cvSize( roi.width, roi.height ), IPL_DEPTH_8U, 1 );

3. copy the portion from the source image to destination image

cvCopy( img_src, img_dst );

Wednesday, May 6, 2009

OpenCV#4: Remove small blobs from binary image


// Function to remove small blobs from the binary image
IplImage* remove_small_objects( IplImage* img_in, int size )
{
IplImage* img_out = cvCloneImage( img_in ); // return image
CvMemStorage* storage = cvCreateMemStorage( 0 ); // container of retrieved contours
CvSeq* contours = NULL;
CvScalar black = CV_RGB( 0, 0, 0 ); // black color
CvScalar white = CV_RGB( 255, 255, 255 ); // white color
double area;

// find contours in binary image
cvFindContours( img_in, storage, &contours, sizeof( CvContour ), CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE );

while( contours ) // loop over all the contours
{
area = cvContourArea( contours, CV_WHOLE_SEQ );
if( fabs( area ) <= size ) // if the area of the contour is less than threshold remove it
{
// draws the contours into a new image
cvDrawContours( img_out, contours, black, black, -1, CV_FILLED, 8 ); // removes white dots
}
/* else
{
cvDrawContours( img_out, contours, white, white, -1, CV_FILLED, 8 ); // fills in holes
}*/
contours = contours->h_next; // jump to the next contour
}

cvReleaseMemStorage( &storage );
return img_out;
}

Tuesday, May 5, 2009

OpenCV #3: Converting an image to gray scale


int M = img_rgb->width;
int N = img_rgb->height;

// convert to gray scale
IplImage* img_gray = cvCreateImage( cvSize(M, N), IPL_DEPTH_8U, 1 );
cvCvtColor( img_rgb, img_gray, CV_BGR2GRAY );

Followers