5 * Created by Victor Eruhimov on 3/23/10.
6 * Copyright 2010 Argus Corp. All rights reserved.
10 #include "precomp.hpp"
11 #include "opencv2/opencv_modules.hpp"
12 #ifdef HAVE_OPENCV_HIGHGUI
13 # include "opencv2/highgui.hpp"
19 inline int round(float value)
23 return int(value + 0.5f);
27 return int(value - 0.5f);
31 inline CvRect resize_rect(CvRect rect, float alpha)
33 return cvRect(rect.x + round((float)(0.5*(1 - alpha)*rect.width)), rect.y + round((float)(0.5*(1 - alpha)*rect.height)),
34 round(rect.width*alpha), round(rect.height*alpha));
37 CvMat* ConvertImageToMatrix(IplImage* patch);
44 m_rotation = cvCreateMat(1, 3, CV_32FC1);
45 m_translation = cvCreateMat(1, 3, CV_32FC1);
50 cvReleaseMat(&m_rotation);
51 cvReleaseMat(&m_translation);
54 void SetPose(CvMat* rotation, CvMat* translation)
56 cvCopy(rotation, m_rotation);
57 cvCopy(translation, m_translation);
60 CvMat* GetRotation() {return m_rotation;}
61 CvMat* GetTranslation() {return m_translation;}
68 // AffineTransformPatch: generates an affine transformed image patch.
69 // - src: source image (roi is supported)
70 // - dst: output image. ROI of dst image should be 2 times smaller than ROI of src.
71 // - pose: parameters of an affine transformation
72 void AffineTransformPatch(IplImage* src, IplImage* dst, CvAffinePose pose);
74 // GenerateAffineTransformFromPose: generates an affine transformation matrix from CvAffinePose instance
75 // - size: the size of image patch
76 // - pose: affine transformation
77 // - transform: 2x3 transformation matrix
78 void GenerateAffineTransformFromPose(CvSize size, CvAffinePose pose, CvMat* transform);
80 // Generates a random affine pose
81 CvAffinePose GenRandomAffinePose();
84 const static int num_mean_components = 500;
85 const static float noise_intensity = 0.15f;
88 static inline CvPoint rect_center(CvRect rect)
90 return cvPoint(rect.x + rect.width/2, rect.y + rect.height/2);
93 // static void homography_transform(IplImage* frontal, IplImage* result, CvMat* homography)
95 // cvWarpPerspective(frontal, result, homography);
98 static CvAffinePose perturbate_pose(CvAffinePose pose, float noise)
100 // perturbate the matrix
101 float noise_mult_factor = 1 + (0.5f - float(rand())/RAND_MAX)*noise;
102 float noise_add_factor = noise_mult_factor - 1;
104 CvAffinePose pose_pert = pose;
105 pose_pert.phi += noise_add_factor;
106 pose_pert.theta += noise_mult_factor;
107 pose_pert.lambda1 *= noise_mult_factor;
108 pose_pert.lambda2 *= noise_mult_factor;
113 static void generate_mean_patch(IplImage* frontal, IplImage* result, CvAffinePose pose, int pose_count, float noise)
115 IplImage* sum = cvCreateImage(cvSize(result->width, result->height), IPL_DEPTH_32F, 1);
116 IplImage* workspace = cvCloneImage(result);
117 IplImage* workspace_float = cvCloneImage(sum);
120 for(int i = 0; i < pose_count; i++)
122 CvAffinePose pose_pert = perturbate_pose(pose, noise);
124 AffineTransformPatch(frontal, workspace, pose_pert);
125 cvConvertScale(workspace, workspace_float);
126 cvAdd(sum, workspace_float, sum);
129 cvConvertScale(sum, result, 1.0f/pose_count);
131 cvReleaseImage(&workspace);
132 cvReleaseImage(&sum);
133 cvReleaseImage(&workspace_float);
136 // static void generate_mean_patch_fast(IplImage* /*frontal*/, IplImage* /*result*/, CvAffinePose /*pose*/,
137 // CvMat* /*pca_hr_avg*/, CvMat* /*pca_hr_eigenvectors*/, const OneWayDescriptor* /*pca_descriptors*/)
139 // /*for(int i = 0; i < pca_hr_eigenvectors->cols; i++)
145 void readPCAFeatures(const char *filename, CvMat** avg, CvMat** eigenvectors, const char *postfix = "");
146 void readPCAFeatures(const FileNode &fn, CvMat** avg, CvMat** eigenvectors, const char* postfix = "");
147 void savePCAFeatures(FileStorage &fs, const char* postfix, CvMat* avg, CvMat* eigenvectors);
148 void calcPCAFeatures(std::vector<IplImage*>& patches, FileStorage &fs, const char* postfix, CvMat** avg,
149 CvMat** eigenvectors);
150 void loadPCAFeatures(const char* path, const char* images_list, std::vector<IplImage*>& patches, CvSize patch_size);
151 void generatePCAFeatures(const char* path, const char* img_filename, FileStorage& fs, const char* postfix,
152 CvSize patch_size, CvMat** avg, CvMat** eigenvectors);
154 void eigenvector2image(CvMat* eigenvector, IplImage* img);
156 void FindOneWayDescriptor(int desc_count, const OneWayDescriptor* descriptors, IplImage* patch, int& desc_idx, int& pose_idx, float& distance,
157 CvMat* avg = 0, CvMat* eigenvalues = 0);
159 void FindOneWayDescriptor(int desc_count, const OneWayDescriptor* descriptors, IplImage* patch, int n,
160 std::vector<int>& desc_idxs, std::vector<int>& pose_idxs, std::vector<float>& distances,
161 CvMat* avg = 0, CvMat* eigenvalues = 0);
163 void FindOneWayDescriptor(cv::flann::Index* m_pca_descriptors_tree, CvSize patch_size, int m_pca_dim_low, int m_pose_count, IplImage* patch, int& desc_idx, int& pose_idx, float& distance,
164 CvMat* avg = 0, CvMat* eigenvalues = 0);
166 void FindOneWayDescriptorEx(int desc_count, const OneWayDescriptor* descriptors, IplImage* patch,
167 float scale_min, float scale_max, float scale_step,
168 int& desc_idx, int& pose_idx, float& distance, float& scale,
169 CvMat* avg, CvMat* eigenvectors);
171 void FindOneWayDescriptorEx(int desc_count, const OneWayDescriptor* descriptors, IplImage* patch,
172 float scale_min, float scale_max, float scale_step,
173 int n, std::vector<int>& desc_idxs, std::vector<int>& pose_idxs,
174 std::vector<float>& distances, std::vector<float>& scales,
175 CvMat* avg, CvMat* eigenvectors);
177 void FindOneWayDescriptorEx(cv::flann::Index* m_pca_descriptors_tree, CvSize patch_size, int m_pca_dim_low, int m_pose_count, IplImage* patch,
178 float scale_min, float scale_max, float scale_step,
179 int& desc_idx, int& pose_idx, float& distance, float& scale,
180 CvMat* avg, CvMat* eigenvectors);
182 inline CvRect fit_rect_roi_fixedsize(CvRect rect, CvRect roi)
185 fit.x = MAX(fit.x, roi.x);
186 fit.y = MAX(fit.y, roi.y);
187 fit.x = MIN(fit.x, roi.x + roi.width - fit.width - 1);
188 fit.y = MIN(fit.y, roi.y + roi.height - fit.height - 1);
192 inline CvRect fit_rect_fixedsize(CvRect rect, IplImage* img)
194 CvRect roi = cvGetImageROI(img);
195 return fit_rect_roi_fixedsize(rect, roi);
198 OneWayDescriptor::OneWayDescriptor()
208 m_pca_dim_high = 100;
211 OneWayDescriptor::~OneWayDescriptor()
215 for(int i = 0; i < m_pose_count; i++)
217 cvReleaseImage(&m_samples[i]);
218 cvReleaseMat(&m_pca_coeffs[i]);
220 cvReleaseImage(&m_input_patch);
221 cvReleaseImage(&m_train_patch);
223 delete []m_pca_coeffs;
227 delete []m_affine_poses;
232 void OneWayDescriptor::Allocate(int pose_count, CvSize size, int nChannels)
234 m_pose_count = pose_count;
235 m_samples = new IplImage* [m_pose_count];
236 m_pca_coeffs = new CvMat* [m_pose_count];
237 m_patch_size = cvSize(size.width/2, size.height/2);
241 m_affine_poses = new CvAffinePose[m_pose_count];
244 int length = m_pca_dim_low;//roi.width*roi.height;
245 for(int i = 0; i < m_pose_count; i++)
247 m_samples[i] = cvCreateImage(cvSize(size.width/2, size.height/2), IPL_DEPTH_32F, nChannels);
248 m_pca_coeffs[i] = cvCreateMat(1, length, CV_32FC1);
251 m_input_patch = cvCreateImage(GetPatchSize(), IPL_DEPTH_8U, 1);
252 m_train_patch = cvCreateImage(GetInputPatchSize(), IPL_DEPTH_8U, 1);
255 // static void cvmSet2DPoint(CvMat* matrix, int row, int col, CvPoint2D32f point)
257 // cvmSet(matrix, row, col, point.x);
258 // cvmSet(matrix, row, col + 1, point.y);
261 // static void cvmSet3DPoint(CvMat* matrix, int row, int col, CvPoint3D32f point)
263 // cvmSet(matrix, row, col, point.x);
264 // cvmSet(matrix, row, col + 1, point.y);
265 // cvmSet(matrix, row, col + 2, point.z);
268 CvAffinePose GenRandomAffinePose()
270 const float scale_min = 0.8f;
271 const float scale_max = 1.2f;
273 pose.theta = float(rand())/RAND_MAX*120 - 60;
274 pose.phi = float(rand())/RAND_MAX*360;
275 pose.lambda1 = scale_min + float(rand())/RAND_MAX*(scale_max - scale_min);
276 pose.lambda2 = scale_min + float(rand())/RAND_MAX*(scale_max - scale_min);
281 void GenerateAffineTransformFromPose(CvSize size, CvAffinePose pose, CvMat* transform)
283 CvMat* temp = cvCreateMat(3, 3, CV_32FC1);
284 CvMat* final = cvCreateMat(3, 3, CV_32FC1);
285 cvmSet(temp, 2, 0, 0.0f);
286 cvmSet(temp, 2, 1, 0.0f);
287 cvmSet(temp, 2, 2, 1.0f);
290 cvGetSubRect(temp, &rotation, cvRect(0, 0, 3, 2));
292 cv2DRotationMatrix(cvPoint2D32f(size.width/2, size.height/2), pose.phi, 1.0, &rotation);
295 cvmSet(temp, 0, 0, pose.lambda1);
296 cvmSet(temp, 0, 1, 0.0f);
297 cvmSet(temp, 1, 0, 0.0f);
298 cvmSet(temp, 1, 1, pose.lambda2);
299 cvmSet(temp, 0, 2, size.width/2*(1 - pose.lambda1));
300 cvmSet(temp, 1, 2, size.height/2*(1 - pose.lambda2));
301 cvMatMul(temp, final, final);
303 cv2DRotationMatrix(cvPoint2D32f(size.width/2, size.height/2), pose.theta - pose.phi, 1.0, &rotation);
304 cvMatMul(temp, final, final);
306 cvGetSubRect(final, &rotation, cvRect(0, 0, 3, 2));
307 cvCopy(&rotation, transform);
310 cvReleaseMat(&final);
313 void AffineTransformPatch(IplImage* src, IplImage* dst, CvAffinePose pose)
315 CvRect src_large_roi = cvGetImageROI(src);
317 IplImage* temp = cvCreateImage(cvSize(src_large_roi.width, src_large_roi.height), IPL_DEPTH_32F, src->nChannels);
319 IplImage* temp2 = cvCloneImage(temp);
320 CvMat* rotation_phi = cvCreateMat(2, 3, CV_32FC1);
322 CvSize new_size = cvSize(cvRound(temp->width*pose.lambda1), cvRound(temp->height*pose.lambda2));
323 IplImage* temp3 = cvCreateImage(new_size, IPL_DEPTH_32F, src->nChannels);
325 cvConvertScale(src, temp);
326 cvResetImageROI(temp);
329 cv2DRotationMatrix(cvPoint2D32f(temp->width/2, temp->height/2), pose.phi, 1.0, rotation_phi);
330 cvWarpAffine(temp, temp2, rotation_phi);
334 cvResize(temp2, temp3);
336 cv2DRotationMatrix(cvPoint2D32f(temp3->width/2, temp3->height/2), pose.theta - pose.phi, 1.0, rotation_phi);
337 cvWarpAffine(temp3, temp, rotation_phi);
339 cvSetImageROI(temp, cvRect(temp->width/2 - src_large_roi.width/4, temp->height/2 - src_large_roi.height/4,
340 src_large_roi.width/2, src_large_roi.height/2));
341 cvConvertScale(temp, dst);
342 cvReleaseMat(&rotation_phi);
344 cvReleaseImage(&temp3);
345 cvReleaseImage(&temp2);
346 cvReleaseImage(&temp);
349 void OneWayDescriptor::GenerateSamples(int pose_count, IplImage* frontal, int norm)
353 GenerateSamplesWithTransforms(pose_count, frontal);
357 CvRect roi = cvGetImageROI(frontal);
358 IplImage* patch_8u = cvCreateImage(cvSize(roi.width/2, roi.height/2), frontal->depth, frontal->nChannels);
359 for(int i = 0; i < pose_count; i++)
363 m_affine_poses[i] = GenRandomAffinePose();
365 //AffineTransformPatch(frontal, patch_8u, m_affine_poses[i]);
366 generate_mean_patch(frontal, patch_8u, m_affine_poses[i], num_mean_components, noise_intensity);
371 double sum = cvSum(patch_8u).val[0];
374 cvConvertScale(patch_8u, m_samples[i], scale);
378 cvMinMaxLoc(m_samples[i], 0, &maxval);
379 IplImage* test = cvCreateImage(cvSize(roi.width/2, roi.height/2), IPL_DEPTH_8U, 1);
380 cvConvertScale(m_samples[i], test, 255.0/maxval);
381 cvNamedWindow("1", 1);
382 cvShowImage("1", test);
386 cvReleaseImage(&patch_8u);
389 void OneWayDescriptor::GenerateSamplesFast(IplImage* frontal, CvMat* pca_hr_avg,
390 CvMat* pca_hr_eigenvectors, OneWayDescriptor* pca_descriptors)
392 CvRect roi = cvGetImageROI(frontal);
393 if(roi.width != GetInputPatchSize().width || roi.height != GetInputPatchSize().height)
395 cvResize(frontal, m_train_patch);
396 frontal = m_train_patch;
399 CvMat* pca_coeffs = cvCreateMat(1, pca_hr_eigenvectors->cols, CV_32FC1);
401 cvMinMaxLoc(frontal, 0, &maxval);
402 CvMat* frontal_data = ConvertImageToMatrix(frontal);
404 double sum = cvSum(frontal_data).val[0];
405 cvConvertScale(frontal_data, frontal_data, 1.0f/sum);
406 cvProjectPCA(frontal_data, pca_hr_avg, pca_hr_eigenvectors, pca_coeffs);
407 for(int i = 0; i < m_pose_count; i++)
409 cvSetZero(m_samples[i]);
410 for(int j = 0; j < m_pca_dim_high; j++)
412 double coeff = cvmGet(pca_coeffs, 0, j);
413 IplImage* patch = pca_descriptors[j + 1].GetPatch(i);
414 cvAddWeighted(m_samples[i], 1.0, patch, coeff, 0, m_samples[i]);
417 printf("coeff%d = %f\n", j, coeff);
418 IplImage* test = cvCreateImage(cvSize(12, 12), IPL_DEPTH_8U, 1);
420 cvMinMaxLoc(patch, 0, &maxval);
421 cvConvertScale(patch, test, 255.0/maxval);
422 cvNamedWindow("1", 1);
423 cvShowImage("1", test);
428 cvAdd(pca_descriptors[0].GetPatch(i), m_samples[i], m_samples[i]);
429 double sm = cvSum(m_samples[i]).val[0];
430 cvConvertScale(m_samples[i], m_samples[i], 1.0/sm);
433 IplImage* test = cvCreateImage(cvSize(12, 12), IPL_DEPTH_8U, 1);
434 /* IplImage* temp1 = cvCreateImage(cvSize(12, 12), IPL_DEPTH_32F, 1);
435 eigenvector2image(pca_hr_avg, temp1);
436 IplImage* test = cvCreateImage(cvSize(12, 12), IPL_DEPTH_8U, 1);
437 cvAdd(m_samples[i], temp1, temp1);
438 cvMinMaxLoc(temp1, 0, &maxval);
439 cvConvertScale(temp1, test, 255.0/maxval);*/
440 cvMinMaxLoc(m_samples[i], 0, &maxval);
441 cvConvertScale(m_samples[i], test, 255.0/maxval);
443 cvNamedWindow("1", 1);
444 cvShowImage("1", frontal);
445 cvNamedWindow("2", 1);
446 cvShowImage("2", test);
451 cvReleaseMat(&pca_coeffs);
452 cvReleaseMat(&frontal_data);
455 void OneWayDescriptor::SetTransforms(CvAffinePose* poses, CvMat** transforms)
459 delete []m_affine_poses;
462 m_affine_poses = poses;
463 m_transforms = transforms;
466 void OneWayDescriptor::Initialize(int pose_count, IplImage* frontal, const char* feature_name, int norm)
468 m_feature_name = String(feature_name);
469 CvRect roi = cvGetImageROI(frontal);
470 m_center = rect_center(roi);
472 Allocate(pose_count, cvSize(roi.width, roi.height), frontal->nChannels);
474 GenerateSamples(pose_count, frontal, norm);
477 void OneWayDescriptor::InitializeFast(int pose_count, IplImage* frontal, const char* feature_name,
478 CvMat* pca_hr_avg, CvMat* pca_hr_eigenvectors, OneWayDescriptor* pca_descriptors)
482 Initialize(pose_count, frontal, feature_name, 1);
485 m_feature_name = String(feature_name);
486 CvRect roi = cvGetImageROI(frontal);
487 m_center = rect_center(roi);
489 Allocate(pose_count, cvSize(roi.width, roi.height), frontal->nChannels);
491 GenerateSamplesFast(frontal, pca_hr_avg, pca_hr_eigenvectors, pca_descriptors);
494 void OneWayDescriptor::InitializePCACoeffs(CvMat* avg, CvMat* eigenvectors)
496 for(int i = 0; i < m_pose_count; i++)
498 ProjectPCASample(m_samples[i], avg, eigenvectors, m_pca_coeffs[i]);
502 void OneWayDescriptor::ProjectPCASample(IplImage* patch, CvMat* avg, CvMat* eigenvectors, CvMat* pca_coeffs) const
504 CvMat* patch_mat = ConvertImageToMatrix(patch);
505 // CvMat eigenvectorsr;
506 // cvGetSubRect(eigenvectors, &eigenvectorsr, cvRect(0, 0, eigenvectors->cols, pca_coeffs->cols));
507 CvMat* temp = cvCreateMat(1, eigenvectors->cols, CV_32FC1);
508 cvProjectPCA(patch_mat, avg, eigenvectors, temp);
510 cvGetSubRect(temp, &temp1, cvRect(0, 0, pca_coeffs->cols, 1));
511 cvCopy(&temp1, pca_coeffs);
514 cvReleaseMat(&patch_mat);
517 void OneWayDescriptor::EstimatePosePCA(CvArr* patch, int& pose_idx, float& distance, CvMat* avg, CvMat* eigenvectors) const
522 if (!CV_IS_MAT(patch))
524 EstimatePose((IplImage*)patch, pose_idx, distance);
533 if (!CV_IS_MAT(patch))
535 roi = cvGetImageROI((IplImage*)patch);
536 if(roi.width != GetPatchSize().width || roi.height != GetPatchSize().height)
538 cvResize(patch, m_input_patch);
539 patch = m_input_patch;
540 roi = cvGetImageROI((IplImage*)patch);
544 CvMat* pca_coeffs = cvCreateMat(1, m_pca_dim_low, CV_32FC1);
546 if (CV_IS_MAT(patch))
548 cvCopy((CvMat*)patch, pca_coeffs);
552 IplImage* patch_32f = cvCreateImage(cvSize(roi.width, roi.height), IPL_DEPTH_32F, 1);
553 double sum = cvSum(patch).val[0];
554 cvConvertScale(patch, patch_32f, 1.0f/sum);
555 ProjectPCASample(patch_32f, avg, eigenvectors, pca_coeffs);
556 cvReleaseImage(&patch_32f);
563 for(int i = 0; i < m_pose_count; i++)
565 double dist = cvNorm(m_pca_coeffs[i], pca_coeffs);
567 // float data1, data2;
568 // //CvMat* pose_pca_coeffs = m_pca_coeffs[i];
569 // for (int x=0; x < pca_coeffs->width; x++)
570 // for (int y =0 ; y < pca_coeffs->height; y++)
572 // data1 = ((float*)(pca_coeffs->data.ptr + pca_coeffs->step*x))[y];
573 // data2 = ((float*)(m_pca_coeffs[i]->data.ptr + m_pca_coeffs[i]->step*x))[y];
574 // dist+=(data1-data2)*(data1-data2);
577 // for (int j = 0; j < m_pca_dim_low; j++)
579 // dist += (pose_pca_coeffs->data.fl[j]- pca_coeffs->data.fl[j])*(pose_pca_coeffs->data.fl[j]- pca_coeffs->data.fl[j]);
582 // for (int j = 0; j <= m_pca_dim_low - 4; j += 4)
584 // dist += (pose_pca_coeffs->data.fl[j]- pca_coeffs->data.fl[j])*
585 // (pose_pca_coeffs->data.fl[j]- pca_coeffs->data.fl[j]);
586 // dist += (pose_pca_coeffs->data.fl[j+1]- pca_coeffs->data.fl[j+1])*
587 // (pose_pca_coeffs->data.fl[j+1]- pca_coeffs->data.fl[j+1]);
588 // dist += (pose_pca_coeffs->data.fl[j+2]- pca_coeffs->data.fl[j+2])*
589 // (pose_pca_coeffs->data.fl[j+2]- pca_coeffs->data.fl[j+2]);
590 // dist += (pose_pca_coeffs->data.fl[j+3]- pca_coeffs->data.fl[j+3])*
591 // (pose_pca_coeffs->data.fl[j+3]- pca_coeffs->data.fl[j+3]);
596 distance = (float)dist;
601 cvReleaseMat(&pca_coeffs);
604 void OneWayDescriptor::EstimatePose(IplImage* patch, int& pose_idx, float& distance) const
609 CvRect roi = cvGetImageROI(patch);
610 IplImage* patch_32f = cvCreateImage(cvSize(roi.width, roi.height), IPL_DEPTH_32F, patch->nChannels);
611 double sum = cvSum(patch).val[0];
612 cvConvertScale(patch, patch_32f, 1/sum);
614 for(int i = 0; i < m_pose_count; i++)
616 if(m_samples[i]->width != patch_32f->width || m_samples[i]->height != patch_32f->height)
620 double dist = cvNorm(m_samples[i], patch_32f);
624 //for (int y = 0; y<patch_32f->height; y++)
625 // for (int x = 0; x< patch_32f->width; x++)
627 // i1 = ((float*)(m_samples[i]->imageData + m_samples[i]->widthStep*y))[x];
628 // i2 = ((float*)(patch_32f->imageData + patch_32f->widthStep*y))[x];
629 // dist+= (i1-i2)*(i1-i2);
634 distance = (float)dist;
639 IplImage* img1 = cvCreateImage(cvSize(roi.width, roi.height), IPL_DEPTH_8U, 1);
640 IplImage* img2 = cvCreateImage(cvSize(roi.width, roi.height), IPL_DEPTH_8U, 1);
642 cvMinMaxLoc(m_samples[i], 0, &maxval);
643 cvConvertScale(m_samples[i], img1, 255.0/maxval);
644 cvMinMaxLoc(patch_32f, 0, &maxval);
645 cvConvertScale(patch_32f, img2, 255.0/maxval);
647 cvNamedWindow("1", 1);
648 cvShowImage("1", img1);
649 cvNamedWindow("2", 1);
650 cvShowImage("2", img2);
651 printf("Distance = %f\n", dist);
656 cvReleaseImage(&patch_32f);
659 void OneWayDescriptor::Save(const char* path)
661 for(int i = 0; i < m_pose_count; i++)
664 sprintf(buf, "%s/patch_%04d.png", path, i);
665 IplImage* patch = cvCreateImage(cvSize(m_samples[i]->width, m_samples[i]->height), IPL_DEPTH_8U, m_samples[i]->nChannels);
668 cvMinMaxLoc(m_samples[i], 0, &maxval);
669 cvConvertScale(m_samples[i], patch, 255/maxval);
671 #ifdef HAVE_OPENCV_HIGHGUI
672 cv::imwrite(buf, cv::cvarrToMat(patch));
674 CV_Error(CV_StsNotImplemented, "OpenCV has been compiled without image I/O support");
677 cvReleaseImage(&patch);
681 void OneWayDescriptor::Write(CvFileStorage* fs, const char* name)
683 CvMat* mat = cvCreateMat(m_pose_count, m_samples[0]->width*m_samples[0]->height, CV_32FC1);
685 // prepare data to write as a single matrix
686 for(int i = 0; i < m_pose_count; i++)
688 for(int y = 0; y < m_samples[i]->height; y++)
690 for(int x = 0; x < m_samples[i]->width; x++)
692 float val = *((float*)(m_samples[i]->imageData + m_samples[i]->widthStep*y) + x);
693 cvmSet(mat, i, y*m_samples[i]->width + x, val);
698 cvWrite(fs, name, mat);
703 int OneWayDescriptor::ReadByName(const FileNode &parent, const char* name)
705 CvMat* mat = reinterpret_cast<CvMat*> (parent[name].readObj ());
712 for(int i = 0; i < m_pose_count; i++)
714 for(int y = 0; y < m_samples[i]->height; y++)
716 for(int x = 0; x < m_samples[i]->width; x++)
718 float val = (float)cvmGet(mat, i, y*m_samples[i]->width + x);
719 *((float*)(m_samples[i]->imageData + y*m_samples[i]->widthStep) + x) = val;
728 int OneWayDescriptor::ReadByName(CvFileStorage* fs, CvFileNode* parent, const char* name)
730 return ReadByName (FileNode (fs, parent), name);
733 IplImage* OneWayDescriptor::GetPatch(int index)
735 return m_samples[index];
738 CvAffinePose OneWayDescriptor::GetPose(int index) const
740 return m_affine_poses[index];
743 void FindOneWayDescriptor(int desc_count, const OneWayDescriptor* descriptors, IplImage* patch, int& desc_idx, int& pose_idx, float& distance,
744 CvMat* avg, CvMat* eigenvectors)
750 //PCA_coeffs precalculating
751 int m_pca_dim_low = descriptors[0].GetPCADimLow();
752 CvMat* pca_coeffs = cvCreateMat(1, m_pca_dim_low, CV_32FC1);
753 int patch_width = descriptors[0].GetPatchSize().width;
754 int patch_height = descriptors[0].GetPatchSize().height;
757 CvRect _roi = cvGetImageROI((IplImage*)patch);
758 IplImage* test_img = cvCreateImage(cvSize(patch_width,patch_height), IPL_DEPTH_8U, 1);
759 if(_roi.width != patch_width|| _roi.height != patch_height)
762 cvResize(patch, test_img);
763 _roi = cvGetImageROI(test_img);
767 cvCopy(patch,test_img);
769 IplImage* patch_32f = cvCreateImage(cvSize(_roi.width, _roi.height), IPL_DEPTH_32F, 1);
770 double sum = cvSum(test_img).val[0];
771 cvConvertScale(test_img, patch_32f, 1.0f/sum);
773 //ProjectPCASample(patch_32f, avg, eigenvectors, pca_coeffs);
775 CvMat* patch_mat = ConvertImageToMatrix(patch_32f);
776 CvMat* temp = cvCreateMat(1, eigenvectors->cols, CV_32FC1);
777 cvProjectPCA(patch_mat, avg, eigenvectors, temp);
779 cvGetSubRect(temp, &temp1, cvRect(0, 0, pca_coeffs->cols, 1));
780 cvCopy(&temp1, pca_coeffs);
782 cvReleaseMat(&patch_mat);
785 cvReleaseImage(&patch_32f);
786 cvReleaseImage(&test_img);
793 for(int i = 0; i < desc_count; i++)
799 descriptors[i].EstimatePose(patch, _pose_idx, _distance);
803 descriptors[i].EstimatePosePCA(patch, _pose_idx, _distance, avg, eigenvectors);
807 descriptors[i].EstimatePosePCA(pca_coeffs, _pose_idx, _distance, avg, eigenvectors);
811 if(_distance < distance)
814 pose_idx = _pose_idx;
815 distance = _distance;
818 cvReleaseMat(&pca_coeffs);
823 void FindOneWayDescriptor(cv::flann::Index* m_pca_descriptors_tree, CvSize patch_size, int m_pca_dim_low, int m_pose_count, IplImage* patch, int& desc_idx, int& pose_idx, float& distance,
824 CvMat* avg, CvMat* eigenvectors)
830 //PCA_coeffs precalculating
831 CvMat* pca_coeffs = cvCreateMat(1, m_pca_dim_low, CV_32FC1);
832 int patch_width = patch_size.width;
833 int patch_height = patch_size.height;
836 CvRect _roi = cvGetImageROI((IplImage*)patch);
837 IplImage* test_img = cvCreateImage(cvSize(patch_width,patch_height), IPL_DEPTH_8U, 1);
838 if(_roi.width != patch_width|| _roi.height != patch_height)
841 cvResize(patch, test_img);
842 _roi = cvGetImageROI(test_img);
846 cvCopy(patch,test_img);
848 IplImage* patch_32f = cvCreateImage(cvSize(_roi.width, _roi.height), IPL_DEPTH_32F, 1);
849 float sum = cvSum(test_img).val[0];
850 cvConvertScale(test_img, patch_32f, 1.0f/sum);
852 //ProjectPCASample(patch_32f, avg, eigenvectors, pca_coeffs);
854 CvMat* patch_mat = ConvertImageToMatrix(patch_32f);
855 CvMat* temp = cvCreateMat(1, eigenvectors->cols, CV_32FC1);
856 cvProjectPCA(patch_mat, avg, eigenvectors, temp);
858 cvGetSubRect(temp, &temp1, cvRect(0, 0, pca_coeffs->cols, 1));
859 cvCopy(&temp1, pca_coeffs);
861 cvReleaseMat(&patch_mat);
864 cvReleaseImage(&patch_32f);
865 cvReleaseImage(&test_img);
870 //float* target = new float[m_pca_dim_low];
871 //::cvflann::KNNResultSet res(1,pca_coeffs->data.fl,m_pca_dim_low);
872 //::cvflann::SearchParams params;
873 //params.checks = -1;
875 //int maxDepth = 1000000;
876 //int neighbors_count = 1;
877 //int* neighborsIdx = new int[neighbors_count];
878 //float* distances = new float[neighbors_count];
879 //if (m_pca_descriptors_tree->findNearest(pca_coeffs->data.fl,neighbors_count,maxDepth,neighborsIdx,0,distances) > 0)
881 // desc_idx = neighborsIdx[0] / m_pose_count;
882 // pose_idx = neighborsIdx[0] % m_pose_count;
883 // distance = distances[0];
885 //delete[] neighborsIdx;
886 //delete[] distances;
888 cv::Mat m_object(1, m_pca_dim_low, CV_32F);
889 cv::Mat m_indices(1, 1, CV_32S);
890 cv::Mat m_dists(1, 1, CV_32F);
892 float* object_ptr = m_object.ptr<float>(0);
893 for (int i=0;i<m_pca_dim_low;i++)
895 object_ptr[i] = pca_coeffs->data.fl[i];
898 m_pca_descriptors_tree->knnSearch(m_object, m_indices, m_dists, 1, cv::flann::SearchParams(-1) );
900 desc_idx = ((int*)(m_indices.ptr<int>(0)))[0] / m_pose_count;
901 pose_idx = ((int*)(m_indices.ptr<int>(0)))[0] % m_pose_count;
902 distance = ((float*)(m_dists.ptr<float>(0)))[0];
907 // for(int i = 0; i < desc_count; i++)
909 // int _pose_idx = -1;
910 // float _distance = 0;
913 // descriptors[i].EstimatePose(patch, _pose_idx, _distance);
917 // descriptors[i].EstimatePosePCA(patch, _pose_idx, _distance, avg, eigenvectors);
921 // descriptors[i].EstimatePosePCA(pca_coeffs, _pose_idx, _distance, avg, eigenvectors);
925 // if(_distance < distance)
928 // pose_idx = _pose_idx;
929 // distance = _distance;
932 cvReleaseMat(&pca_coeffs);
936 void FindOneWayDescriptor(int desc_count, const OneWayDescriptor* descriptors, IplImage* patch, int n,
937 std::vector<int>& desc_idxs, std::vector<int>& pose_idxs, std::vector<float>& distances,
938 CvMat* avg, CvMat* eigenvectors)
940 for (int i=0;i<n;i++)
947 //PCA_coeffs precalculating
948 int m_pca_dim_low = descriptors[0].GetPCADimLow();
949 CvMat* pca_coeffs = cvCreateMat(1, m_pca_dim_low, CV_32FC1);
950 int patch_width = descriptors[0].GetPatchSize().width;
951 int patch_height = descriptors[0].GetPatchSize().height;
954 CvRect _roi = cvGetImageROI((IplImage*)patch);
955 IplImage* test_img = cvCreateImage(cvSize(patch_width,patch_height), IPL_DEPTH_8U, 1);
956 if(_roi.width != patch_width|| _roi.height != patch_height)
959 cvResize(patch, test_img);
960 _roi = cvGetImageROI(test_img);
964 cvCopy(patch,test_img);
966 IplImage* patch_32f = cvCreateImage(cvSize(_roi.width, _roi.height), IPL_DEPTH_32F, 1);
967 double sum = cvSum(test_img).val[0];
968 cvConvertScale(test_img, patch_32f, 1.0f/sum);
970 //ProjectPCASample(patch_32f, avg, eigenvectors, pca_coeffs);
972 CvMat* patch_mat = ConvertImageToMatrix(patch_32f);
973 CvMat* temp = cvCreateMat(1, eigenvectors->cols, CV_32FC1);
974 cvProjectPCA(patch_mat, avg, eigenvectors, temp);
976 cvGetSubRect(temp, &temp1, cvRect(0, 0, pca_coeffs->cols, 1));
977 cvCopy(&temp1, pca_coeffs);
979 cvReleaseMat(&patch_mat);
982 cvReleaseImage(&patch_32f);
983 cvReleaseImage(&test_img);
989 for(int i = 0; i < desc_count; i++)
995 descriptors[i].EstimatePose(patch, _pose_idx, _distance);
999 descriptors[i].EstimatePosePCA(patch, _pose_idx, _distance, avg, eigenvectors);
1003 descriptors[i].EstimatePosePCA(pca_coeffs, _pose_idx, _distance, avg, eigenvectors);
1007 for (int j=0;j<n;j++)
1009 if(_distance < distances[j])
1011 for (int k=(n-1);k > j;k--)
1013 desc_idxs[k] = desc_idxs[k-1];
1014 pose_idxs[k] = pose_idxs[k-1];
1015 distances[k] = distances[k-1];
1018 pose_idxs[j] = _pose_idx;
1019 distances[j] = _distance;
1024 cvReleaseMat(&pca_coeffs);
1027 void FindOneWayDescriptorEx(int desc_count, const OneWayDescriptor* descriptors, IplImage* patch,
1028 float scale_min, float scale_max, float scale_step,
1029 int& desc_idx, int& pose_idx, float& distance, float& scale,
1030 CvMat* avg, CvMat* eigenvectors)
1032 CvSize patch_size = descriptors[0].GetPatchSize();
1033 IplImage* input_patch;
1036 input_patch= cvCreateImage(patch_size, IPL_DEPTH_8U, 1);
1037 roi = cvGetImageROI((IplImage*)patch);
1039 int _desc_idx, _pose_idx;
1042 for(float cur_scale = scale_min; cur_scale < scale_max; cur_scale *= scale_step)
1044 // printf("Scale = %f\n", cur_scale);
1046 CvRect roi_scaled = resize_rect(roi, cur_scale);
1047 cvSetImageROI(patch, roi_scaled);
1048 cvResize(patch, input_patch);
1052 if(roi.x > 244 && roi.y < 200)
1054 cvNamedWindow("1", 1);
1055 cvShowImage("1", input_patch);
1060 FindOneWayDescriptor(desc_count, descriptors, input_patch, _desc_idx, _pose_idx, _distance, avg, eigenvectors);
1061 if(_distance < distance)
1063 distance = _distance;
1064 desc_idx = _desc_idx;
1065 pose_idx = _pose_idx;
1071 cvSetImageROI((IplImage*)patch, roi);
1072 cvReleaseImage(&input_patch);
1076 void FindOneWayDescriptorEx(int desc_count, const OneWayDescriptor* descriptors, IplImage* patch,
1077 float scale_min, float scale_max, float scale_step,
1078 int n, std::vector<int>& desc_idxs, std::vector<int>& pose_idxs,
1079 std::vector<float>& distances, std::vector<float>& scales,
1080 CvMat* avg, CvMat* eigenvectors)
1082 CvSize patch_size = descriptors[0].GetPatchSize();
1083 IplImage* input_patch;
1086 input_patch= cvCreateImage(patch_size, IPL_DEPTH_8U, 1);
1087 roi = cvGetImageROI((IplImage*)patch);
1089 // float min_distance = 1e10;
1090 std::vector<int> _desc_idxs;
1091 _desc_idxs.resize(n);
1092 std::vector<int> _pose_idxs;
1093 _pose_idxs.resize(n);
1094 std::vector<float> _distances;
1095 _distances.resize(n);
1098 for (int i=0;i<n;i++)
1100 distances[i] = 1e10;
1103 for(float cur_scale = scale_min; cur_scale < scale_max; cur_scale *= scale_step)
1106 CvRect roi_scaled = resize_rect(roi, cur_scale);
1107 cvSetImageROI(patch, roi_scaled);
1108 cvResize(patch, input_patch);
1112 FindOneWayDescriptor(desc_count, descriptors, input_patch, n,_desc_idxs, _pose_idxs, _distances, avg, eigenvectors);
1113 for (int i=0;i<n;i++)
1115 if(_distances[i] < distances[i])
1117 distances[i] = _distances[i];
1118 desc_idxs[i] = _desc_idxs[i];
1119 pose_idxs[i] = _pose_idxs[i];
1120 scales[i] = cur_scale;
1127 cvSetImageROI((IplImage*)patch, roi);
1128 cvReleaseImage(&input_patch);
1131 #if defined(_KDTREE)
1132 void FindOneWayDescriptorEx(cv::flann::Index* m_pca_descriptors_tree, CvSize patch_size, int m_pca_dim_low,
1133 int m_pose_count, IplImage* patch,
1134 float scale_min, float scale_max, float scale_step,
1135 int& desc_idx, int& pose_idx, float& distance, float& scale,
1136 CvMat* avg, CvMat* eigenvectors)
1138 IplImage* input_patch;
1141 input_patch= cvCreateImage(patch_size, IPL_DEPTH_8U, 1);
1142 roi = cvGetImageROI((IplImage*)patch);
1144 int _desc_idx, _pose_idx;
1147 for(float cur_scale = scale_min; cur_scale < scale_max; cur_scale *= scale_step)
1149 // printf("Scale = %f\n", cur_scale);
1151 CvRect roi_scaled = resize_rect(roi, cur_scale);
1152 cvSetImageROI(patch, roi_scaled);
1153 cvResize(patch, input_patch);
1155 FindOneWayDescriptor(m_pca_descriptors_tree, patch_size, m_pca_dim_low, m_pose_count, input_patch, _desc_idx, _pose_idx, _distance, avg, eigenvectors);
1156 if(_distance < distance)
1158 distance = _distance;
1159 desc_idx = _desc_idx;
1160 pose_idx = _pose_idx;
1166 cvSetImageROI((IplImage*)patch, roi);
1167 cvReleaseImage(&input_patch);
1172 const char* OneWayDescriptor::GetFeatureName() const
1174 return m_feature_name.c_str();
1177 CvPoint OneWayDescriptor::GetCenter() const
1182 int OneWayDescriptor::GetPCADimLow() const
1184 return m_pca_dim_low;
1187 int OneWayDescriptor::GetPCADimHigh() const
1189 return m_pca_dim_high;
1192 CvMat* ConvertImageToMatrix(IplImage* patch)
1194 CvRect roi = cvGetImageROI(patch);
1195 CvMat* mat = cvCreateMat(1, roi.width*roi.height, CV_32FC1);
1197 if(patch->depth == 32)
1199 for(int y = 0; y < roi.height; y++)
1201 for(int x = 0; x < roi.width; x++)
1203 mat->data.fl[y*roi.width + x] = *((float*)(patch->imageData + (y + roi.y)*patch->widthStep) + x + roi.x);
1207 else if(patch->depth == 8)
1209 for(int y = 0; y < roi.height; y++)
1211 for(int x = 0; x < roi.width; x++)
1213 mat->data.fl[y*roi.width + x] = (float)(unsigned char)patch->imageData[(y + roi.y)*patch->widthStep + x + roi.x];
1219 printf("Image depth %d is not supported\n", patch->depth);
1226 OneWayDescriptorBase::OneWayDescriptorBase(CvSize patch_size, int pose_count, const char* train_path,
1227 const char* pca_config, const char* pca_hr_config,
1228 const char* pca_desc_config, int pyr_levels,
1229 int pca_dim_high, int pca_dim_low)
1230 : m_pca_dim_high(pca_dim_high), m_pca_dim_low(pca_dim_low), scale_min (0.7f), scale_max(1.5f), scale_step (1.2f)
1232 #if defined(_KDTREE)
1233 m_pca_descriptors_matrix = 0;
1234 m_pca_descriptors_tree = 0;
1236 // m_pca_descriptors_matrix = 0;
1237 m_patch_size = patch_size;
1238 m_pose_count = pose_count;
1239 m_pyr_levels = pyr_levels;
1244 m_pca_eigenvectors = 0;
1246 m_pca_hr_eigenvectors = 0;
1247 m_pca_descriptors = 0;
1251 if(train_path == 0 || strlen(train_path) == 0)
1256 char pca_config_filename[1024];
1257 sprintf(pca_config_filename, "%s/%s", train_path, pca_config);
1258 readPCAFeatures(pca_config_filename, &m_pca_avg, &m_pca_eigenvectors);
1259 if(pca_hr_config && strlen(pca_hr_config) > 0)
1261 char pca_hr_config_filename[1024];
1262 sprintf(pca_hr_config_filename, "%s/%s", train_path, pca_hr_config);
1263 readPCAFeatures(pca_hr_config_filename, &m_pca_hr_avg, &m_pca_hr_eigenvectors);
1266 m_pca_descriptors = new OneWayDescriptor[m_pca_dim_high + 1];
1268 #if !defined(_GH_REGIONS)
1269 if(pca_desc_config && strlen(pca_desc_config) > 0)
1272 //printf("Loading the descriptors...");
1273 char pca_desc_config_filename[1024];
1274 sprintf(pca_desc_config_filename, "%s/%s", train_path, pca_desc_config);
1275 LoadPCADescriptors(pca_desc_config_filename);
1276 //printf("done.\n");
1280 printf("Initializing the descriptors...\n");
1281 InitializePoseTransforms();
1282 CreatePCADescriptors();
1283 SavePCADescriptors("pca_descriptors.yml");
1285 #endif //_GH_REGIONS
1286 // SavePCADescriptors("./pca_descriptors.yml");
1290 OneWayDescriptorBase::OneWayDescriptorBase(CvSize patch_size, int pose_count, const String &pca_filename,
1291 const String &train_path, const String &images_list, float _scale_min, float _scale_max,
1292 float _scale_step, int pyr_levels,
1293 int pca_dim_high, int pca_dim_low)
1294 : m_pca_dim_high(pca_dim_high), m_pca_dim_low(pca_dim_low), scale_min(_scale_min), scale_max(_scale_max), scale_step(_scale_step)
1296 #if defined(_KDTREE)
1297 m_pca_descriptors_matrix = 0;
1298 m_pca_descriptors_tree = 0;
1300 m_patch_size = patch_size;
1301 m_pose_count = pose_count;
1302 m_pyr_levels = pyr_levels;
1307 m_pca_eigenvectors = 0;
1309 m_pca_hr_eigenvectors = 0;
1310 m_pca_descriptors = 0;
1315 if (pca_filename.length() == 0)
1320 CvFileStorage* fs = cvOpenFileStorage(pca_filename.c_str(), NULL, CV_STORAGE_READ);
1323 cvReleaseFileStorage(&fs);
1325 readPCAFeatures(pca_filename.c_str(), &m_pca_avg, &m_pca_eigenvectors, "_lr");
1326 readPCAFeatures(pca_filename.c_str(), &m_pca_hr_avg, &m_pca_hr_eigenvectors, "_hr");
1327 m_pca_descriptors = new OneWayDescriptor[m_pca_dim_high + 1];
1328 #if !defined(_GH_REGIONS)
1329 LoadPCADescriptors(pca_filename.c_str());
1330 #endif //_GH_REGIONS
1334 GeneratePCA(train_path.c_str(), images_list.c_str());
1335 m_pca_descriptors = new OneWayDescriptor[m_pca_dim_high + 1];
1336 char pca_default_filename[1024];
1337 sprintf(pca_default_filename, "%s/%s", train_path.c_str(), GetPCAFilename().c_str());
1338 LoadPCADescriptors(pca_default_filename);
1342 void OneWayDescriptorBase::Read (const FileNode &fn)
1346 m_pose_count = fn["poseCount"];
1347 int patch_width = fn["patchWidth"];
1348 int patch_height = fn["patchHeight"];
1349 m_patch_size = cvSize (patch_width, patch_height);
1350 m_pyr_levels = fn["pyrLevels"];
1351 m_pca_dim_high = fn["pcaDimHigh"];
1352 m_pca_dim_low = fn["pcaDimLow"];
1353 scale_min = fn["minScale"];
1354 scale_max = fn["maxScale"];
1355 scale_step = fn["stepScale"];
1360 void OneWayDescriptorBase::LoadPCAall (const FileNode &fn)
1362 readPCAFeatures(fn, &m_pca_avg, &m_pca_eigenvectors, "_lr");
1363 readPCAFeatures(fn, &m_pca_hr_avg, &m_pca_hr_eigenvectors, "_hr");
1364 m_pca_descriptors = new OneWayDescriptor[m_pca_dim_high + 1];
1365 #if !defined(_GH_REGIONS)
1366 LoadPCADescriptors(fn);
1367 #endif //_GH_REGIONS
1370 OneWayDescriptorBase::~OneWayDescriptorBase()
1372 cvReleaseMat(&m_pca_avg);
1373 cvReleaseMat(&m_pca_eigenvectors);
1375 if(m_pca_hr_eigenvectors)
1377 delete[] m_pca_descriptors;
1378 cvReleaseMat(&m_pca_hr_avg);
1379 cvReleaseMat(&m_pca_hr_eigenvectors);
1384 delete []m_descriptors;
1391 for(int i = 0; i < m_pose_count; i++)
1393 cvReleaseMat(&m_transforms[i]);
1395 delete []m_transforms;
1397 #if defined(_KDTREE)
1398 if (m_pca_descriptors_matrix)
1400 cvReleaseMat(&m_pca_descriptors_matrix);
1402 if (m_pca_descriptors_tree)
1404 delete m_pca_descriptors_tree;
1409 void OneWayDescriptorBase::clear(){
1412 delete []m_descriptors;
1416 #if defined(_KDTREE)
1417 if (m_pca_descriptors_matrix)
1419 cvReleaseMat(&m_pca_descriptors_matrix);
1420 m_pca_descriptors_matrix = 0;
1422 if (m_pca_descriptors_tree)
1424 delete m_pca_descriptors_tree;
1425 m_pca_descriptors_tree = 0;
1430 void OneWayDescriptorBase::InitializePoses()
1432 m_poses = new CvAffinePose[m_pose_count];
1433 for(int i = 0; i < m_pose_count; i++)
1435 m_poses[i] = GenRandomAffinePose();
1439 void OneWayDescriptorBase::InitializeTransformsFromPoses()
1441 m_transforms = new CvMat*[m_pose_count];
1442 for(int i = 0; i < m_pose_count; i++)
1444 m_transforms[i] = cvCreateMat(2, 3, CV_32FC1);
1445 GenerateAffineTransformFromPose(cvSize(m_patch_size.width*2, m_patch_size.height*2), m_poses[i], m_transforms[i]);
1449 void OneWayDescriptorBase::InitializePoseTransforms()
1452 InitializeTransformsFromPoses();
1455 void OneWayDescriptorBase::InitializeDescriptor(int desc_idx, IplImage* train_image, const KeyPoint& keypoint, const char* feature_label)
1458 // TBD add support for octave != 0
1459 CvPoint center = keypoint.pt;
1461 CvRect roi = cvRect(center.x - m_patch_size.width/2, center.y - m_patch_size.height/2, m_patch_size.width, m_patch_size.height);
1462 cvResetImageROI(train_image);
1463 roi = fit_rect_fixedsize(roi, train_image);
1464 cvSetImageROI(train_image, roi);
1465 if(roi.width != m_patch_size.width || roi.height != m_patch_size.height)
1470 InitializeDescriptor(desc_idx, train_image, feature_label);
1471 cvResetImageROI(train_image);
1474 void OneWayDescriptorBase::InitializeDescriptor(int desc_idx, IplImage* train_image, const char* feature_label)
1476 m_descriptors[desc_idx].SetPCADimHigh(m_pca_dim_high);
1477 m_descriptors[desc_idx].SetPCADimLow(m_pca_dim_low);
1478 m_descriptors[desc_idx].SetTransforms(m_poses, m_transforms);
1480 if(!m_pca_hr_eigenvectors)
1482 m_descriptors[desc_idx].Initialize(m_pose_count, train_image, feature_label);
1486 m_descriptors[desc_idx].InitializeFast(m_pose_count, train_image, feature_label,
1487 m_pca_hr_avg, m_pca_hr_eigenvectors, m_pca_descriptors);
1492 m_descriptors[desc_idx].InitializePCACoeffs(m_pca_avg, m_pca_eigenvectors);
1496 void OneWayDescriptorBase::FindDescriptor(IplImage* src, cv::Point2f pt, int& desc_idx, int& pose_idx, float& distance) const
1498 CvRect roi = cvRect(cvRound(pt.x - m_patch_size.width/4),
1499 cvRound(pt.y - m_patch_size.height/4),
1500 m_patch_size.width/2, m_patch_size.height/2);
1501 cvSetImageROI(src, roi);
1503 FindDescriptor(src, desc_idx, pose_idx, distance);
1504 cvResetImageROI(src);
1507 void OneWayDescriptorBase::FindDescriptor(IplImage* patch, int& desc_idx, int& pose_idx, float& distance, float* _scale, float* scale_ranges) const
1510 ::FindOneWayDescriptor(m_train_feature_count, m_descriptors, patch, desc_idx, pose_idx, distance, m_pca_avg, m_pca_eigenvectors);
1512 float min = scale_min;
1513 float max = scale_max;
1514 float step = scale_step;
1518 min = scale_ranges[0];
1519 max = scale_ranges[1];
1524 #if !defined(_KDTREE)
1525 cv::FindOneWayDescriptorEx(m_train_feature_count, m_descriptors, patch,
1526 min, max, step, desc_idx, pose_idx, distance, scale,
1527 m_pca_avg, m_pca_eigenvectors);
1529 cv::FindOneWayDescriptorEx(m_pca_descriptors_tree, m_descriptors[0].GetPatchSize(), m_descriptors[0].GetPCADimLow(), m_pose_count, patch,
1530 min, max, step, desc_idx, pose_idx, distance, scale,
1531 m_pca_avg, m_pca_eigenvectors);
1540 void OneWayDescriptorBase::FindDescriptor(IplImage* patch, int n, std::vector<int>& desc_idxs, std::vector<int>& pose_idxs,
1541 std::vector<float>& distances, std::vector<float>& _scales, float* scale_ranges) const
1543 float min = scale_min;
1544 float max = scale_max;
1545 float step = scale_step;
1549 min = scale_ranges[0];
1550 max = scale_ranges[1];
1553 distances.resize(n);
1555 desc_idxs.resize(n);
1556 pose_idxs.resize(n);
1557 /*float scales = 1.0f;*/
1559 cv::FindOneWayDescriptorEx(m_train_feature_count, m_descriptors, patch,
1560 min, max, step ,n, desc_idxs, pose_idxs, distances, _scales,
1561 m_pca_avg, m_pca_eigenvectors);
1565 void OneWayDescriptorBase::SetPCAHigh(CvMat* avg, CvMat* eigenvectors)
1567 m_pca_hr_avg = cvCloneMat(avg);
1568 m_pca_hr_eigenvectors = cvCloneMat(eigenvectors);
1571 void OneWayDescriptorBase::SetPCALow(CvMat* avg, CvMat* eigenvectors)
1573 m_pca_avg = cvCloneMat(avg);
1574 m_pca_eigenvectors = cvCloneMat(eigenvectors);
1577 void OneWayDescriptorBase::AllocatePCADescriptors()
1579 m_pca_descriptors = new OneWayDescriptor[m_pca_dim_high + 1];
1580 for(int i = 0; i < m_pca_dim_high + 1; i++)
1582 m_pca_descriptors[i].SetPCADimHigh(m_pca_dim_high);
1583 m_pca_descriptors[i].SetPCADimLow(m_pca_dim_low);
1587 void OneWayDescriptorBase::CreatePCADescriptors()
1589 if(m_pca_descriptors == 0)
1591 AllocatePCADescriptors();
1593 IplImage* frontal = cvCreateImage(m_patch_size, IPL_DEPTH_32F, 1);
1595 eigenvector2image(m_pca_hr_avg, frontal);
1596 m_pca_descriptors[0].SetTransforms(m_poses, m_transforms);
1597 m_pca_descriptors[0].Initialize(m_pose_count, frontal, "", 0);
1599 for(int j = 0; j < m_pca_dim_high; j++)
1602 cvGetSubRect(m_pca_hr_eigenvectors, &eigenvector, cvRect(0, j, m_pca_hr_eigenvectors->cols, 1));
1603 eigenvector2image(&eigenvector, frontal);
1605 m_pca_descriptors[j + 1].SetTransforms(m_poses, m_transforms);
1606 m_pca_descriptors[j + 1].Initialize(m_pose_count, frontal, "", 0);
1608 printf("Created descriptor for PCA component %d\n", j);
1611 cvReleaseImage(&frontal);
1615 int OneWayDescriptorBase::LoadPCADescriptors(const char* filename)
1617 FileStorage fs = FileStorage (filename, FileStorage::READ);
1620 printf("File %s not found...\n", filename);
1624 LoadPCADescriptors (fs.root ());
1626 printf("Successfully read %d pca components\n", m_pca_dim_high);
1632 int OneWayDescriptorBase::LoadPCADescriptors(const FileNode &fn)
1634 // read affine poses
1635 // FileNode* node = cvGetFileNodeByName(fs, 0, "affine poses");
1636 CvMat* poses = reinterpret_cast<CvMat*> (fn["affine_poses"].readObj ());
1639 poses = reinterpret_cast<CvMat*> (fn["affine poses"].readObj ());
1649 m_poses = new CvAffinePose[m_pose_count];
1650 for(int i = 0; i < m_pose_count; i++)
1652 m_poses[i].phi = (float)cvmGet(poses, i, 0);
1653 m_poses[i].theta = (float)cvmGet(poses, i, 1);
1654 m_poses[i].lambda1 = (float)cvmGet(poses, i, 2);
1655 m_poses[i].lambda2 = (float)cvmGet(poses, i, 3);
1657 cvReleaseMat(&poses);
1659 // now initialize pose transforms
1660 InitializeTransformsFromPoses();
1662 m_pca_dim_high = (int) fn["pca_components_number"];
1663 if (m_pca_dim_high == 0)
1665 m_pca_dim_high = (int) fn["pca components number"];
1667 if(m_pca_descriptors)
1669 delete []m_pca_descriptors;
1671 AllocatePCADescriptors();
1672 for(int i = 0; i < m_pca_dim_high + 1; i++)
1674 m_pca_descriptors[i].Allocate(m_pose_count, m_patch_size, 1);
1675 m_pca_descriptors[i].SetTransforms(m_poses, m_transforms);
1677 sprintf(buf, "descriptor_for_pca_component_%d", i);
1679 if (! m_pca_descriptors[i].ReadByName(fn, buf))
1681 sprintf(buf, "descriptor for pca component %d", i);
1682 m_pca_descriptors[i].ReadByName(fn, buf);
1689 void savePCAFeatures(FileStorage &fs, const char* postfix, CvMat* avg, CvMat* eigenvectors)
1692 sprintf(buf, "avg_%s", postfix);
1693 fs.writeObj(buf, avg);
1694 sprintf(buf, "eigenvectors_%s", postfix);
1695 fs.writeObj(buf, eigenvectors);
1698 void calcPCAFeatures(std::vector<IplImage*>& patches, FileStorage &fs, const char* postfix, CvMat** avg,
1699 CvMat** eigenvectors)
1701 int width = patches[0]->width;
1702 int height = patches[0]->height;
1703 int length = width * height;
1704 int patch_count = (int)patches.size();
1706 CvMat* data = cvCreateMat(patch_count, length, CV_32FC1);
1707 *avg = cvCreateMat(1, length, CV_32FC1);
1708 CvMat* eigenvalues = cvCreateMat(1, length, CV_32FC1);
1709 *eigenvectors = cvCreateMat(length, length, CV_32FC1);
1711 for (int i = 0; i < patch_count; i++)
1713 float nf = (float)(1./cvSum(patches[i]).val[0]);
1714 for (int y = 0; y < height; y++)
1716 for (int x = 0; x < width; x++)
1718 *((float*)(data->data.ptr + data->step * i) + y * width + x)
1719 = (unsigned char)patches[i]->imageData[y * patches[i]->widthStep + x] * nf;
1724 //printf("Calculating PCA...");
1725 cvCalcPCA(data, *avg, eigenvalues, *eigenvectors, CV_PCA_DATA_AS_ROW);
1729 savePCAFeatures(fs, postfix, *avg, *eigenvectors);
1731 cvReleaseMat(&data);
1732 cvReleaseMat(&eigenvalues);
1735 static void extractPatches (IplImage *img, std::vector<IplImage*>& patches, CvSize patch_size)
1737 std::vector<KeyPoint> features;
1738 Ptr<FeatureDetector> surf_extractor = FeatureDetector::create("SURF");
1739 if( !surf_extractor )
1740 CV_Error(CV_StsNotImplemented, "OpenCV was built without SURF support");
1741 surf_extractor->set("hessianThreshold", 1.0);
1742 //printf("Extracting SURF features...");
1743 surf_extractor->detect(cv::cvarrToMat(img), features);
1746 for (int j = 0; j < (int)features.size(); j++)
1748 int patch_width = patch_size.width;
1749 int patch_height = patch_size.height;
1751 CvPoint center = features[j].pt;
1753 CvRect roi = cvRect(center.x - patch_width / 2, center.y - patch_height / 2, patch_width, patch_height);
1754 cvSetImageROI(img, roi);
1755 roi = cvGetImageROI(img);
1756 if (roi.width != patch_width || roi.height != patch_height)
1761 IplImage* patch = cvCreateImage(cvSize(patch_width, patch_height), IPL_DEPTH_8U, 1);
1763 patches.push_back(patch);
1764 cvResetImageROI(img);
1766 //printf("Completed file, extracted %d features\n", (int)features.size());
1770 void loadPCAFeatures(const FileNode &fn, std::vector<IplImage*>& patches, CvSize patch_size)
1772 FileNodeIterator begin = fn.begin();
1773 for (FileNodeIterator i = fn.begin(); i != fn.end(); i++)
1775 IplImage *img = reinterpret_cast<IplImage*> ((*i).readObj());
1776 extractPatches (img, patches, patch_size);
1777 cvReleaseImage(&img);
1782 void loadPCAFeatures(const char* path, const char* images_list, std::vector<IplImage*>& patches, CvSize patch_size)
1784 char images_filename[1024];
1785 sprintf(images_filename, "%s/%s", path, images_list);
1786 FILE *pFile = fopen(images_filename, "r");
1789 printf("Cannot open images list file %s\n", images_filename);
1792 while (!feof(pFile))
1794 char imagename[1024];
1795 if (fscanf(pFile, "%s", imagename) <= 0)
1800 char filename[1024];
1801 sprintf(filename, "%s/%s", path, imagename);
1803 //printf("Reading image %s...", filename);
1805 #ifdef HAVE_OPENCV_HIGHGUI
1806 Mat img2 = cv::imread(filename, IMREAD_GRAYSCALE);
1809 CV_Error(CV_StsNotImplemented, "OpenCV has been compiled without image I/O support");
1813 extractPatches (&img, patches, patch_size);
1818 void generatePCAFeatures(const char* path, const char* img_filename, FileStorage& fs, const char* postfix,
1819 CvSize patch_size, CvMat** avg, CvMat** eigenvectors)
1821 std::vector<IplImage*> patches;
1822 loadPCAFeatures(path, img_filename, patches, patch_size);
1823 calcPCAFeatures(patches, fs, postfix, avg, eigenvectors);
1827 void generatePCAFeatures(const FileNode &fn, const char* postfix,
1828 CvSize patch_size, CvMat** avg, CvMat** eigenvectors)
1830 std::vector<IplImage*> patches;
1831 loadPCAFeatures(fn, patches, patch_size);
1832 calcPCAFeatures(patches, fs, postfix, avg, eigenvectors);
1836 void OneWayDescriptorBase::GeneratePCA(const FileNode &fn, int pose_count)
1838 generatePCAFeatures(fn, "hr", m_patch_size, &m_pca_hr_avg, &m_pca_hr_eigenvectors);
1839 generatePCAFeatures(fn, "lr", cvSize(m_patch_size.width / 2, m_patch_size.height / 2),
1840 &m_pca_avg, &m_pca_eigenvectors);
1843 OneWayDescriptorBase descriptors(m_patch_size, pose_count);
1844 descriptors.SetPCAHigh(m_pca_hr_avg, m_pca_hr_eigenvectors);
1845 descriptors.SetPCALow(m_pca_avg, m_pca_eigenvectors);
1847 printf("Calculating %d PCA descriptors (you can grab a coffee, this will take a while)...\n",
1848 descriptors.GetPCADimHigh());
1849 descriptors.InitializePoseTransforms();
1850 descriptors.CreatePCADescriptors();
1851 descriptors.SavePCADescriptors(*fs);
1855 void OneWayDescriptorBase::GeneratePCA(const char* img_path, const char* images_list, int pose_count)
1857 char pca_filename[1024];
1858 sprintf(pca_filename, "%s/%s", img_path, GetPCAFilename().c_str());
1859 FileStorage fs = FileStorage(pca_filename, FileStorage::WRITE);
1861 generatePCAFeatures(img_path, images_list, fs, "hr", m_patch_size, &m_pca_hr_avg, &m_pca_hr_eigenvectors);
1862 generatePCAFeatures(img_path, images_list, fs, "lr", cvSize(m_patch_size.width / 2, m_patch_size.height / 2),
1863 &m_pca_avg, &m_pca_eigenvectors);
1865 OneWayDescriptorBase descriptors(m_patch_size, pose_count);
1866 descriptors.SetPCAHigh(m_pca_hr_avg, m_pca_hr_eigenvectors);
1867 descriptors.SetPCALow(m_pca_avg, m_pca_eigenvectors);
1869 printf("Calculating %d PCA descriptors (you can grab a coffee, this will take a while)...\n",
1870 descriptors.GetPCADimHigh());
1871 descriptors.InitializePoseTransforms();
1872 descriptors.CreatePCADescriptors();
1873 descriptors.SavePCADescriptors(*fs);
1878 void OneWayDescriptorBase::Write (FileStorage &fs) const
1880 fs << "poseCount" << m_pose_count;
1881 fs << "patchWidth" << m_patch_size.width;
1882 fs << "patchHeight" << m_patch_size.height;
1883 fs << "minScale" << scale_min;
1884 fs << "maxScale" << scale_max;
1885 fs << "stepScale" << scale_step;
1886 fs << "pyrLevels" << m_pyr_levels;
1887 fs << "pcaDimHigh" << m_pca_dim_high;
1888 fs << "pcaDimLow" << m_pca_dim_low;
1893 void OneWayDescriptorBase::SavePCAall (FileStorage &fs) const
1895 savePCAFeatures(fs, "hr", m_pca_hr_avg, m_pca_hr_eigenvectors);
1896 savePCAFeatures(fs, "lr", m_pca_avg, m_pca_eigenvectors);
1897 SavePCADescriptors(*fs);
1900 void OneWayDescriptorBase::SavePCADescriptors(const char* filename)
1902 CvMemStorage* storage = cvCreateMemStorage();
1903 CvFileStorage* fs = cvOpenFileStorage(filename, storage, CV_STORAGE_WRITE);
1905 SavePCADescriptors (fs);
1907 cvReleaseMemStorage(&storage);
1908 cvReleaseFileStorage(&fs);
1911 void OneWayDescriptorBase::SavePCADescriptors(CvFileStorage *fs) const
1913 cvWriteInt(fs, "pca_components_number", m_pca_dim_high);
1916 "The first component is the average Vector, so the total number of components is <pca components number> + 1",
1918 cvWriteInt(fs, "patch_width", m_patch_size.width);
1919 cvWriteInt(fs, "patch_height", m_patch_size.height);
1921 // pack the affine transforms into a single CvMat and write them
1922 CvMat* poses = cvCreateMat(m_pose_count, 4, CV_32FC1);
1923 for (int i = 0; i < m_pose_count; i++)
1925 cvmSet(poses, i, 0, m_poses[i].phi);
1926 cvmSet(poses, i, 1, m_poses[i].theta);
1927 cvmSet(poses, i, 2, m_poses[i].lambda1);
1928 cvmSet(poses, i, 3, m_poses[i].lambda2);
1930 cvWrite(fs, "affine_poses", poses);
1931 cvReleaseMat(&poses);
1933 for (int i = 0; i < m_pca_dim_high + 1; i++)
1936 sprintf(buf, "descriptor_for_pca_component_%d", i);
1937 m_pca_descriptors[i].Write(fs, buf);
1942 void OneWayDescriptorBase::Allocate(int train_feature_count)
1944 m_train_feature_count = train_feature_count;
1945 m_descriptors = new OneWayDescriptor[m_train_feature_count];
1946 for(int i = 0; i < m_train_feature_count; i++)
1948 m_descriptors[i].SetPCADimHigh(m_pca_dim_high);
1949 m_descriptors[i].SetPCADimLow(m_pca_dim_low);
1953 void OneWayDescriptorBase::InitializeDescriptors(IplImage* train_image, const std::vector<KeyPoint>& features,
1954 const char* feature_label, int desc_start_idx)
1956 for(int i = 0; i < (int)features.size(); i++)
1958 InitializeDescriptor(desc_start_idx + i, train_image, features[i], feature_label);
1961 cvResetImageROI(train_image);
1963 #if defined(_KDTREE)
1964 ConvertDescriptorsArrayToTree();
1968 void OneWayDescriptorBase::CreateDescriptorsFromImage(IplImage* src, const std::vector<KeyPoint>& features)
1970 m_train_feature_count = (int)features.size();
1972 m_descriptors = new OneWayDescriptor[m_train_feature_count];
1974 InitializeDescriptors(src, features);
1978 #if defined(_KDTREE)
1979 void OneWayDescriptorBase::ConvertDescriptorsArrayToTree()
1981 int n = this->GetDescriptorCount();
1984 int pca_dim_low = this->GetDescriptor(0)->GetPCADimLow();
1986 //if (!m_pca_descriptors_matrix)
1987 // m_pca_descriptors_matrix = new ::cvflann::Matrix<float>(n*m_pose_count,pca_dim_low);
1990 // if ((m_pca_descriptors_matrix->cols != pca_dim_low)&&(m_pca_descriptors_matrix->rows != n*m_pose_count))
1992 // delete m_pca_descriptors_matrix;
1993 // m_pca_descriptors_matrix = new ::cvflann::Matrix<float>(n*m_pose_count,pca_dim_low);
1997 m_pca_descriptors_matrix = cvCreateMat(n*m_pose_count,pca_dim_low,CV_32FC1);
1998 for (int i=0;i<n;i++)
2000 CvMat** pca_coeffs = m_descriptors[i].GetPCACoeffs();
2001 for (int j = 0;j<m_pose_count;j++)
2003 for (int k=0;k<pca_dim_low;k++)
2005 m_pca_descriptors_matrix->data.fl[(i*m_pose_count+j)*m_pca_dim_low + k] = pca_coeffs[j]->data.fl[k];
2009 cv::Mat pca_descriptors_mat(m_pca_descriptors_matrix,false);
2011 //::cvflann::KDTreeIndexParams params;
2013 //m_pca_descriptors_tree = new KDTree(pca_descriptors_mat);
2014 m_pca_descriptors_tree = new cv::flann::Index(pca_descriptors_mat,cv::flann::KDTreeIndexParams(1));
2015 //cvReleaseMat(&m_pca_descriptors_matrix);
2016 //m_pca_descriptors_tree->buildIndex();
2020 void OneWayDescriptorObject::Allocate(int train_feature_count, int object_feature_count)
2022 OneWayDescriptorBase::Allocate(train_feature_count);
2023 m_object_feature_count = object_feature_count;
2025 m_part_id = new int[m_object_feature_count];
2029 void OneWayDescriptorObject::InitializeObjectDescriptors(IplImage* train_image, const std::vector<KeyPoint>& features,
2030 const char* feature_label, int desc_start_idx, float scale, int is_background)
2032 InitializeDescriptors(train_image, features, feature_label, desc_start_idx);
2034 for(int i = 0; i < (int)features.size(); i++)
2036 CvPoint center = features[i].pt;
2040 // remember descriptor part id
2041 CvPoint center_scaled = cvPoint(round(center.x*scale), round(center.y*scale));
2042 m_part_id[i + desc_start_idx] = MatchPointToPart(center_scaled);
2045 cvResetImageROI(train_image);
2048 int OneWayDescriptorObject::IsDescriptorObject(int desc_idx) const
2050 return desc_idx < m_object_feature_count ? 1 : 0;
2053 int OneWayDescriptorObject::MatchPointToPart(CvPoint pt) const
2056 const int max_dist = 10;
2057 for(int i = 0; i < (int)m_train_features.size(); i++)
2059 if(norm(Point2f(pt) - m_train_features[i].pt) < max_dist)
2069 int OneWayDescriptorObject::GetDescriptorPart(int desc_idx) const
2071 // return MatchPointToPart(GetDescriptor(desc_idx)->GetCenter());
2072 return desc_idx < m_object_feature_count ? m_part_id[desc_idx] : -1;
2075 OneWayDescriptorObject::OneWayDescriptorObject(CvSize patch_size, int pose_count, const char* train_path,
2076 const char* pca_config, const char* pca_hr_config, const char* pca_desc_config, int pyr_levels) :
2077 OneWayDescriptorBase(patch_size, pose_count, train_path, pca_config, pca_hr_config, pca_desc_config, pyr_levels)
2082 OneWayDescriptorObject::OneWayDescriptorObject(CvSize patch_size, int pose_count, const String &pca_filename,
2083 const String &train_path, const String &images_list, float _scale_min, float _scale_max, float _scale_step, int pyr_levels) :
2084 OneWayDescriptorBase(patch_size, pose_count, pca_filename, train_path, images_list, _scale_min, _scale_max, _scale_step, pyr_levels)
2089 OneWayDescriptorObject::~OneWayDescriptorObject()
2095 std::vector<KeyPoint> OneWayDescriptorObject::_GetLabeledFeatures() const
2097 std::vector<KeyPoint> features;
2098 for(size_t i = 0; i < m_train_features.size(); i++)
2100 features.push_back(m_train_features[i]);
2106 void eigenvector2image(CvMat* eigenvector, IplImage* img)
2108 CvRect roi = cvGetImageROI(img);
2109 if(img->depth == 32)
2111 for(int y = 0; y < roi.height; y++)
2113 for(int x = 0; x < roi.width; x++)
2115 float val = (float)cvmGet(eigenvector, 0, roi.width*y + x);
2116 *((float*)(img->imageData + (roi.y + y)*img->widthStep) + roi.x + x) = val;
2122 for(int y = 0; y < roi.height; y++)
2124 for(int x = 0; x < roi.width; x++)
2126 float val = (float)cvmGet(eigenvector, 0, roi.width*y + x);
2127 img->imageData[(roi.y + y)*img->widthStep + roi.x + x] = (unsigned char)val;
2133 void readPCAFeatures(const char* filename, CvMat** avg, CvMat** eigenvectors, const char* postfix)
2135 FileStorage fs = FileStorage(filename, FileStorage::READ);
2136 if (!fs.isOpened ())
2138 printf("Cannot open file %s! Exiting!", filename);
2141 readPCAFeatures (fs.root (), avg, eigenvectors, postfix);
2145 void readPCAFeatures(const FileNode &fn, CvMat** avg, CvMat** eigenvectors, const char* postfix)
2147 String str = String ("avg") + postfix;
2148 CvMat* _avg = reinterpret_cast<CvMat*> (fn[str].readObj());
2151 *avg = cvCloneMat(_avg);
2152 cvReleaseMat(&_avg);
2155 str = String ("eigenvectors") + postfix;
2156 CvMat* _eigenvectors = reinterpret_cast<CvMat*> (fn[str].readObj());
2157 if (_eigenvectors != 0)
2159 *eigenvectors = cvCloneMat(_eigenvectors);
2160 cvReleaseMat(&_eigenvectors);
2164 /****************************************************************************************\
2165 * OneWayDescriptorMatcher *
2166 \****************************************************************************************/
2168 OneWayDescriptorMatcher::Params::Params( int _poseCount, Size _patchSize, String _pcaFilename,
2169 String _trainPath, String _trainImagesList,
2170 float _minScale, float _maxScale, float _stepScale ) :
2171 poseCount(_poseCount), patchSize(_patchSize), pcaFilename(_pcaFilename),
2172 trainPath(_trainPath), trainImagesList(_trainImagesList),
2173 minScale(_minScale), maxScale(_maxScale), stepScale(_stepScale)
2177 OneWayDescriptorMatcher::OneWayDescriptorMatcher( const Params& _params)
2179 initialize(_params);
2182 OneWayDescriptorMatcher::~OneWayDescriptorMatcher()
2185 void OneWayDescriptorMatcher::initialize( const Params& _params, const Ptr<OneWayDescriptorBase>& _base )
2195 void OneWayDescriptorMatcher::clear()
2197 GenericDescriptorMatcher::clear();
2204 void OneWayDescriptorMatcher::train()
2206 if( !base || prevTrainCount < (int)trainPointCollection.keypointCount() )
2209 new OneWayDescriptorObject( params.patchSize, params.poseCount, params.pcaFilename,
2210 params.trainPath, params.trainImagesList, params.minScale, params.maxScale, params.stepScale ));
2212 base->Allocate( (int)trainPointCollection.keypointCount() );
2213 prevTrainCount = (int)trainPointCollection.keypointCount();
2215 const std::vector<std::vector<KeyPoint> >& points = trainPointCollection.getKeypoints();
2217 for( size_t i = 0; i < points.size(); i++ )
2219 IplImage _image = trainPointCollection.getImage((int)i);
2220 for( size_t j = 0; j < points[i].size(); j++ )
2221 base->InitializeDescriptor( count++, &_image, points[i][j], "" );
2224 #if defined(_KDTREE)
2225 base->ConvertDescriptorsArrayToTree();
2230 bool OneWayDescriptorMatcher::isMaskSupported()
2235 void OneWayDescriptorMatcher::knnMatchImpl( InputArray _queryImage, std::vector<KeyPoint>& queryKeypoints,
2236 std::vector<std::vector<DMatch> >& matches, int knn,
2237 InputArrayOfArrays /*masks*/, bool /*compactResult*/ )
2239 Mat queryImage = _queryImage.getMat();
2242 CV_Assert( knn == 1 ); // knn > 1 unsupported because of bug in OneWayDescriptorBase for this case
2244 matches.resize( queryKeypoints.size() );
2245 IplImage _qimage = queryImage;
2246 for( size_t i = 0; i < queryKeypoints.size(); i++ )
2248 int descIdx = -1, poseIdx = -1;
2250 base->FindDescriptor( &_qimage, queryKeypoints[i].pt, descIdx, poseIdx, distance );
2251 matches[i].push_back( DMatch((int)i, descIdx, distance) );
2255 void OneWayDescriptorMatcher::radiusMatchImpl( InputArray _queryImage, std::vector<KeyPoint>& queryKeypoints,
2256 std::vector<std::vector<DMatch> >& matches, float maxDistance,
2257 InputArrayOfArrays /*masks*/, bool /*compactResult*/ )
2259 Mat queryImage = _queryImage.getMat();
2263 matches.resize( queryKeypoints.size() );
2264 IplImage _qimage = queryImage;
2265 for( size_t i = 0; i < queryKeypoints.size(); i++ )
2267 int descIdx = -1, poseIdx = -1;
2269 base->FindDescriptor( &_qimage, queryKeypoints[i].pt, descIdx, poseIdx, distance );
2270 if( distance < maxDistance )
2271 matches[i].push_back( DMatch((int)i, descIdx, distance) );
2275 void OneWayDescriptorMatcher::read( const FileNode &fn )
2278 new OneWayDescriptorObject( params.patchSize, params.poseCount, String (), String (), String (),
2279 params.minScale, params.maxScale, params.stepScale ));
2283 void OneWayDescriptorMatcher::write( FileStorage& fs ) const
2288 bool OneWayDescriptorMatcher::empty() const
2290 return !base || base->empty();
2293 Ptr<GenericDescriptorMatcher> OneWayDescriptorMatcher::clone( bool emptyTrainData ) const
2295 Ptr<OneWayDescriptorMatcher> matcher = makePtr<OneWayDescriptorMatcher>( params );
2297 if( !emptyTrainData )
2299 CV_Error( CV_StsNotImplemented, "deep clone functionality is not implemented, because "
2300 "OneWayDescriptorBase has not copy constructor or clone method ");
2303 matcher->params = params;
2304 matcher->prevTrainCount = prevTrainCount;
2305 matcher->trainPointCollection = trainPointCollection;