[Robotvision-commit] SF.net SVN: robotvision:[15] vision
Brought to you by:
phildavidson
From: <phi...@us...> - 2010-05-29 14:43:19
|
Revision: 15 http://robotvision.svn.sourceforge.net/robotvision/?rev=15&view=rev Author: phildavidson Date: 2010-05-29 14:43:13 +0000 (Sat, 29 May 2010) Log Message: ----------- Final Find Pipe Modified Paths: -------------- vision/images/flipper.png vision/src/test2.cpp vision/testimg.png Added Paths: ----------- vision/images/test1.PNG vision/images/test2.PNG vision/images/test3.PNG vision/images/test4.PNG vision/images/test5.PNG vision/images/test6.PNG vision/src/ellipse.cpp vision/src/main.cpp vision/src/pipe.cpp Removed Paths: ------------- vision/src/test.cpp Modified: vision/images/flipper.png =================================================================== (Binary files differ) Added: vision/images/test1.PNG =================================================================== (Binary files differ) Property changes on: vision/images/test1.PNG ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: vision/images/test2.PNG =================================================================== (Binary files differ) Property changes on: vision/images/test2.PNG ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: vision/images/test3.PNG =================================================================== (Binary files differ) Property changes on: vision/images/test3.PNG ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: vision/images/test4.PNG =================================================================== (Binary files differ) Property changes on: vision/images/test4.PNG ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: vision/images/test5.PNG =================================================================== (Binary files differ) Property changes on: vision/images/test5.PNG ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: vision/images/test6.PNG =================================================================== (Binary files differ) Property changes on: vision/images/test6.PNG ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: vision/src/ellipse.cpp =================================================================== --- vision/src/ellipse.cpp (rev 0) +++ vision/src/ellipse.cpp 2010-05-29 14:43:13 UTC (rev 15) @@ -0,0 +1,269 @@ +#ifdef _CH_ +#pragma package <opencv> +#endif + +#define CV_NO_BACKWARD_COMPATIBILITY + +#ifndef _EiC +#include "cv.h" +#include "highgui.h" +#include "cxcore.h" +#include "math.h" +#endif + + +typedef struct elipse { + + float angle; + int total; + CvPoint center; + CvSize size; + + +} elipse; + + + +elipse findPipe(IplImage *src) { + + int sthreshold = 86, erode = 4, dialate = 8; + + int hlower = 127, hupper = 25;/* + 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] <= hlower) + && (datahsv[(i) * stephsv + j * channelshsv] >= hupper)) { + if ((datahsv[(i) * stephsv + j * (channelshsv) + 1]) + > sthreshold) { + 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, erode); + cvDilate(monoimgbot, monoimgbot, 0, dialate); + + 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 zmain(int argc, char** argv) { + + 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"); + + 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 = findPipe(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 0; +} + + Added: vision/src/main.cpp =================================================================== --- vision/src/main.cpp (rev 0) +++ vision/src/main.cpp 2010-05-29 14:43:13 UTC (rev 15) @@ -0,0 +1,420 @@ +#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; + +//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 + +point findBuoy(IplImage* img) { + + point p; + p.x = 0.0; + p.y = 0.0; + + //these are the threshold values + int sthreshold = 194;//210; + double hlower = 178; + double hupper = 3; + + //create the windows: + //this is for the original image + cvNamedWindow("orig", CV_WINDOW_AUTOSIZE); + //this is for the smoothed image + cvNamedWindow("smooth", CV_WINDOW_AUTOSIZE); + //this is for the binary image (thresholding) + cvNamedWindow("binary", CV_WINDOW_AUTOSIZE); + + //display the original image + cvShowImage("orig", img); + + //we smooth the image and store the smooth img back in img + cvSmooth(img, img, CV_GAUSSIAN, 3, 3, 0, 0); + + //display the smoothed image + cvShowImage("smooth", img); + + //these are the properties of the image + //we will use them to loop through the data array (the image buffer) + int height = img->height; + int width = img->width; + int step = img->widthStep; + int nChannels = img->nChannels; + + //this is the image buffer + uchar *data = (uchar*) img->imageData; + + int i; + int j; + + for (i = 0; i < height; i++) { + + for (j = 0; j < width; j++) { + + if ((data[i * step + j * nChannels + 2] >= hlower) && (data[i + * step + j * nChannels + 2] >= hupper)) { + + if ((data[i * step + j * nChannels + 2]) > sthreshold) { + + data[i * step + j * nChannels + 0] = 255; + + data[i * step + j * nChannels + 1] = 255; + + data[i * step + j * nChannels + 2] = 255; + + } else { + data[i * step + j * nChannels + 0] = 0; + + data[i * step + j * nChannels + 1] = 0; + + data[i * step + j * nChannels + 2] = 0; + + } + + } else { + + data[i * step + j * nChannels + 0] = 0; + + data[i * step + j * nChannels + 1] = 0; + + data[i * step + j * nChannels + 2] = 0; + + } + + }//end inner for loop + + }//end outer for loop + + cvErode(img, img, 0, 6); + cvDilate(img, img, 0, 10); + + //display the binary image + cvShowImage("binary", img); + + cvWaitKey(0); + + cvDestroyWindow("orig"); + cvDestroyWindow("smooth"); + cvDestroyWindow("binary"); + + cvWaitKey(0); + + return p; + +} + +//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;/* + 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] <= hlower) + && (datahsv[(i) * stephsv + j * channelshsv] >= hupper)) { + if ((datahsv[(i) * stephsv + j * (channelshsv) + 1]) + > sthreshold) { + 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, erode); + cvDilate(monoimgbot, monoimgbot, 0, dialate); + + 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 main(int argc, char** argv) { + + 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"); + + 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 = 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 0; +} + + + + Copied: vision/src/pipe.cpp (from rev 14, vision/src/test.cpp) =================================================================== --- vision/src/pipe.cpp (rev 0) +++ vision/src/pipe.cpp 2010-05-29 14:43:13 UTC (rev 15) @@ -0,0 +1,391 @@ + + +#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> + + +/*the includes*/ +/*This program is not done in CVBlob library*/ +/*Purpose of the program to track the blob */ +//using namespace std; + + +/*Note:The detection algorithm is the same as the one you can find in one of my previous posts + + The same algorithm is copied from that post and pasted in this + post only the values of the "sthreshold" and the "hupper" and the "hlower" are different....*/ +//CvSeq* findSquares4(IplImage* img); +//double angle(CvPoint* pt1, CvPoint* pt2, CvPoint* pt0); +//void drawSquares(IplImage* img, CvSeq* squares); +//int findPipe(); + + +namespace pipe { + +double angle(CvPoint* pt1, CvPoint* pt2, CvPoint* pt0) { + double dx1 = pt1->x - pt0->x; + double dy1 = pt1->y - pt0->y; + double dx2 = pt2->x - pt0->x; + double dy2 = pt2->y - pt0->y; + return (dx1 * dx2 + dy1 * dy2) / sqrt((dx1 * dx1 + dy1 * dy1) * (dx2 * dx2 + + dy2 * dy2) + 1e-10); +} + +// returns sequence of squares detected on the image. +// the sequence is stored in the specified memory storage +CvSeq* findSquares4(IplImage* img) { + int thresh = 50; + CvSeq* contours; + int i, c, l, N = 11; + CvSize sz = cvSize(img->width & -2, img->height & -2); + IplImage* timg = cvCloneImage(img); // make a copy of input image + IplImage* gray = cvCreateImage(sz, 8, 1); + IplImage* pyr = cvCreateImage(cvSize(sz.width / 2, sz.height / 2), 8, 3); + IplImage* tgray; + CvSeq* result; + double s, t; + + CvMemStorage* storage = 0; + + storage = cvCreateMemStorage(0); + + // create empty sequence that will contain points - + // 4 points per square (the square's vertices) + CvSeq* squares = cvCreateSeq(0, sizeof(CvSeq), sizeof(CvPoint), storage); + + // select the maximum ROI in the image + // with the width and height divisible by 2 + cvSetImageROI(timg, cvRect(0, 0, sz.width, sz.height)); + + // down-scale and upscale the image to filter out the noise + cvPyrDown(timg, pyr, 7); + cvPyrUp(pyr, timg, 7); + tgray = cvCreateImage(sz, 8, 1); + + // find squares in every color plane of the image + for (c = 0; c < 3; c++) { + // extract the c-th color plane + cvSetImageCOI(timg, c + 1); + cvCopy(timg, tgray, 0); + + // try several threshold levels + for (l = 0; l < N; l++) { + // hack: use Canny instead of zero threshold level. + // Canny helps to catch squares with gradient shading + if (l == 0) { + // apply Canny. Take the upper threshold from slider + // and set the lower to 0 (which forces edges merging) + cvCanny(tgray, gray, 0, thresh, 5); + // dilate canny output to remove potential + // holes between edge segments + cvDilate(gray, gray, 0, 1); + } else { + // apply threshold if l!=0: + // tgray(x,y) = gray(x,y) < (l+1)*255/N ? 255 : 0 + cvThreshold(tgray, gray, (l + 1) * 255 / N, 255, + CV_THRESH_BINARY ); + } + + // find contours and store them all as a list + cvFindContours(gray, storage, &contours, sizeof(CvContour), + CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0, 0)); + + // test each contour + while (contours) { + // approximate contour with accuracy proportional + // to the contour perimeter + result = cvApproxPoly(contours, sizeof(CvContour), storage, + CV_POLY_APPROX_DP, cvContourPerimeter(contours) * 0.02, + 0); + // square contours should have 4 vertices after approximation + // relatively large area (to filter out noisy contours) + // and be convex. + // Note: absolute value of an area is used because + // area may be positive or negative - in accordance with the + // contour orientation + if (result->total == 4 + && cvContourArea(result, CV_WHOLE_SEQ, 0) > 1000 + && cvCheckContourConvexity(result)) { + s = 0; + + for (i = 0; i < 5; i++) { + // find minimum angle between joint + // edges (maximum of cosine) + if (i >= 2) { + t = fabs(angle((CvPoint*) cvGetSeqElem(result, i), + (CvPoint*) cvGetSeqElem(result, i - 2), + (CvPoint*) cvGetSeqElem(result, i - 1))); + s = s > t ? s : t; + } + } + + // if cosines of all angles are small + // (all angles are ~90 degree) then write quandrange + // vertices to resultant sequence + if (s < 0.3) + for (i = 0; i < 4; i++) + cvSeqPush(squares, (CvPoint*) cvGetSeqElem(result, + i)); + } + + // take the next contour + contours = contours->h_next; + } + } + } + + // release all the temporary images + cvReleaseImage(&gray); + cvReleaseImage(&pyr); + cvReleaseImage(&tgray); + cvReleaseImage(&timg); + cvClearMemStorage(storage); + return squares; +} + +// the function draws all the squares in the image +void drawSquares(IplImage* img, CvSeq* squares) { + CvSeqReader reader; + //IplImage* cpy = cvCloneImage( img ); + int i; + + // initialize reader of the sequence + cvStartReadSeq(squares, &reader, 0); + + // read 4 sequence elements at a time (all vertices of a square) + for (i = 0; i < squares->total; i += 4) { + CvPoint pt[4], *rect = pt; + int count = 4; + + // read 4 vertices + CV_READ_SEQ_ELEM( pt[0], reader ); + CV_READ_SEQ_ELEM( pt[1], reader ); + CV_READ_SEQ_ELEM( pt[2], reader ); + CV_READ_SEQ_ELEM( pt[3], reader ); + + // draw the square as a closed polyline + cvPolyLine(img, &rect, &count, 1, 1, CV_RGB(0,255,0), 3, CV_AA, 0); + } + + // show the resultant image + //cvReleaseImage( &cpy ); +} + +int findPipe() { + + int sthreshold = 86, erode = 4, dialate = 8; + + int hlower = 127, hupper = 25;/* + here hlower is the lower cut off and the hupper is the upper cut off for hue values of red.*/ + + cvNamedWindow("original", CV_WINDOW_AUTOSIZE); + + cvNamedWindow("processed", CV_WINDOW_AUTOSIZE); + + //cvCreateTrackbar("sthreshold", "Monochrome Of red Blob", &sthreshold, 255, 0); + //cvCreateTrackbar("hlower", "Monochrome Of red Blob", &hlower, 255, 0); + //cvCreateTrackbar("hupper", "Monochrome Of red Blob", &hupper, 255, 0); + //cvCreateTrackbar("erode", "Monochrome Of red Blob", &erode, 20, 0); + //cvCreateTrackbar("dialate", "Monochrome Of red Blob", &dialate, 20, 0); + + int i, j, k;//for iterations + int temp = 0;//if we use a temporary var + /*here lets look at the word \x93heighthsv\x94 \x85now lets breadk up this word\x85here height means + + height as a regular IplImage Structure has now the addition \x93hsv\x94 to the word heigh means this + height attribute is for the image which is color converted to the hsv,Similar conventions + for the monochrome image\x85so you may find the attribute height for the monochrome image to be + heightmono\x85So i believe it is easy\x85*/ + int heighthsv, widthhsv, stephsv, channelshsv; + int heightmono, widthmono, stepmono, channelsmono; + uchar *datahsv, *datamono; + + IplImage *frame; + IplImage *colimgbot; + + IplImage *monoimgbot; + + CvCapture* capture = cvCreateFileCapture("videos/pipe3.avi"); + //CvCapture* capture = cvCreateFileCapture("videos/ets2007pipe.avi"); + + // CvSize size = cvSize((int) cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH), (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT)); + + //CvVideoWriter* writer = cvCreateVideoWriter(string1, CV_FOURCC( 'D','I','V','X'), fps, size); + + /* always check */ + + if (!capture) { + + printf("Cannot open video file!\n"); + + return (1); + + } + + /* create a window for the video,one for the monochrome image and the other for the original frame */ + + //if (!cvGrabFrame(capture)) { + + //break; + + // } + + //frame = cvRetrieveFrame(capture); + + for (;;) {/*keep looping till we are out of frames...*/ + + if (!cvGrabFrame(capture)) { + + break; + + } + + /*colimgbot---means color image of the bot*/ + + frame = cvRetrieveFrame(capture); + + if (frame == NULL) { + puts("unable to load the frame"); + return 0; + } + //printf("frame loaded"); + + colimgbot = cvCreateImage(cvGetSize(frame), 8, 3); + + monoimgbot = cvCreateImage(cvGetSize(frame), 8, 1); + + cvCvtColor(frame, 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] <= hlower) + && (datahsv[(i) * stephsv + j * channelshsv] >= hupper)) { + if ((datahsv[(i) * stephsv + j * (channelshsv) + 1]) + > sthreshold) { + 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; + } + } + } + + 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; + } + } + + /*Just a cross chek to ensure whether all the pixels have only + either 0 or 255*/ + + /*Please check these links for the explanation of the erosion and dilation functions + + + + + http://www.dca.fee.unicamp.br/dipcourse/html-dip/c9/s4/front-page.html*/ + + /*so now the last parameter in the function indicates how many times you want to apply dilation + + or erosion*/ + + cvErode(monoimgbot, monoimgbot, 0, erode); + cvDilate(monoimgbot, monoimgbot, 0, dialate); + /*here i have experimented with the values by changing them\x85and i have found + that i come to a good result by applying erosion 6 times and dilation 15 times + you can comment/uncomment play with the values and see what is going on + Sometimes you will find the areas which are shining in the image also get detected\x85 + + Please think why and then try to post a comment the best commment would get visible on this page*/ + + int w = 0; + int countw = 0; + int h = 0; + int counth = 0; + + for (i = 0; i < (heighthsv); i++) { + for (j = 0; j < (widthhsv); j++) { + if (datamono[i * stepmono + j * channelsmono] == 255) { + + w += j; + countw++; + h += i; + counth++; + } + } + } + + if (countw != 0 && counth != 0) { + w = w / countw; + h = h / counth; + } + cvCircle(frame, cvPoint(w, h), 20, cvScalar(0, 255, 0), 1); + + //printf("w: %i, h: %i", w, h); + + cvSaveImage("testimg.png", monoimgbot); + //cvCvtColor(monoimgbot, img2, CV_GRAY2RGB); + + + IplImage * img2 = cvLoadImage("testimg.png", 1); + + drawSquares(img2, findSquares4(img2)); + + cvCircle(img2, cvPoint(w, h), 20, cvScalar(0, 255, 0), 1); + + cvShowImage("original", frame); + //cvSaveImage("red-ballmonochrome.jpg",monoimgbot);/*if you want to save the image*/ + cvShowImage("processed", img2); + int c = cvWaitKey(100); + if ((char) c == 27) + break; + /*for all the other clarifications you can check the other posts\x85. you will find an answer + People who are getting started with the Opencv must make sure you + + check the other posts on this blog*/ + } + + /* free memory */ + + //cvReleaseVideoWriter(&writer); + + cvDestroyWindow("processed"); + cvDestroyWindow("original"); + + cvReleaseCapture(&capture); + + return 0; +} +} + + Deleted: vision/src/test.cpp =================================================================== --- vision/src/test.cpp 2010-05-24 19:27:52 UTC (rev 14) +++ vision/src/test.cpp 2010-05-29 14:43:13 UTC (rev 15) @@ -1,375 +0,0 @@ -#include "iostream" -#include "stdlib.h" -#include "stdio.h" -#include "cv.h" -#include "highgui.h" -#include "cstring" - -/*the includes*/ -/*This program is not done in CVBlob library*/ -/*Purpose of the program to track the blob */ -using namespace std; - -/*Note:The detection algorithm is the same as the one you can find in one of my previous posts - - The same algorithm is copied from that post and pasted in this - post only the values of the "sthreshold" and the "hupper" and the "hlower" are different....*/ - -double angle(CvPoint* pt1, CvPoint* pt2, CvPoint* pt0) { - double dx1 = pt1->x - pt0->x; - double dy1 = pt1->y - pt0->y; - double dx2 = pt2->x - pt0->x; - double dy2 = pt2->y - pt0->y; - return (dx1 * dx2 + dy1 * dy2) / sqrt((dx1 * dx1 + dy1 * dy1) * (dx2 * dx2 - + dy2 * dy2) + 1e-10); -} - -// returns sequence of squares detected on the image. -// the sequence is stored in the specified memory storage -CvSeq* findSquares4(IplImage* img) { - int thresh = 50; - CvSeq* contours; - int i, c, l, N = 11; - CvSize sz = cvSize(img->width & -2, img->height & -2); - IplImage* timg = cvCloneImage(img); // make a copy of input image - IplImage* gray = cvCreateImage(sz, 8, 1); - IplImage* pyr = cvCreateImage(cvSize(sz.width / 2, sz.height / 2), 8, 3); - IplImage* tgray; - CvSeq* result; - double s, t; - - CvMemStorage* storage = 0; - - storage = cvCreateMemStorage(0); - - // create empty sequence that will contain points - - // 4 points per square (the square's vertices) - CvSeq* squares = cvCreateSeq(0, sizeof(CvSeq), sizeof(CvPoint), storage); - - // select the maximum ROI in the image - // with the width and height divisible by 2 - cvSetImageROI(timg, cvRect(0, 0, sz.width, sz.height)); - - // down-scale and upscale the image to filter out the noise - cvPyrDown(timg, pyr, 7); - cvPyrUp(pyr, timg, 7); - tgray = cvCreateImage(sz, 8, 1); - - // find squares in every color plane of the image - for (c = 0; c < 3; c++) { - // extract the c-th color plane - cvSetImageCOI(timg, c + 1); - cvCopy(timg, tgray, 0); - - // try several threshold levels - for (l = 0; l < N; l++) { - // hack: use Canny instead of zero threshold level. - // Canny helps to catch squares with gradient shading - if (l == 0) { - // apply Canny. Take the upper threshold from slider - // and set the lower to 0 (which forces edges merging) - cvCanny(tgray, gray, 0, thresh, 5); - // dilate canny output to remove potential - // holes between edge segments - cvDilate(gray, gray, 0, 1); - } else { - // apply threshold if l!=0: - // tgray(x,y) = gray(x,y) < (l+1)*255/N ? 255 : 0 - cvThreshold(tgray, gray, (l + 1) * 255 / N, 255, - CV_THRESH_BINARY ); - } - - // find contours and store them all as a list - cvFindContours(gray, storage, &contours, sizeof(CvContour), - CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0, 0)); - - // test each contour - while (contours) { - // approximate contour with accuracy proportional - // to the contour perimeter - result = cvApproxPoly(contours, sizeof(CvContour), storage, - CV_POLY_APPROX_DP, cvContourPerimeter(contours) * 0.02, - 0); - // square contours should have 4 vertices after approximation - // relatively large area (to filter out noisy contours) - // and be convex. - // Note: absolute value of an area is used because - // area may be positive or negative - in accordance with the - // contour orientation - if (result->total == 4 - && cvContourArea(result, CV_WHOLE_SEQ, 0) > 1000 - && cvCheckContourConvexity(result)) { - s = 0; - - for (i = 0; i < 5; i++) { - // find minimum angle between joint - // edges (maximum of cosine) - if (i >= 2) { - t = fabs(angle((CvPoint*) cvGetSeqElem(result, i), - (CvPoint*) cvGetSeqElem(result, i - 2), - (CvPoint*) cvGetSeqElem(result, i - 1))); - s = s > t ? s : t; - } - } - - // if cosines of all angles are small - // (all angles are ~90 degree) then write quandrange - // vertices to resultant sequence - if (s < 0.3) - for (i = 0; i < 4; i++) - cvSeqPush(squares, (CvPoint*) cvGetSeqElem(result, - i)); - } - - // take the next contour - contours = contours->h_next; - } - } - } - - // release all the temporary images - cvReleaseImage(&gray); - cvReleaseImage(&pyr); - cvReleaseImage(&tgray); - cvReleaseImage(&timg); - cvClearMemStorage(storage); - return squares; -} - -// the function draws all the squares in the image -void drawSquares(IplImage* img, CvSeq* squares) { - CvSeqReader reader; - //IplImage* cpy = cvCloneImage( img ); - int i; - - // initialize reader of the sequence - cvStartReadSeq(squares, &reader, 0); - - // read 4 sequence elements at a time (all vertices of a square) - for (i = 0; i < squares->total; i += 4) { - CvPoint pt[4], *rect = pt; - int count = 4; - - // read 4 vertices - CV_READ_SEQ_ELEM( pt[0], reader ); - CV_READ_SEQ_ELEM( pt[1], reader ); - CV_READ_SEQ_ELEM( pt[2], reader ); - CV_READ_SEQ_ELEM( pt[3], reader ); - - // draw the square as a closed polyline - cvPolyLine(img, &rect, &count, 1, 1, CV_RGB(0,255,0), 3, CV_AA, 0); - } - - // show the resultant image - //cvReleaseImage( &cpy ); -} - -int main(int argc, char** argv) - -{ - int sthreshold = 86, erode = 4, dialate = 8; - - int hlower = 127, hupper = 18;/* - here hlower is the lower cut off and the hupper is the upper cut off for hue values of red.*/ - - cvNamedWindow("original", CV_WINDOW_AUTOSIZE); - - cvNamedWindow("processed", CV_WINDOW_AUTOSIZE); - - //cvCreateTrackbar("sthreshold", "Monochrome Of red Blob", &sthreshold, 255, 0); - //cvCreateTrackbar("hlower", "Monochrome Of red Blob", &hlower, 255, 0); - //cvCreateTrackbar("hupper", "Monochrome Of red Blob", &hupper, 255, 0); - //cvCreateTrackbar("erode", "Monochrome Of red Blob", &erode, 20, 0); - //cvCreateTrackbar("dialate", "Monochrome Of red Blob", &dialate, 20, 0); - - int i, j, k;//for iterations - int temp = 0;//if we use a temporary var - /*here lets look at the word \x93heighthsv\x94 \x85now lets breadk up this word\x85here height means - - height as a regular IplImage Structure has now the addition \x93hsv\x94 to the word heigh means this - height attribute is for the image which is color converted to the hsv,Similar conventions - for the monochrome image\x85so you may find the attribute height for the monochrome image to be - heightmono\x85So i believe it is easy\x85*/ - int heighthsv, widthhsv, stephsv, channelshsv; - int heightmono, widthmono, stepmono, channelsmono; - uchar *datahsv, *datamono; - - IplImage *frame; - IplImage *colimgbot; - - IplImage *monoimgbot; - - CvCapture* capture = cvCreateFileCapture("videos/pipe3.avi"); - //CvCapture* capture = cvCreateFileCapture("videos/ets2007pipe.avi"); - - // CvSize size = cvSize((int) cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH), (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT)); - - //CvVideoWriter* writer = cvCreateVideoWriter(string1, CV_FOURCC( 'D','I','V','X'), fps, size); - - /* always check */ - - if (!capture) { - - printf("Cannot open video file!\n"); - - return (1); - - } - - /* create a window for the video,one for the monochrome image and the other for the original frame */ - - //if (!cvGrabFrame(capture)) { - - //break; - - // } - - //frame = cvRetrieveFrame(capture); - - for (;;) {/*keep looping till we are out of frames...*/ - - if (!cvGrabFrame(capture)) { - - break; - - } - - /*colimgbot---means color image of the bot*/ - - frame = cvRetrieveFrame(capture); - - if (frame == NULL) { - puts("unable to load the frame"); - exit(0); - } - //printf("frame loaded"); - - colimgbot = cvCreateImage(cvGetSize(frame), 8, 3); - - monoimgbot = cvCreateImage(cvGetSize(frame), 8, 1); - - cvCvtColor(frame, 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] <= hlower) - && (datahsv[(i) * stephsv + j * channelshsv] >= hupper)) { - if ((datahsv[(i) * stephsv + j * (channelshsv) + 1]) - > sthreshold) { - 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; - } - } - } - - 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; - } - } - - /*Just a cross chek to ensure whether all the pixels have only - either 0 or 255*/ - - /*Please check these links for the explanation of the erosion and dilation functions - - - - - http://www.dca.fee.unicamp.br/dipcourse/html-dip/c9/s4/front-page.html*/ - - /*so now the last parameter in the function indicates how many times you want to apply dilation - - or erosion*/ - - cvErode(monoimgbot, monoimgbot, 0, erode); - cvDilate(monoimgbot, monoimgbot, 0, dialate); - /*here i have experimented with the values by changing them\x85and i have found - that i come to a good result by applying erosion 6 times and dilation 15 times - you can comment/uncomment play with the values and see what is going on - Sometimes you will find the areas which are shining in the image also get detected\x85 - - Please think why and then try to post a comment the best commment would get visible on this page*/ - - int w = 0; - int countw = 0; - int h = 0; - int counth = 0; - - for (i = 0; i < (heighthsv); i++) { - for (j = 0; j < (widthhsv); j++) { - if (datamono[i * stepmono + j * channelsmono] == 255) { - - w += j; - countw++; - h += i; - counth++; - } - } - } - - if(countw!=0 && counth!=0) { - w = w / countw; - h = h / counth; - } - cvCircle(frame, cvPoint(w, h), 20, cvScalar(0, 255, 0), 1); - - //printf("w: %i, h: %i", w, h); - - cvSaveImage("testimg.png", monoimgbot); - //cvCvtColor(monoimgbot, img2, CV_GRAY2RGB); - - - IplImage * img2 = cvLoadImage("testimg.png", 1); - - drawSquares(img2, findSquares4(img2)); - - cvCircle(img2, cvPoint(w, h), 20, cvScalar(0, 255, 0), 1); - - cvShowImage("original", frame); - //cvSaveImage("red-ballmonochrome.jpg",monoimgbot);/*if you want to save the image*/ - cvShowImage("processed", img2); - int c = cvWaitKey(100); - if ((char) c == 27) - break; - /*for all the other clarifications you can check the other posts\x85. you will find an answer - People who are getting started with the Opencv must make sure you - - check the other posts on this blog*/ - } - - - - /* free memory */ - - //cvReleaseVideoWriter(&writer); - - cvDestroyWindow("processed"); - cvDestroyWindow("original"); - - cvReleaseCapture(&capture); - - exit(0); -} - Modified: vision/src/test2.cpp =================================================================== --- vision/src/test2.cpp 2010-05-24 19:27:52 UTC (rev 14) +++ vision/src/test2.cpp 2010-05-29 14:43:13 UTC (rev 15) @@ -7,9 +7,9 @@ #include"stdio.h" int bmain() { - int sthreshold = 68, erode = 6, dialate = 10; + int sthreshold = 68, erode = 4, dialate = 8; - int hlower = 127, hupper = 5;/* + int hlower = 127, hupper = 25;/* here hlower is the lower cut off and the hupper is the upper cut off for hue values of red.*/ cvNamedWindow("original", CV_WINDOW_AUTOSIZE); @@ -49,7 +49,9 @@ //frame = cvLoadImage("images/3dballs.jpg", 1); - frame=cvLoadImage("images/flipper.png",1); + //frame=cvLoadImage("images/flipper.png",1); + frame=cvLoadImage("images/test6.png",1); + //frame=cvLoadImage("images/pipe.png",1); if (frame == NULL) { puts("unable to load the frame"); Modified: vision/testimg.png =================================================================== (Binary files differ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |