int Classifier::getZone(IplImage* frame, double& confidence, FrameAnnotation& fa) { if (!leftEye || !rightEye || !nose) { string err = "Classifier::getZone. Location extractors malformed."; throw (err); } // the roi offset CvPoint offset; // LOIs CvPoint leftEyeLocation; CvPoint rightEyeLocation; CvPoint noseLocation; // computing the confidence of the location identification double leftPSR; double rightPSR; double nosePSR; CvPoint center = fa.getLOI(Annotations::Face); if (!center.x || !center.y) { center.x = Globals::imgWidth / 2; center.y = Globals::imgHeight / 2; fa.setFace(center); } offset.x = offset.y = 0; IplImage* roi = (roiFunction)? roiFunction(frame, fa, offset, Annotations::Face) : 0; // all location extractors do identical preprocessing. Therefore, preprocess // once using say the left eye extractor and re-use it for all three extractors fftw_complex* preprocessedImage = leftEye->getPreprocessedImage((roi)? roi : frame); #pragma omp parallel sections num_threads(2) { #pragma omp section { leftEye->setImage(preprocessedImage); leftEye->apply(); leftEye->getMaxLocation(leftEyeLocation, leftPSR); leftEyeLocation.x += offset.x; leftEyeLocation.y += offset.y; } #pragma omp section { // get the location of the right eye rightEye->setImage(preprocessedImage); rightEye->apply(); rightEye->getMaxLocation(rightEyeLocation, rightPSR); rightEyeLocation.x += offset.x; rightEyeLocation.y += offset.y; } } if (roi) cvReleaseImage(&roi); center.x = (leftEyeLocation.x + rightEyeLocation.x) / 2; center.y = leftEyeLocation.y + Globals::noseDrop; fa.setNose(center); offset.x = offset.y = 0; roi = (roiFunction)? roiFunction(frame, fa, offset, Annotations::Nose) : 0; // free the preprocessed image fftw_free(preprocessedImage); // all location extractors do identical preprocessing. Therefore, preprocess // once using say the left eye extractor and re-use it for all three extractors preprocessedImage = nose->getPreprocessedImage((roi)? roi : frame); // get the location of the nose nose->setImage(preprocessedImage); nose->apply(); nose->getMaxLocation(noseLocation, nosePSR); noseLocation.x += offset.x; noseLocation.y += offset.y; // free the preprocessed image fftw_free(preprocessedImage); fa.setLeftIris(leftEyeLocation); fa.setRightIris(rightEyeLocation); fa.setNose(noseLocation); // we are done with the images at this point. Free roi if not zero if (roi) cvReleaseImage(&roi); // cout << "Confidence (L, R, N) = (" << leftPSR << ", " << // rightPSR << ")" << endl; // extract features vector vector<double> data; for (int i = 0; i < nFeatures; i++) { double value = featureExtractors[i]->extract(&fa); data.push_back(value); } // normalize normalize(data); // create SVM Light objects to classify DOC* doc; WORD* words = (WORD*)malloc(sizeof(WORD) * (nFeatures + 1)); for (int i = 0; i < nFeatures; i++) { words[i].wnum = featureExtractors[i]->getId(); words[i].weight = data[i]; } // SVM Light expects that the features vector has a zero element // to indicate termination and hence words[nFeatures].wnum = 0; words[nFeatures].weight = 0.0; // create doc string comment = "Gaze SVM"; doc = create_example(-1, 0, 0, 0.0, create_svector(words, (char*)comment.c_str(), 1.0)); int maxIndex = 0; confidence = -FLT_MAX; double dists[Globals::numZones]; // classify using each zone model #pragma omp parallel for num_threads(Globals::numZones) for (unsigned int i = 0; i < Globals::numZones; i++) { if (kernelType == Trainer::Linear) dists[i] = classify_example_linear(models[i], doc); else dists[i] = classify_example(models[i], doc); } for (unsigned int i = 0; i < Globals::numZones; i++) { if (confidence < dists[i]) { confidence = dists[i]; maxIndex = i + 1; } } free_example(doc, 1); free(words); return maxIndex; }
int main(int argc, char** argv) { string modelsFileName = ""; string imageFileName = ""; string imageDirectory = ""; int x = Globals::imgWidth / 2; int y = Globals::imgHeight / 2; for (int i = 1; i < argc; i++) { if (!strcmp(argv[i], "-i")) imageFileName = argv[i + 1]; else if (!strcmp(argv[i], "-d")) imageDirectory = argv[i + 1]; else if (!strcmp(argv[i], "-m")) modelsFileName = argv[i + 1]; else if (!strcmp(argv[i], "-c")) { char* str = argv[i + 1]; char* token = strtok(str, "(),"); if (token) x = atoi(token); token = strtok(NULL, "(),"); if (token) y = atoi(token); } else if (!strcmp(argv[i], "-h")) { cout << "Usage: classify -i <imageFileName> -m <modelsFileName>" << endl; return 0; } } if (modelsFileName == "") { cout << "Usage: classify -i <imageFileName> -m <modelsFileName>" << endl; return -1; } CvPoint center; center.x = x; center.y = y; CvSize size; size.width = Globals::roiWidth; size.height = Globals::roiHeight; double scale = 0.3; try { loadModel(modelsFileName); if (imageFileName != "") { Preprocess preprocess(size, scale, center, roiFunction); IplImage* image = cvLoadImage(imageFileName.c_str()); IplImage* imageVector = preprocess.generateImageVector(image); cout << "Sector " << classify(imageVector) << endl; cvReleaseImage(&image); cvReleaseImage(&imageVector); } else if (imageDirectory != "") { int counts[5][6]; for (int i = 0; i < 5; i++) for (int j = 0; j < 6; j++) counts[i][j] = 0; string annotationsFileName = imageDirectory + "/annotations.xml"; Annotations annotations; annotations.readAnnotations(annotationsFileName); CvPoint& center = annotations.getCenter(); Preprocess preprocess(size, scale, center, roiFunction); vector<FrameAnnotation*>& frameAnnotations = annotations.getFrameAnnotations(); for (unsigned int i = 0; i < frameAnnotations.size(); i++) { FrameAnnotation* fa = frameAnnotations[i]; fa->setFace(center); int expectedZone = fa->getSector(); counts[expectedZone - 1][5]++; // compose filename and update map char buffer[256]; sprintf(buffer, "frame_%d.png", fa->getFrameNumber()); string simpleName = buffer; string fileName = imageDirectory + "/" + simpleName; IplImage* image = cvLoadImage(fileName.c_str()); IplImage* imageVector = preprocess.generateImageVector(image); int zone = classify(imageVector); if (expectedZone == zone) counts[zone - 1][zone - 1]++; else counts[expectedZone - 1][zone - 1]++; cvReleaseImage(&image); cvReleaseImage(&imageVector); } cout << "Errors by class" << endl; for (int i = 0; i < 5; i++) { for (int j = 0; j < 6; j++) cout << counts[i][j] << "\t"; cout << endl; } } } catch (string err) { cout << err << endl; } return 0; }