sift.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <iostream>
00025 #include <vector>
00026
00027 #include <classifiers/sift.h>
00028
00029 #include <utils/time/clock.h>
00030 #include <utils/time/tracker.h>
00031
00032
00033 extern "C" {
00034 #include <sift/sift.h>
00035 #include <sift/imgfeatures.h>
00036 #include <sift/kdtree.h>
00037 #include <sift/utils.h>
00038 #include <sift/xform.h>
00039 }
00040
00041 #include <core/exception.h>
00042 #include <core/exceptions/software.h>
00043 #include <fvutils/color/colorspaces.h>
00044 #include <fvutils/color/conversions.h>
00045
00046 #include <opencv/cv.h>
00047 #include <opencv/cxcore.h>
00048 #include <opencv/highgui.h>
00049
00050 using namespace fawkes;
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 SiftClassifier::SiftClassifier( const char * object_file,
00074 unsigned int pixel_width, unsigned int pixel_height,
00075 int kdtree_bbf_max_nn_chks, float nn_sq_dist_ratio_thr, int flags)
00076 : Classifier("SiftClassifier")
00077 {
00078 __kdtree_bbf_max_nn_chks = kdtree_bbf_max_nn_chks;
00079 __nn_sq_dist_ratio_thr = nn_sq_dist_ratio_thr;
00080 __flags = flags;
00081
00082
00083
00084 __tt = new TimeTracker();
00085 __loop_count = 0;
00086 __ttc_objconv = __tt->add_class("ObjectConvert");
00087 __ttc_objfeat = __tt->add_class("ObjectFeatures");
00088 __ttc_imgconv = __tt->add_class("ImageConvert");
00089 __ttc_imgfeat = __tt->add_class("ImageFeatures");
00090 __ttc_matchin = __tt->add_class("Matching");
00091 __ttc_roimerg = __tt->add_class("MergeROIs");
00092
00093
00094
00095 __tt->ping_start(__ttc_objconv);
00096
00097 __obj_img = cvLoadImage( object_file, 1 );
00098 if ( ! __obj_img ) {
00099 throw Exception("Could not load object file");
00100 }
00101
00102 __tt->ping_end(__ttc_objconv);
00103
00104
00105
00106 __tt->ping_start(__ttc_objfeat);
00107
00108 __obj_num_features = 0;
00109 __obj_num_features = sift_features( __obj_img, &__obj_features );
00110 if ( ! __obj_num_features > 0 ) {
00111 throw Exception("Could not compute object features");
00112 }
00113 std::cout << "SiftClassifier(classify): computed '" << __obj_num_features << "' features from object" << std::endl;
00114
00115
00116 __tt->ping_end(__ttc_objfeat);
00117
00118
00119
00120 __image = cvCreateImage(cvSize(pixel_width, pixel_height), IPL_DEPTH_8U, 3);
00121
00122 }
00123
00124
00125
00126 SiftClassifier::~SiftClassifier()
00127 {
00128
00129 cvReleaseImage(&__obj_img);
00130 cvReleaseImage(&__image);
00131 }
00132
00133
00134 std::list< ROI > *
00135 SiftClassifier::classify()
00136 {
00137
00138 __tt->ping_start(0);
00139
00140
00141
00142 std::list< ROI > *rv = new std::list< ROI >();
00143
00144 struct feature * feat;
00145 struct feature** nbrs;
00146 struct kd_node* kd_root;
00147 CvPoint pt1, pt2;
00148
00149
00150 CvPoint ftpt;
00151 std::vector< CvPoint > ftlist;
00152
00153 int x_min = _width;
00154 int y_min = _height;
00155 int x_max = 0;
00156 int y_max = 0;
00157
00158 double d0, d1;
00159 int k, m = 0;
00160
00161
00162 __tt->ping_start(__ttc_imgconv);
00163
00164
00165 convert(YUV422_PLANAR, BGR, _src, (unsigned char *)__image->imageData, _width, _height);
00166
00167 __tt->ping_end(__ttc_imgconv);
00168
00169
00170
00171 __tt->ping_start(__ttc_imgfeat);
00172
00173
00174 int num_img_ft = sift_features( __image, &__img_features );
00175 kd_root = kdtree_build( __img_features, num_img_ft );
00176
00177 __tt->ping_end(__ttc_imgfeat);
00178
00179
00180 if( ! kd_root ) {
00181 std::cerr << "SiftClassifier(classify): KD-Root NULL!" << std::endl;
00182 }
00183
00184
00185 __tt->ping_start(__ttc_matchin);
00186
00187 std::cout << "SiftClassifier(classify): matching ..." << std::endl;
00188 for( int i = 0; i < __obj_num_features; ++i ) {
00189
00190 feat = __obj_features + i;
00191 k = kdtree_bbf_knn( kd_root, feat, 2, &nbrs, __kdtree_bbf_max_nn_chks );
00192 if( k == 2 )
00193 {
00194 d0 = descr_dist_sq( feat, nbrs[0] );
00195 d1 = descr_dist_sq( feat, nbrs[1] );
00196 if( d0 < d1 * __nn_sq_dist_ratio_thr )
00197 {
00198 pt1 = cvPoint( cvRound( feat->x ), cvRound( feat->y ) );
00199 pt2 = cvPoint( cvRound( nbrs[0]->x ), cvRound( nbrs[0]->y ) );
00200 m++;
00201 __obj_features[i].fwd_match = nbrs[0];
00202
00203 ftpt = cvPoint( cvRound( nbrs[0]->x), cvRound( nbrs[0]->y ) );
00204 ftlist.push_back(ftpt);
00205
00206 ROI r( pt2.x-5, pt2.y-5, 11, 11, _width, _height);
00207 rv->push_back(r);
00208 }
00209 }
00210 free( nbrs );
00211 }
00212 std::cout << "SiftClassifier(classify): found '" << m << "' matches" << std::endl;
00213 kdtree_release( kd_root );
00214
00215 __tt->ping_end(__ttc_matchin);
00216
00217
00218
00219 __tt->ping_start(__ttc_roimerg);
00220
00221 std::cout << "SiftClassifier(classify): computing ROI" << std::endl;
00222
00223 for ( std::vector< CvPoint >::size_type i = 0; i < ftlist.size(); ++i) {
00224 if( ftlist[i].x < x_min )
00225 x_min = ftlist[i].x;
00226 if( ftlist[i].y < y_min )
00227 y_min = ftlist[i].y;
00228 if( ftlist[i].x > x_max )
00229 x_max = ftlist[i].x;
00230 if( ftlist[i].y > y_max )
00231 y_max = ftlist[i].y;
00232 }
00233 if( m != 0 ) {
00234 ROI r(x_min, y_min, x_max-x_min, y_max-y_min, _width, _height);
00235 rv->push_back(r);
00236 }
00237
00238 __tt->ping_end(__ttc_roimerg);
00239
00240
00241
00242 __tt->ping_end(0);
00243
00244
00245
00246 __tt->print_to_stdout();
00247
00248
00249 std::cout << "SiftClassifier(classify): done ... returning '" << rv->size() << "' ROIs." << std::endl;
00250 return rv;
00251 }