00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "VisualVector.h"
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 VisualVector::VisualVector()
00026 {
00027 WorkingImage = NULL;
00028 RawImage = NULL;
00029 Debug = false;
00030
00031 capture = cvCaptureFromCAM(CV_CAP_ANY);
00032 if (!capture)
00033 {
00034 cout << "no capture device available" << endl;
00035 exit(1);
00036 }
00037
00038 cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, 320);
00039 cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, 240);
00040
00041 }
00042
00043 VisualVector::VisualVector(bool debug)
00044 {
00045 WorkingImage = NULL;
00046 RawImage = NULL;
00047 Debug = debug;
00048
00049 capture = cvCaptureFromCAM(CV_CAP_ANY);
00050 if (!capture)
00051 {
00052 cout << "no capture device available" << endl;
00053 exit(1);
00054 }
00055
00056 cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, 320);
00057 cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, 240);
00058
00059
00060 }
00061
00062
00063 VisualVector::~VisualVector()
00064 {
00065
00066 cvReleaseCapture(&capture);
00067
00068 }
00069
00070
00071
00072
00073
00074
00075
00076 Measurement VisualVector::GetMeasurement()
00077 {
00078
00079 return 0;
00080 }
00081
00082
00083
00084 Vector VisualVector::GetVectorMeasurement()
00085 {
00086 int check;
00087 float a1,a2;
00088 long double a3;
00089 double a1deg,a2deg,a3deg;
00090 int pixelheight,pixelwidth;
00091
00092 const int CENTZEROTILT[2] = {140,154};
00093 const double RUNIT = 17.2;
00094 const double HUNIT = 88.25;
00095 const double PI = 3.1415926535897932384626433832795028841971693993751;
00096
00097
00098 RawImage = cvQueryFrame(capture);
00099 if (!RawImage)
00100 {
00101 cout << "no WorkingImage captured" << endl;
00102 exit(1);
00103 }
00104
00105 WorkingImage = cvCreateImage(cvSize(RawImage->width,RawImage->height),IPL_DEPTH_8U,1);
00106
00107 cvConvertImage(RawImage,WorkingImage,CV_CVTIMG_FLIP);
00108
00109 pixelheight = WorkingImage->height;
00110 pixelwidth = WorkingImage->width;
00111
00112 check = FindVertex();
00113
00114 if (check != 0)
00115 {
00116 if (check == 1)
00117 cout << "Error within FindVertex: Equilateral Triangle Inputted.\n";
00118 else if (check == 2)
00119 cout << "Error within FindVertex: Area mismatch - is whole triangle present?\n";
00120 else if (check == 3)
00121 cout << "Error within FindVertex: Intensity mismatch - are lights on?\n";
00122 else if (check == 4)
00123 cout << "Error within FindVertex: Vertex Index out of Image\n";
00124 else
00125 cout << "Error within FindVertex: Unknown Error\n";
00126 return 0;
00127 }
00128
00129
00130
00131 cvReleaseImage(&WorkingImage);
00132 WorkingImage = NULL;
00133 RawImage = NULL;
00134
00135 capture = NULL;
00136
00137
00138 a3 = RotationAngleFunc(pixelwidth, pixelheight);
00139 a3deg = (180 * a3) / PI;
00140
00141 a1 = TiltAngle1Func(a3, pixelheight, pixelwidth, CENTZEROTILT, RUNIT, HUNIT);
00142 a1deg = (a1 * 180) / PI;
00143
00144 a2 = TiltAngle2Func(a3, pixelheight, pixelwidth, CENTZEROTILT, RUNIT, HUNIT);
00145 a2deg = (a2 * 180) / PI;
00146
00147 if (Debug == true)
00148 {
00149 cout << endl << "Corner Locations (furthest vertex listed first):\nx1: "
00150 << vertex[0] << "\ty1: " << vertex[1] << "\nx2: " << vertex[2]
00151 << "\ty2: " << vertex[3] << "\nx3: " << vertex[4] << "\ty3: "
00152 << vertex[5] << endl << "Centroid:\n x: " << centroid[0]
00153 << "\n y: " << centroid[1] << endl << endl;
00154
00155 cout << "Angle about the N1 axis (deg) = " << a1deg << endl;
00156 cout << "Angle about the N2 axis (deg) = " << a2deg << endl;
00157 cout << "Angle about the N3 axis (deg) = " << a3deg << endl << endl;
00158 }
00159
00160 Vector AngleVals(3);
00161 AngleVals(1) = a1deg;
00162 AngleVals(2) = a2deg;
00163 AngleVals(3) = a3deg;
00164 return AngleVals;
00165 }
00166
00167
00168
00169
00170
00171
00172
00173 int VisualVector::FindVertex()
00174 {
00175 const double MIN_DISTANCE = 45;
00176 const double QUALITY = 0.01;
00177
00178
00179 const int MAX_COUNT = 3;
00180 int corner_count;
00181 int check;
00182 double area;
00183
00184 IplImage *temp = NULL, *eigenval = NULL;
00185
00186 corner_count = MAX_COUNT;
00187 CvPoint2D32f corners[3];
00188
00189 eigenval = cvCreateImage(cvSize(WorkingImage->width,WorkingImage->height),32,1);
00190 temp = cvCreateImage(cvSize(WorkingImage->width,WorkingImage->height),32,1);
00191
00192
00193 cvCornerMinEigenVal(WorkingImage, eigenval,3,3);
00194
00195 cvGoodFeaturesToTrack(WorkingImage, eigenval, temp, corners, &corner_count, QUALITY, MIN_DISTANCE, NULL, 3, 0, 0.04);
00196
00197
00198 cvReleaseImage(&temp); cvReleaseImage(&eigenval);
00199 temp = NULL; eigenval = NULL;
00200
00201 vertex[0] = int(corners[0].x); vertex[1] = int(corners[0].y); vertex[2] = int(corners[1].x);
00202 vertex[3] = int(corners[1].y); vertex[4] = int(corners[2].x); vertex[5] = int(corners[2].y);
00203
00204 check = VertexSwitch();
00205 if (check != 0)
00206 return 1;
00207
00208
00209 area = (vertex[0]*vertex[5]-vertex[0]*vertex[3]+vertex[2]*vertex[1]-vertex[2]*vertex[5]
00210 +vertex[4]*vertex[3]-vertex[4]*vertex[1])/2;
00211 area = fabs(area);
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224 centroid[0] = double(vertex[0]+vertex[2]+vertex[4])/3;
00225 centroid[1] = double(vertex[1]+vertex[3]+vertex[5])/3;
00226
00227 if (Debug == true)
00228 {
00229
00230
00231 IplImage *color = NULL;
00232
00233 CvScalar red; red.val[0] = 0; red.val[1] = 0; red.val[2] = 255;
00234 CvScalar blue; blue.val[0] = 255; blue.val[1] = 0; blue.val[2] = 0;
00235 CvScalar black; black.val[0] = 0; black.val[1] = 0; black.val[2] = 0;
00236
00237 color = cvCreateImage(cvSize(WorkingImage->width,WorkingImage->height),8, 3);
00238
00239 cvCvtColor(WorkingImage,color,CV_GRAY2RGB);
00240
00241 cvSet2D(color,int(corners[0].y),int(corners[0].x),red);
00242 cvSet2D(color,int(corners[1].y),int(corners[1].x),red);
00243 cvSet2D(color,int(corners[2].y),int(corners[2].x),red);
00244 cvSet2D(color,int(centroid[1]),int(centroid[0]),blue);
00245
00246 cvSaveImage("ImageFeatures.bmp",color);
00247 cvReleaseImage(&color);
00248 color = NULL;
00249 }
00250
00251 return 0;
00252 }
00253
00254
00255
00256
00257 int VisualVector::VertexSwitch()
00258 {
00259 int tempVertex;
00260 double dist1,dist2,dist3;
00261
00262
00263 dist1 = sqrt(pow(double(vertex[0] - vertex[2]),2) + pow(double(vertex[1] - vertex[3]),2));
00264 dist2 = sqrt(pow(double(vertex[0] - vertex[4]),2) + pow(double(vertex[1] - vertex[5]),2));
00265 dist3 = sqrt(pow(double(vertex[2] - vertex[4]),2) + pow(double(vertex[3] - vertex[5]),2));
00266
00267 if ((dist3 < dist1) && (dist3 <= dist2));
00268 else if ((dist2 < dist1) && (dist2 <= dist3))
00269 {
00270 tempVertex = vertex[0];
00271 vertex[0] = vertex[2];
00272 vertex[2] = tempVertex;
00273 tempVertex = vertex[1];
00274 vertex[1] = vertex[3];
00275 vertex[3] = tempVertex;
00276 }
00277 else if ((dist1 < dist2) && (dist1 <= dist3))
00278 {
00279 tempVertex = vertex[0];
00280 vertex[0] = vertex[4];
00281 vertex[4] = tempVertex;
00282 tempVertex = vertex[1];
00283 vertex[1] = vertex[5];
00284 vertex[5] = tempVertex;
00285 }
00286 else
00287 return 1;
00288
00289 return 0;
00290 }
00291
00292
00293
00294 long double VisualVector::RotationAngleFunc(int pixelwidth, int pixelheight)
00295 {
00296
00297
00298
00299
00300 const double PI = 3.1415926535897932384626433832795028841971693993751;
00301
00302 if (centroid[0] < 0 || centroid[1] < 0 || vertex[0] < 0 || vertex[1] < 0){
00303 cout << "Invalid inputs for the centroid or vertex" << endl;
00304 }
00305
00306
00307 int cox = pixelwidth/2;
00308 int coy = pixelheight/2;
00309 int c1ex = pixelwidth;
00310 int c1ey = pixelheight/2;
00311 int c1x = c1ex - cox;
00312 int c1y = c1ey - coy;
00313
00314
00315
00316 double n1x = vertex[0] - centroid[0];
00317 double n1y = vertex[1] - centroid[1];
00318
00319
00320 double dot = c1x*n1x+c1y*n1y;
00321 double normc1 = sqrt( pow((double)c1x,2) + pow((double)c1y,2) );
00322 double normn1 = sqrt( pow((double)n1x,2) + pow((double)n1y,2) );
00323 double tpart = dot/( normc1 * normn1 );
00324 long double theta = acos(tpart);
00325
00326
00327 if (vertex[1] > centroid[1]){
00328 theta = (PI - theta) + PI;
00329 }
00330
00331 long double an3 = theta ;
00332 return an3;
00333 }
00334
00335
00336
00337 float VisualVector::TiltAngle1Func(long double RotAngle,int pixelheight, int pixelwidth, const int centzerotilt[], double runit,double hunit)
00338 {
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353 double Xdiff = centroid[0] - centzerotilt[0];
00354 double Ydiff = centroid[1] - centzerotilt[1];
00355
00356 double Yhyp = Ydiff / sin(RotAngle);
00357 double Yleg = Yhyp * cos(RotAngle);
00358
00359 double Y_Nframe = (Xdiff - Yleg) * sin(RotAngle);
00360 double Xhyp = Xdiff - Yleg;
00361 double Xleg = Xhyp * cos(RotAngle);
00362
00363 double X_Nframe = Yhyp + Xleg;
00364
00365
00366 if (sin(RotAngle) == 0){
00367 Y_Nframe = Ydiff;
00368 X_Nframe = Xdiff;
00369 }
00370
00371
00372 double intern1 = pow((pixelheight / 2 - centzerotilt[1]), 2.0);
00373 double intern2 = pow((pixelwidth / 2 - centzerotilt[0]), 2.0);
00374 double rpix = sqrt(intern1 + intern2);
00375
00376
00377 double hpix = (rpix / runit) * hunit;
00378 float phiy = atan(Y_Nframe / hpix);
00379 float an1 = phiy ;
00380 return an1;
00381 }
00382
00383 float VisualVector::TiltAngle2Func(long double RotAngle,int pixelheight, int pixelwidth, const int centzerotilt[], double runit, double hunit)
00384 {
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399 double Xdiff = centroid[0] - centzerotilt[0];
00400 double Ydiff = centroid[1] - centzerotilt[1];
00401
00402 double Yhyp = Ydiff / sin(RotAngle);
00403 double Yleg = Yhyp * cos(RotAngle);
00404
00405 double Y_Nframe = (Xdiff - Yleg) * sin(RotAngle);
00406 double Xhyp = Xdiff - Yleg;
00407 double Xleg = Xhyp * cos(RotAngle);
00408
00409 double X_Nframe = Yhyp + Xleg;
00410
00411
00412 if (sin(RotAngle) == 0){
00413 Y_Nframe = Ydiff;
00414 X_Nframe = Xdiff;
00415 }
00416
00417
00418 double intern1 = pow((pixelheight / 2 - centzerotilt[1]), 2.0);
00419 double intern2 = pow((pixelwidth / 2 - centzerotilt[0]), 2.0);
00420 double rpix = sqrt(intern1 + intern2);
00421
00422
00423 double hpix = (rpix / runit) * hunit;
00424 float phix = atan(X_Nframe/hpix);
00425 float an2 = phix ;
00426 return an2;
00427
00428 }
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472