[Robotvision-commit] SF.net SVN: robotvision:[19] vision/src/main.cpp
Brought to you by:
phildavidson
From: <bre...@us...> - 2010-06-02 03:03:07
|
Revision: 19 http://robotvision.svn.sourceforge.net/robotvision/?rev=19&view=rev Author: brendasegal Date: 2010-06-02 03:03:00 +0000 (Wed, 02 Jun 2010) Log Message: ----------- Added Paths: ----------- vision/src/main.cpp Added: vision/src/main.cpp =================================================================== --- vision/src/main.cpp (rev 0) +++ vision/src/main.cpp 2010-06-02 03:03:00 UTC (rev 19) @@ -0,0 +1,688 @@ +#ifdef _CH_ +#pragma package <opencv> +#endif + +#define CV_NO_BACKWARD_COMPATIBILITY + +#include <cv.h> +#include <highgui.h> +#include <stdio.h> +#include <math.h> +#include <string.h> +//#include "pipe.cpp" + +using namespace std; + +//using namespace pipe; + +//the struct is what will be used to return the values in the form of an ordered pair (x,y) + + +typedef struct retValue { + + double x; + double y; + +} point; + + +typedef struct elipse { + + float angle; + int total; + CvPoint center; + CvSize size; + + +} elipse; + +int sthresholdbuoy=0, hupperbuoy=0, hlowerbuoy=0, erodebuoy=0, dilatebuoy=0; +int sthresholdpipe=0, hupperpipe=0, hlowerpipe=0, erodepipe=0, dilatepipe=0; +int sthresholdhedge=0, hupperhedge=0, hlowerhedge=0, erodehedge=0, dilatehedge=0; + +//the following function is used by all of the find functions +//in order to set their threshold values on the fly +//using a config file + +//type 1 is the buoy, type 2 is the pipe, type 3 is the hedge +void readFile(char* filename, int type){ + + FILE* filereader; + + filereader = fopen(filename, "r"); + char line[100]; + char* line2 = (char*)malloc(sizeof(char)*100); + + char var[100]; + char value[100]; + + if(filereader!=NULL){ + + while(fgets(line, sizeof(line), filereader)!=NULL){ + + strcpy(line2, line); + strcpy(var,""); + strcpy(value,""); + + sscanf(line, "%s %s", var, value); + + if(strncmp("sthreshold ", line, 11)==0){ + + switch(type){ + + case(1):sthresholdbuoy=atoi(value);break; + case(2):sthresholdpipe=atoi(value);break; + case(3):sthresholdhedge=atoi(value);break; + + } + + + } + else if(strncmp("hupper ", line, 7)==0){ + + + switch(type){ + + case(1):hupperbuoy=atoi(value);break; + case(2):hupperpipe=atoi(value);break; + case(3):hupperhedge=atoi(value);break; + + } + + } + else if(strncmp("hlower ", line, 7)==0){ + + + switch(type){ + + case(1):hlowerbuoy=atoi(value);break; + case(2):hlowerpipe=atoi(value);break; + case(3):hlowerhedge=atoi(value);break; + + } + + + } + else if(strncmp("erode ", line, 6)==0){ + + switch(type){ + case(1):erodebuoy=atoi(value);break; + case(2):erodepipe=atoi(value);break; + case(3):erodehedge=atoi(value);break; + } + + + } + else if(strncmp("dilate ", line, 7)==0){ + + switch(type){ + + case(1):dilatebuoy=atoi(value);break; + case(2):dilatepipe=atoi(value);break; + case(3):dilatehedge=atoi(value);break; + + } + + } + + }//end while + + + } + else{ + + printf("Can't read from file.\n"); + } +} + +//need to show the method headers +/*point findBuoy(IplImage* img); + point findPipe(IplImage* img); + point findHeading(IplImage* img); + */ + +//the convert function converts a gStreamer object to an OpenCV image +/* + + IplImage* convert(GSTBuffer gBuffer){ + + + + + } + */ + +//For the findBuoy function, the center of mass is returned as (x,y) coordinates +//center of mass will either be found by averaging white pixels in binary image +//or by fitting an ellipse around the buoy + +elipse findBuoy(IplImage* src) { + + //we will return our values + //as an ellipse + elipse retElipse; + retElipse.angle=-1; + retElipse.total=0; + + //these are the threshold values + + + + //this is a copy of src + IplImage* img = cvCreateImage( + cvGetSize(src), + IPL_DEPTH_8U, + 3 + ); + + //we smooth the image and store the smooth img back in img + //cvSmooth(img, img, CV_GAUSSIAN, 3, 3, 0, 0); + + //we need to convert the colorspace of img + cvCvtColor(src, img, CV_RGB2HSV); + + //initialization of properties of the actual image + int height; int width; int step; int channels; + //initialization of properties of the thresholded image + int heightmono; int widthmono; int stepmono; int nChannelsmono; + + + + //these are the properties of the image + //we will use them to loop through the data array (the image buffer) + height = img->height; + width = img->width; + step = img->widthStep; + channels = img->nChannels; + + + //this is the image buffer of the current unchanged image + uchar *data = (uchar*) img->imageData; + + //this is the going to hold the binary image formed + //by thresholding the image img + + IplImage* monoimgbot = cvCreateImage( + cvGetSize(img), + IPL_DEPTH_8U, + 1 + ); + + heightmono = monoimgbot->height; + widthmono = monoimgbot->width; + stepmono = monoimgbot->widthStep; + nChannelsmono = monoimgbot->nChannels; + + uchar *datamono = (uchar *)monoimgbot->imageData; + + + + int i, j; + + //this part makes a thresholded image out of img + //and stores it in the image buffer called datamono + + for( i = 0 ; i < height ; i++ ) { + + + for( j = 0 ; j < width ; j++ ) { + + + if((data[i*step + j*channels]<=hlowerbuoy) && ( data[i*step + j*channels]>=hupperbuoy)){ + + if( ( data[i*step + j*channels + 1] ) >sthresholdbuoy){ + + datamono[i*stepmono + j*nChannelsmono + 0] = 255; + + } + else{ + datamono[i*stepmono + j*nChannelsmono + 0] = 0; + + + } + + + } + else{ + datamono[i*stepmono + j*nChannelsmono + 0] = 0; + + } + + }//end inner for loop + + }//end outer for loop + + cvErode(monoimgbot, monoimgbot, 0, erodebuoy); + cvDilate(monoimgbot, monoimgbot, 0, dilatebuoy); + + //now that we have our thresholded image, + //we will draw an ellipse around our white pixels + //and the center of the ellipse will represent + //the approximate center of the buoy + + CvMemStorage* storage; + CvSeq* contour; + + // Create dynamic structure and sequence. + storage = cvCreateMemStorage(0); + contour = cvCreateSeq(CV_SEQ_ELTYPE_POINT, sizeof(CvSeq), sizeof(CvPoint) , storage); + + cvShowImage("processed", monoimgbot); + + // Find all contours. + cvFindContours( monoimgbot, storage, &contour, sizeof(CvContour), + CV_RETR_LIST, CV_CHAIN_APPROX_NONE, cvPoint(0,0)); + + // This cycle draw all contours and approximate it by ellipses. + for(;contour;contour = contour->h_next){ + + int count = contour->total; // This is number point in contour + CvPoint center; + CvSize size; + CvBox2D box; + + // Number point must be more than or equal to 6 (for cvFitEllipse_32f). + if( count < 6 ) + continue; + + CvMat* points_f = cvCreateMat( 1, count, CV_32FC2 ); + CvMat points_i = cvMat( 1, count, CV_32SC2, points_f->data.ptr ); + cvCvtSeqToArray( contour, points_f->data.ptr, CV_WHOLE_SEQ ); + cvConvert( &points_i, points_f ); + + // Fits ellipse to current contour. + box = cvFitEllipse2( points_f ); + + //we draw an ellipse from these points + //iff there are more points in this current contour + //than for the last one to which we fit an ellipse + if(count>retElipse.total) { + + retElipse.total = count; + retElipse.angle = box.angle; + retElipse.center = cvPointFrom32f(box.center); + retElipse.size.width = cvRound(box.size.width*0.5); + retElipse.size.height = cvRound(box.size.height*0.5); + } + + cvReleaseMat(&points_f); + + }//end for + + if(retElipse.angle!=-1) { + cvLine(monoimgbot, cvPoint(monoimgbot->width / 2, monoimgbot->height / 2), + cvPoint((monoimgbot->width / 2) + (100 * (sin((-retElipse.angle) + * 3.14159265 / 180))), (monoimgbot->height / 2) + (100 + * (cos(-retElipse.angle * 3.14159265 / 180)))), + CV_RGB(0,0,255), 5); + + cvCircle(monoimgbot, cvPoint(monoimgbot->width / 2, monoimgbot->height / 2), 10, + CV_RGB(0,0,255), 10); + + // Draw ellipse. + cvEllipse(monoimgbot, retElipse.center, retElipse.size, -retElipse.angle, 0, 360, CV_RGB(255,0,255), + 1, CV_AA, 0); + + + cvCircle(monoimgbot, retElipse.center, 20, CV_RGB(0,255,0), 3); + + + } + + cvReleaseMemStorage(&storage); + cvReleaseImage(&monoimgbot); + + return retElipse; + +} + +//the findHedge function will have to be used with a fake image we create +//(I suggest manipulating the buoy image and drawing a green hedge within it) +//since we don't have any ones to base ourselves on +//how are we going to return the values? Are we going to return a struct with three points, +//each corresponding to the center of each rectangle? Will it have to be done in the same way +//as finding the heading of the pipe? +//will we need to make a new struct then for this return value? + +/*point? findHedge(IplImage* img){ + + + } + */ + +//The findPipe function works in quite the same way as findBuoy + + + + +elipse finalFindPipe(IplImage *src) { + + //int sthreshold = 86, erode = 4, dialate = 8; + + //int hlower = 127, hupper = 25; + + //int sthreshold = 11, erode = 3, dialate = 6; + + //int hlower = 127, hupper = 45; + + /*here hlower is the lower cut off and the hupper is the upper cut off for hue values of red.*/ + + int i, j, k;//for iterations + int temp = 0;//if we use a temporary var + + int heighthsv, widthhsv, stephsv, channelshsv; + int heightmono, widthmono, stepmono, channelsmono; + uchar *datahsv, *datamono; + + IplImage *colimgbot; + + IplImage *monoimgbot; + + //printf("frame loaded"); + + colimgbot = cvCreateImage(cvGetSize(src), 8, 3); + + monoimgbot = cvCreateImage(cvGetSize(src), 8, 1); + + cvCvtColor(src, colimgbot, CV_RGB2HSV); + + //\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97 + + heighthsv = colimgbot->height; + widthhsv = colimgbot->width; + stephsv = colimgbot->widthStep; + channelshsv = colimgbot->nChannels; + datahsv = (uchar *) colimgbot->imageData; + //\x97\x97\x97\x97\x97\x97\x97\x97\x96 + + heightmono = monoimgbot ->height; + widthmono = monoimgbot->width; + stepmono = monoimgbot->widthStep; + channelsmono = monoimgbot->nChannels; + datamono = (uchar *) monoimgbot->imageData; + + for (i = 0; i < (heighthsv); i++) { + for (j = 0; j < (widthhsv); j++) { + if ((datahsv[(i) * stephsv + j * channelshsv] <= hlowerpipe) + && (datahsv[(i) * stephsv + j * channelshsv] >= hupperpipe)) { + if ((datahsv[(i) * stephsv + j * (channelshsv) + 1]) + > sthresholdpipe) { + datamono[i * stepmono + j * channelsmono] = 255; + } else + /*A very simple concept with the loops here if the hue values are in the aforementioned range and the + threshold is met then logic one else logic zero*/ + + datamono[i * stepmono + j * channelsmono] = 0; + } + } + } + + + //crosscheck all are either black or white + for (i = 0; i < (heighthsv); i++) { + for (j = 0; j < (widthhsv); j++) { + if (!(datamono[i * stepmono + j * channelsmono] == 0 || datamono[i + * stepmono + j * channelsmono] == 255)) + datamono[i * stepmono + j * channelsmono] = 0; + } + } + + + // get rid of noise + cvErode(monoimgbot, monoimgbot, 0, erodepipe); + cvDilate(monoimgbot, monoimgbot, 0, dilatepipe); + + CvMemStorage* storage; + CvSeq* contour; + + // Create dynamic structure and sequence. + storage = cvCreateMemStorage(0); + contour = cvCreateSeq(CV_SEQ_ELTYPE_POINT, sizeof(CvSeq), sizeof(CvPoint), + storage); + + + cvShowImage("processed", monoimgbot); + + // Find all contours. + cvFindContours(monoimgbot, storage, &contour, sizeof(CvContour), CV_RETR_LIST, + CV_CHAIN_APPROX_NONE, cvPoint(0, 0)); + + elipse retElipse; + retElipse.total=0; + retElipse.angle=-1; + + // This cycle draw all contours and approximate it by ellipses. + for(;contour;contour = contour->h_next) + { + + + int count = contour->total; // This is number point in contour + + CvBox2D box; + + // Number point must be more than or equal to 6 (for cvFitEllipse_32f). + if (count < 6) + continue; + + CvMat* points_f = cvCreateMat(1, count, CV_32FC2 ); + CvMat points_i = cvMat(1, count, CV_32SC2, points_f->data.ptr); + cvCvtSeqToArray(contour, points_f->data.ptr, CV_WHOLE_SEQ ); + cvConvert( &points_i, points_f ); + + // Fits ellipse to current contour. + box = cvFitEllipse2(points_f); + + // Draw current contour. + //cvDrawContours(image04,contour,CV_RGB(255,255,255),CV_RGB(255,255,255),0,1,8,cvPoint(0,0)); + + // Convert ellipse data from float to integer representation. + + if(count>retElipse.total) { + + retElipse.total = count; + retElipse.angle = box.angle; + retElipse.center = cvPointFrom32f(box.center); + retElipse.size.width = cvRound(box.size.width*0.5); + retElipse.size.height = cvRound(box.size.height*0.5); + } + + cvReleaseMat(&points_f); + + } + + + if(retElipse.angle!=-1) { + cvLine(monoimgbot, cvPoint(monoimgbot->width / 2, monoimgbot->height / 2), + cvPoint((monoimgbot->width / 2) + (100 * (sin((-retElipse.angle) + * 3.14159265 / 180))), (monoimgbot->height / 2) + (100 + * (cos(-retElipse.angle * 3.14159265 / 180)))), + CV_RGB(0,0,255), 5); + + cvCircle(monoimgbot, cvPoint(monoimgbot->width / 2, monoimgbot->height / 2), 10, + CV_RGB(0,0,255), 10); + + // Draw ellipse. + cvEllipse(monoimgbot, retElipse.center, retElipse.size, -retElipse.angle, 0, 360, CV_RGB(255,0,255), + 1, CV_AA, 0); + + + cvCircle(monoimgbot, retElipse.center, 20, CV_RGB(0,255,0), 3); + + + } + + + // Show image. HighGUI use. + + + cvReleaseImage(&colimgbot); + cvReleaseImage(&monoimgbot); + cvReleaseMemStorage(&storage); + + return retElipse; +} + +int showImage(char* functionName, char* img){ + + + cvNamedWindow("original", CV_WINDOW_AUTOSIZE); + + cvNamedWindow("processed", CV_WINDOW_AUTOSIZE); + + IplImage* image = cvLoadImage( img, CV_LOAD_IMAGE_COLOR ); + + //display the original image + cvShowImage("original", image); + + if(strcmp(functionName, "findBuoy")==0){ + + findBuoy(image); + } + else if(strcmp(functionName, "finalFindPipe")==0){ + + finalFindPipe(image); + } + + cvWaitKey(0); + + cvDestroyWindow("processed"); + cvDestroyWindow("original"); + + + +} + +int playVideo(char* functionName, char* video){ + + cvNamedWindow("original", CV_WINDOW_AUTOSIZE); + + cvNamedWindow("processed", CV_WINDOW_AUTOSIZE); + + //CvCapture* capture = cvCreateFileCapture("videos/pipe3.avi"); + //CvCapture* capture = cvCreateFileCapture("videos/ets2007pipe.avi"); + //CvCapture* capture = cvCreateFileCapture("videos/ets2007buoy.avi"); + //CvCapture* capture = cvCreateFileCapture("videos/cuauvFinalForward.avi"); + + CvCapture* capture = cvCreateFileCapture(video); + + IplImage *frame; + + if (!capture) { + + printf("Cannot open video file!\n"); + + return (1); + + } + + + for (;;) {/*keep looping till we are out of frames...*/ + + if (!cvGrabFrame(capture)) { + + break; + + } + + + frame = cvRetrieveFrame(capture); + + if (frame == NULL) { + puts("unable to load the frame"); + return 0; + } + + elipse retElipse; + //elipse retElipse = finalFindPipe(frame); + + if(strcmp("findBuoy",functionName)==0){ + + retElipse = findBuoy(frame); + } + else if(strcmp("finalFindPipe",functionName)==0){ + + retElipse = finalFindPipe(frame); + } + + if(retElipse.angle!=-1) { + cvLine(frame, cvPoint(frame->width / 2, frame->height / 2), + cvPoint((frame->width / 2) + (100 * (sin((-retElipse.angle) + * 3.14159265 / 180))), (frame->height / 2) + (100 + * (cos(-retElipse.angle * 3.14159265 / 180)))), + CV_RGB(0,0,255), 5); + + cvCircle(frame, cvPoint(frame->width / 2, frame->height / 2), 10, + CV_RGB(0,0,255), 10); + + // Draw ellipse. + cvEllipse(frame, retElipse.center, retElipse.size, -retElipse.angle, 0, 360, CV_RGB(255,0,255), + 1, CV_AA, 0); + + + cvCircle(frame, retElipse.center, 10, CV_RGB(0,255,0), 5); + + + } + + + cvShowImage("original", frame); + + + int c = cvWaitKey(150); + if ((char) c == 27) + break; + + } + + /* free memory */ + + + cvDestroyWindow("processed"); + cvDestroyWindow("original"); + + cvReleaseCapture(&capture); + + return 1; + +} + + + +int main(int argc, char** argv) { + + + //this part is for the reading of the config files + //thus setting the threshold values on the fly + readFile("config/buoy.txt", 1); + readFile("config/pipe.txt", 2); + //readFile("config/hedge.txt", 3); + + + playVideo("finalFindPipe", "videos/pipe3.avi"); + //showImage("findBuoy", "images/buoy.jpg"); + //playVideo("finalFindPipe", "videos/ets2007buoy.avi"); + //playVideo("findBuoy", "videos/ets2007buoy.avi"); + + if(argc<=1){ + + + + + + + + } + else{ + + + + } + + + + return 0; +} + + + + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |