void siftDesctor::covdet_keypoints_and_descriptors(cv::Mat &img, std::vector<std::vector<float>> &frames, std::vector<std::vector<float>> &desctor, bool rootSIFT, bool verbose){ bool display_image = 0; vl_size numCols, numRows; numCols = img.cols; //61 numRows = img.rows; //74 img = (cv::Mat_<float>)img/255.0; // This is for debugging, checking the image was correctly loaded. if (display_image) { std::string window_name = "Image"; namedWindow(window_name, cv::WINDOW_AUTOSIZE );// Create a window for display. imshow(window_name, img); // Show our image inside it. cv::waitKey(0); // Wait for a keystroke in the window } cv::Mat imageTest(img.rows, img.cols, CV_32FC1); cv::Mat imgT(img.cols, img.rows, CV_32FC1); img.copyTo(imageTest); imgT = img.t(); imgT = imgT.reshape(1,1); //std::cout << imgT << std::endl; float *image = new float[(int)imgT.cols]; for(int i = 0; i < imgT.cols; i++){ image[i] = (float)imgT.at<float>(i); //std::cout << image[i] << " "; } typedef enum _VlCovDetDescriptorType{ VL_COVDET_DESC_SIFT } VlCovDetDescriporType; VlCovDetMethod method = VL_COVDET_METHOD_DOG; //vl_bool estimateAffineShape = VL_FALSE; //vl_bool estimateOrientation = VL_FALSE; vl_bool doubleImage = VL_TRUE; vl_index octaveResolution = -1; double edgeThreshold = 10; double peakThreshold = 0.01; double lapPeakThreshold = -1; int descriptorType = -1; vl_index patchResolution = -1; double patchRelativeExtent = -1; double patchRelativeSmoothing = -1; double boundaryMargin = 2.0; if (descriptorType < 0) descriptorType = VL_COVDET_DESC_SIFT; switch (descriptorType){ case VL_COVDET_DESC_SIFT: if (patchResolution < 0) patchResolution = 15; if (patchRelativeExtent < 0) patchRelativeExtent = 10; if (patchRelativeSmoothing <0) patchRelativeSmoothing = 1; if (verbose){ printf("vl_covdet: VL_COVDET_DESC_SIFT: patchResolution=%lld, patchRelativeExtent=%g, patchRelativeSmoothing=%g\n", patchResolution, patchRelativeExtent, patchRelativeSmoothing); } } if (1) { //clock_t t_start = clock(); // create a detector object: VL_COVDET_METHOD_HESSIAN VlCovDet * covdet = vl_covdet_new(method); // set various parameters (optional) vl_covdet_set_transposed(covdet, VL_TRUE); vl_covdet_set_first_octave(covdet, doubleImage? -1 : 0); if (octaveResolution >= 0) vl_covdet_set_octave_resolution(covdet, octaveResolution); if (peakThreshold >= 0) vl_covdet_set_peak_threshold(covdet, peakThreshold); if (edgeThreshold >= 0) vl_covdet_set_edge_threshold(covdet, edgeThreshold); if (lapPeakThreshold >= 0) vl_covdet_set_laplacian_peak_threshold(covdet, lapPeakThreshold); //vl_covdet_set_target_num_features(covdet, target_num_features); //vl_covdet_set_use_adaptive_suppression(covdet, use_adaptive_suppression); if(verbose){ VL_PRINTF("vl_covdet: doubling image: %s, image size: numRows = %d, numCols = %d\n", VL_YESNO(vl_covdet_get_first_octave(covdet) < 0), numCols, numRows); } // process the image and run the detector, im.shape(1) is column, im.shape(0) is row //see http://www.vlfeat.org/api/covdet_8h.html#affcedda1fdc7ed72d223e0aab003024e for detail vl_covdet_put_image(covdet, image, numRows, numCols); if (verbose) { VL_PRINTF("vl_covdet: detector: %s\n", vl_enumeration_get_by_value(vlCovdetMethods, method)->name); VL_PRINTF("vl_covdet: peak threshold: %g, edge threshold: %g\n", vl_covdet_get_peak_threshold(covdet),vl_covdet_get_edge_threshold(covdet)); } vl_covdet_detect(covdet); if (verbose) { vl_size numFeatures = vl_covdet_get_num_features(covdet) ; VL_PRINTF("vl_covdet: %d features suppressed as duplicate (threshold: %g)\n", vl_covdet_get_num_non_extrema_suppressed(covdet), vl_covdet_get_non_extrema_suppression_threshold(covdet)); VL_PRINTF("vl_covdet: detected %d features", numFeatures); } //drop feature on the margin(optimal) if(boundaryMargin > 0){ vl_covdet_drop_features_outside(covdet, boundaryMargin); if(verbose){ vl_size numFeatures = vl_covdet_get_num_features(covdet); VL_PRINTF("vl_covdet: kept %d inside the boundary margin (%g)\n", numFeatures, boundaryMargin); } } /* affine adaptation if needed */ bool estimateAffineShape = true; if (estimateAffineShape) { if (verbose) { vl_size numFeaturesBefore = vl_covdet_get_num_features(covdet) ; VL_PRINTF("vl_covdet: estimating affine shape for %d features", numFeaturesBefore); } vl_covdet_extract_affine_shape(covdet) ; if (verbose) { vl_size numFeaturesAfter = vl_covdet_get_num_features(covdet) ; VL_PRINTF("vl_covdet: %d features passed affine adaptation\n", numFeaturesAfter); } } // compute the orientation of the features (optional) //vl_covdet_extract_orientations(covdet); // get feature descriptors vl_size numFeatures = vl_covdet_get_num_features(covdet); VlCovDetFeature const * feature = (VlCovDetFeature const *)vl_covdet_get_features(covdet); VlSiftFilt * sift = vl_sift_new(16, 16, 1, 3, 0); vl_size patchSide = 2 * patchResolution + 1; double patchStep = (double)patchRelativeExtent / patchResolution; float tempDesc[128]; //float * desc; if (verbose) { VL_PRINTF("vl_covdet: descriptors: type = sift, resolution = %d, extent = %g, smoothing = %g\n", patchResolution,patchRelativeExtent, patchRelativeSmoothing); } //std::vector<float> points(6 * numFeatures); //std::vector<float> desc(dimension * numFeatures); std::vector<float> desc(128); std::vector<float> frame(6); //std::vector<float> patch(patchSide * patchSide); //std::vector<float> patchXY(2 * patchSide * patchSide); float *patch = (float*)malloc(sizeof(float)*patchSide*patchSide); float *patchXY = (float*)malloc(2*sizeof(float)*patchSide*patchSide); vl_sift_set_magnif(sift, 3.0); for (vl_index i = 0; i < (signed)numFeatures; i++) { frame.clear(); frame.push_back(feature[i].frame.y); frame.push_back(feature[i].frame.x); frame.push_back(feature[i].frame.a22); frame.push_back(feature[i].frame.a12); frame.push_back(feature[i].frame.a21); frame.push_back(feature[i].frame.a11); frames.push_back(frame); //std::cout << std::setiosflags(std::ios::fixed); //std::cout << std::setprecision(6) << feature[i].frame.y << ", " << feature[i].frame.x << ", " << feature[i].frame.a22 << ", "<< feature[i].frame.a12 << ", "<< feature[i].frame.a21 << ", " << feature[i].frame.a11 << ", "<< std::endl; vl_covdet_extract_patch_for_frame(covdet, patch, patchResolution, patchRelativeExtent, patchRelativeSmoothing, feature[i].frame); vl_imgradient_polar_f(patchXY, patchXY+1, 2, 2 * patchSide, patch, patchSide, patchSide, patchSide); vl_sift_calc_raw_descriptor(sift, patchXY, tempDesc, (int)patchSide, (int)patchSide, (double)(patchSide - 1) / 2, (double)(patchSide - 1) / 2, (double)patchRelativeExtent / (3.0 * (4 + 1) / 2) / patchStep, VL_PI / 2); flip_descriptor(desc, tempDesc); // sift or rootsift if(rootSIFT == true){ std::vector<float> rootdesc = rootsift(desc); desctor.push_back(rootdesc); }else{ desctor.push_back(desc); } /*std::cout << std::setiosflags(std::ios::fixed); for(vl_index j = 0; j < 128; j++){ std::cout << std::setprecision(6) << desc[j] << " "; } std::cout << "\n" << std::endl;*/ } vl_sift_delete(sift); vl_covdet_delete(covdet); //delete covdet; delete patch; delete patchXY; } }
//Two pass flood fill to make sure points are ordered //this is robust to loop! //there must be no junctions std::vector< CvPoint> floodfill(CvPoint seed, uint8 edgC, uint8 bckV, IplImage* img) { Image<uint8> imgT(img); std::vector<CvPoint> vPt; uint8 bckV2 = bckV+10; uint8 s = imgT[seed.y][seed.x]; if (s != edgC) //not an edge return vPt; vPt.push_back(seed); imgT[seed.y][seed.x] = bckV2; uint i =0; uint lastPush=0; uint lastPushPrev=0; //pass one: this is just a naive floodfill while (true) { CvPoint p_curr = vPt[i]; CvPoint p = p_curr; for (int x=-1;x<=1;x++) { for (int y=-1;y<=1;y++) { p.x=p_curr.x+x; p.y=p_curr.y+y; //printf("%d %d\n", p.x,p.y); //s = cvGet2D(img,p.y,p.x); s = imgT[p.y][p.x]; if (s==edgC) { vPt.push_back(p); //cvSet2D(img,p.y,p.x, bckV2); imgT[p.y][p.x] = bckV2; lastPushPrev = i; lastPush = vPt.size()-1; } } } i++; if (i==vPt.size()) break; } if (vPt.size() < 3) return vPt; CvPoint p1 = vPt[lastPush]; //this the last push on the stack CvPoint p2 = vPt[lastPushPrev]; //this the connected pixel to this last push imgT[p1.y][p1.x] = bckV; imgT[p2.y][p2.x] = bckV; vPt.clear(); //reset list vPt.push_back(p1); //going reverse, this is the new beginning vPt.push_back(p2); //go to next and make sure we go in the right direction i=1; //pass two start from the ending: that will make sure the data are sorted while (true) { CvPoint p_curr = vPt[i]; CvPoint p = p_curr; for (int x=-1;x<=1;x++) { for (int y=-1;y<=1;y++) { p.x=p_curr.x+x; p.y=p_curr.y+y; s = imgT[p.y][p.x]; // cvGet2D(img,p.y,p.x); if (s==bckV2) { vPt.push_back(p); imgT[p.y][p.x] = bckV; //cvSet2D(img,p.y,p.x, bckV); } } } i++; if (i>=vPt.size()) break; } // printf("%d \n-------------\n", vPt.size() ); // for (int i=0;i<vPt.size()-1; i++) // { // CvPoint p1 = vPt[i]; // CvPoint p2 = vPt[i+1]; // double dist = sqrt(pow(p1.x-p2.x,2)+pow(p1.y-p2.y,2)); // //if (dist > 2) // printf("%d %d -> %f\n", i,i+1,dist); // } return vPt; }