00001 /* 00002 * SimpleRectangleFinder.cpp 00003 * 00004 * Created on: Feb 20, 2010 00005 * Author: uscr 00006 */ 00007 00008 #include "SimpleRectangleFinder.h" 00009 #include <cstdio> 00010 #include <cmath> 00011 00012 00013 SimpleRectangleFinder::SimpleRectangleFinder(IplImage * imgRef) { 00014 edges = cvCloneImage(imgRef); 00015 storage = cvCreateMemStorage(0); 00016 approxStorage = cvCreateMemStorage(0); 00017 00018 contours = 0; 00019 polyPoints = 0; 00020 00021 //Grab the Camera Calibration Data: 00022 cameraMat = (CvMat*)cvLoad(CV_CALIB_IFILE); 00023 distortMat = (CvMat*)cvLoad(CV_CALIB_DFILE); 00024 mapx = cvCreateImage( cvGetSize( imgRef ), IPL_DEPTH_32F, 1 ); 00025 mapy = cvCreateImage( cvGetSize( imgRef ), IPL_DEPTH_32F, 1 ); 00026 ideal = cvCreateImage( cvGetSize( imgRef ), IPL_DEPTH_8U, 1 ); 00027 cvInitUndistortMap( cameraMat, distortMat, mapx, mapy ); 00028 00029 00030 for (int i = 0; i < 4; i++) { 00031 rectDeformCorn.push_back(cvPoint2D32f(0,0)); 00032 rectFlatCorn.push_back(cvPoint2D32f(0,0)); 00033 } 00034 00035 } 00036 00037 SimpleRectangleFinder::~SimpleRectangleFinder() { 00038 cvReleaseImage (&edges); 00039 cvReleaseImage (&mapx); 00040 cvReleaseImage (&mapy); 00041 cvReleaseImage (&ideal); 00042 cvReleaseMat (&distortMat); 00043 cvReleaseMat (&cameraMat); 00044 00045 } 00046 00047 void SimpleRectangleFinder::search(IplImage * subj, int width, int & centerx, int & centery) { 00048 00049 contours = 0; 00050 polyPoints = 0; 00051 storage = cvCreateMemStorage(0); 00052 approxStorage = cvCreateMemStorage(0); 00053 int area; 00054 00055 //rather than f'ing around with the stupid cvUndistortPoints method which 00056 // does NOT want to work, let's just do a complete image undistort first 00057 // and ignore have distortion taken care of apriori 00058 //cvRemap(subj, ideal, mapx, mapy); 00059 00060 //Get lines from the image, clean up the lines, and then find the 00061 // countours from the lines 00062 cvCanny(subj, edges, CANNY_THRESH, CANNY_THRESH, 3); 00063 cvDilate(edges, edges, 0, 1); 00064 cvFindContours(edges, storage, &contours, sizeof(CvContour), 00065 CV_RETR_TREE, CV_CHAIN_APPROX_NONE, cvPoint(0, 0)); 00066 00067 for (CvSeq* curCont = contours; curCont != NULL; curCont = curCont->h_next) { 00068 polyPoints = cvApproxPoly(curCont, sizeof(CvContour), approxStorage, 00069 CV_POLY_APPROX_DP, cvContourPerimeter(curCont) * POLY_APPROX_ACCURACY, 0); 00070 00071 if (polyPoints->total == 4) { 00072 area = (int) abs(cvContourArea(polyPoints)); 00073 00074 if (area > AREA_THRESH) { 00075 00076 //Okay, so we think this is the one and we are going to go for it. 00077 // Next we need to convert the observed screen coordinates to 00078 // ideal screen coordinates. 00079 for (int i = 0; i < 4; i++) { 00080 rectDeformCorn[i].x = ((CvPoint *) cvGetSeqElem(polyPoints, i))->x; 00081 rectDeformCorn[i].y = ((CvPoint *) cvGetSeqElem(polyPoints, i))->y; 00082 } 00083 00084 //Compute the center by finding the intersection of the lines 00085 // created by the vertices idealized above 00086 center[0] = ((rectDeformCorn[0].x*rectDeformCorn[2].y - rectDeformCorn[2].x*rectDeformCorn[0].y)* 00087 (rectDeformCorn[1].x - rectDeformCorn[3].x) - 00088 (rectDeformCorn[1].x*rectDeformCorn[3].y - rectDeformCorn[3].x*rectDeformCorn[1].y)* 00089 (rectDeformCorn[0].x - rectDeformCorn[2].x)); 00090 center[0] /= ((rectDeformCorn[0].x - rectDeformCorn[2].x)* 00091 (rectDeformCorn[1].y - rectDeformCorn[3].y) - 00092 (rectDeformCorn[1].x - rectDeformCorn[3].x)* 00093 (rectDeformCorn[0].y - rectDeformCorn[2].y)); 00094 center[1] = ((rectDeformCorn[0].x*rectDeformCorn[2].y - rectDeformCorn[2].x*rectDeformCorn[0].y)* 00095 (rectDeformCorn[1].y - rectDeformCorn[3].y) - 00096 (rectDeformCorn[1].x*rectDeformCorn[3].y - rectDeformCorn[3].x*rectDeformCorn[1].y)* 00097 (rectDeformCorn[0].y - rectDeformCorn[2].y)); 00098 center[1] /= ((rectDeformCorn[0].x - rectDeformCorn[2].x)* 00099 (rectDeformCorn[1].y - rectDeformCorn[3].y) - 00100 (rectDeformCorn[1].x - rectDeformCorn[3].x)* 00101 (rectDeformCorn[0].y - rectDeformCorn[2].y)); 00102 00103 centerx = center[0]; 00104 centery = center[1]; 00105 00106 //Ok so this is the square placed at the center of where we are 00107 rectFlatCorn[1].x = rectFlatCorn[2].x = center[0] + width/2.0; 00108 rectFlatCorn[1].y = rectFlatCorn[0].y = center[1] + width/2.0; 00109 rectFlatCorn[3].x = rectFlatCorn[0].x = center[0] - width/2.0; 00110 rectFlatCorn[2].y = rectFlatCorn[3].y = center[1] - width/2.0; 00111 00112 //find the perspective transformation: 00113 CvMat * mapMatrix = cvCreateMat(3, 3, CV_32FC1); 00114 cvGetPerspectiveTransform (&rectFlatCorn[0], &rectDeformCorn[0], mapMatrix); 00115 00116 double angle1 = asin(cvmGet(mapMatrix, 1, 0)); 00117 double angle2 = acos(cvmGet(mapMatrix, 0, 0) / cos(angle1)); 00118 double angle3 = acos(cvmGet(mapMatrix, 1, 1) / cos(angle1)); 00119 00120 printf("-----------------------------\n"); 00121 printf ("[\t%f\t%f\t%f\t]\n", cvmGet(mapMatrix, 0, 0), cvmGet(mapMatrix, 0, 1), cvmGet(mapMatrix, 0, 2)); 00122 printf ("[\t%f\t%f\t%f\t]\n", cvmGet(mapMatrix, 1, 0), cvmGet(mapMatrix, 1, 1), cvmGet(mapMatrix, 1, 2)); 00123 printf ("[\t%f\t%f\t%f\t]\n", cvmGet(mapMatrix, 2, 0), cvmGet(mapMatrix, 2, 1), cvmGet(mapMatrix, 2, 2)); 00124 //printf ("angle1 = %f\n", angle1); 00125 //printf ("angle2 = %f\n", angle2); 00126 //printf ("angle3 = %f\n", angle3); 00127 00128 cvReleaseMat(&mapMatrix); 00129 } 00130 } 00131 } 00132 00133 cvReleaseMemStorage(&approxStorage); 00134 cvReleaseMemStorage(&storage); 00135 }