void mexFunction(int nout, mxArray *out[], int nin, const mxArray *in[]) { int verbose = 0 ; char buffer [1024] ; int unsigned const bufferSize = sizeof(buffer)/sizeof(buffer[0]) ; int opt ; int next = 0 ; mxArray const *optarg ; VL_USE_MATLAB_ENV ; if (nout > 1) { vlmxError(vlmxErrTooManyOutputArguments, NULL) ; } while ((opt = vlmxNextOption (in, nin, options, &next, &optarg)) >= 0) { switch (opt) { case opt_verbose : ++ verbose ; break ; default: abort() ; } } if (verbose) { int offset = 0 ; char * string = vl_configuration_to_string_copy() ; offset = vl_string_copy(buffer, bufferSize, string) ; snprintf(buffer + offset, bufferSize - offset, " SIMD enabled: %s\n", VL_YESNO(vl_get_simd_enabled())) ; if(string) vl_free(string) ; } else { snprintf(buffer, sizeof(buffer)/sizeof(buffer[0]), "%s", VL_VERSION_STRING) ; } if (nout == 0) { mexPrintf("%s\n", buffer) ; } else { out[0] = mxCreateString(buffer) ; } }
VL_EXPORT char * vl_configuration_to_string_copy () { char * string = 0 ; int length = 0 ; char * staticString = vl_static_configuration_to_string_copy() ; char * cpuString = #if defined(VL_ARCH_IX86) || defined(VL_ARCH_X64) || defined(VL_ARCH_IA64) _vl_x86cpu_info_to_string_copy(&vl_get_state()->cpuInfo) ; #else "Generic CPU" ; #endif #if defined(DEBUG) int const debug = 1 ; #else int const debug = 0 ; #endif while (string == 0) { if (length > 0) { string = vl_malloc(sizeof(char) * length) ; if (string == NULL) break ; } length = snprintf(string, length, "VLFeat version %s\n" " Static config: %s\n" " %d CPU(s): %s\n" " Debug: %s\n", vl_get_version_string (), staticString, vl_get_num_cpus(), cpuString, VL_YESNO(debug)) ; length += 1 ; } if (staticString) vl_free(staticString) ; if (cpuString) vl_free(cpuString) ; return string ; }
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; } }
void mexFunction(int nout, mxArray *out[], int nin, const mxArray *in[]) { enum {IN_I = 0, IN_END} ; enum {OUT_FRAMES=0, OUT_DESCRIPTORS, OUT_INFO, OUT_END} ; int verbose = 0 ; int opt ; int next = IN_END ; mxArray const *optarg ; VlEnumerator *pair ; float const *image ; vl_size numCols, numRows ; 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 = -1 ; double peakThreshold = -1 ; double lapPeakThreshold = -1 ; int descriptorType = -1 ; vl_index patchResolution = -1 ; double patchRelativeExtent = -1 ; double patchRelativeSmoothing = -1 ; float *patch = NULL ; float *patchXY = NULL ; vl_int liopNumSpatialBins = 6; vl_int liopNumNeighbours = 4; float liopRadius = 6.0; float liopIntensityThreshold = VL_NAN_F ; double boundaryMargin = 2.0 ; double * userFrames = NULL ; vl_size userFrameDimension = 0 ; vl_size numUserFrames = 0 ; VL_USE_MATLAB_ENV ; /* ----------------------------------------------------------------- * Check the arguments * -------------------------------------------------------------- */ if (nin < IN_END) { vlmxError(vlmxErrNotEnoughInputArguments, 0) ; } else if (nout > OUT_END) { vlmxError(vlmxErrTooManyOutputArguments, 0) ; } if (mxGetNumberOfDimensions(IN(I)) != 2 || mxGetClassID(IN(I)) != mxSINGLE_CLASS){ vlmxError(vlmxErrInvalidArgument, "I must be a matrix of class SINGLE.") ; } image = (float*) mxGetData(IN(I)) ; numRows = mxGetM(IN(I)) ; numCols = mxGetN(IN(I)) ; while ((opt = vlmxNextOption (in, nin, options, &next, &optarg)) >= 0) { switch (opt) { case opt_verbose : ++ verbose ; break ; case opt_method: pair = vlmxDecodeEnumeration(optarg, vlCovdetMethods, VL_TRUE) ; if (pair == NULL) { vlmxError(vlmxErrInvalidArgument, "METHOD is not a supported detection method.") ; } method = (VlCovDetMethod)pair->value ; break; case opt_descriptor: pair = vlmxDecodeEnumeration(optarg, vlCovDetDescriptorTypes, VL_TRUE) ; if (pair == NULL) { vlmxError(vlmxErrInvalidArgument, "DESCRIPTOR is not a supported descriptor.") ; } descriptorType = (VlCovDetDescriptorType)pair->value ; break; case opt_estimate_affine_shape: if (!mxIsLogicalScalar(optarg)) { vlmxError(vlmxErrInvalidArgument, "ESTIMATEAFFINESHAPE must be a logical scalar value.") ; } else { estimateAffineShape = *mxGetLogicals(optarg) ; } break ; case opt_estimate_orientation: if (!mxIsLogicalScalar(optarg)) { vlmxError(vlmxErrInvalidArgument, "ESTIMATEORIENTATION must be a logical scalar value.") ; } else { estimateOrientation = *mxGetLogicals(optarg); } break ; case opt_double_image: if (!mxIsLogicalScalar(optarg)) { vlmxError(vlmxErrInvalidArgument, "DOUBLEIMAGE must be a logical scalar value.") ; } else { doubleImage = *mxGetLogicals(optarg); } break ; case opt_octave_resolution : if (!vlmxIsPlainScalar(optarg) || (octaveResolution = (vl_index)*mxGetPr(optarg)) < 1) { vlmxError(vlmxErrInvalidArgument, "OCTAVERESOLUTION must be an integer not smaller than 1.") ; } break ; case opt_edge_threshold : if (!vlmxIsPlainScalar(optarg) || (edgeThreshold = *mxGetPr(optarg)) < 1) { vlmxError(vlmxErrInvalidArgument, "EDGETHRESHOLD must be a real not smaller than 1.") ; } break ; case opt_peak_threshold : if (!vlmxIsPlainScalar(optarg) || (peakThreshold = *mxGetPr(optarg)) < 0) { vlmxError(vlmxErrInvalidArgument, "PEAKTHRESHOLD must be a non-negative real.") ; } break ; case opt_laplacian_peak_threshold : if (!vlmxIsPlainScalar(optarg) || (lapPeakThreshold = *mxGetPr(optarg)) < 0) { vlmxError(vlmxErrInvalidArgument, "LAPLACIANPEAKTHRESHOLD must be a non-negative real.") ; } break ; case opt_patch_relative_smoothing : if (!vlmxIsPlainScalar(optarg) || (patchRelativeSmoothing = *mxGetPr(optarg)) < 0) { vlmxError(vlmxErrInvalidArgument, "PATCHRELATIVESMOOTHING must be a non-negative real.") ; } break ; case opt_patch_relative_extent : if (!vlmxIsPlainScalar(optarg) || (patchRelativeExtent = *mxGetPr(optarg)) <= 0) { vlmxError(vlmxErrInvalidArgument, "PATCHRELATIVEEXTENT must be a posiive real.") ; } break ; case opt_patch_resolution : if (!vlmxIsPlainScalar(optarg) || (patchResolution = (vl_index)*mxGetPr(optarg)) <= 0) { vlmxError(vlmxErrInvalidArgument, "PATCHRESOLUTION must be a positive integer.") ; } break ; case opt_liop_bins : if (!vlmxIsPlainScalar(optarg) || (liopNumSpatialBins = (vl_int)*mxGetPr(optarg)) <= 0) { vlmxError(vlmxErrInvalidArgument, "number of LIOPNUMSPATIALBINS is not a positive scalar.") ; } break ; case opt_liop_neighbours : if (!vlmxIsPlainScalar(optarg) || (liopNumNeighbours = (vl_int)*mxGetPr(optarg)) <= 0) { vlmxError(vlmxErrInvalidArgument, "number of LIOPNUMNEIGHBOURS is not a positive scalar.") ; } break ; case opt_liop_radius : if (!vlmxIsPlainScalar(optarg) || (liopRadius = (float)*mxGetPr(optarg)) <= 0) { vlmxError(vlmxErrInvalidArgument, "LIOPRADIUS must is not a positive scalar.") ; } break ; case opt_liop_threshold : if (!vlmxIsPlainScalar(optarg)) { vlmxError(vlmxErrInvalidArgument, "LIOPINTENSITYTHRESHOLD is not a scalar.") ; } liopIntensityThreshold = *mxGetPr(optarg) ; break ; case opt_frames: if (!vlmxIsPlainMatrix(optarg,-1,-1)) { vlmxError(vlmxErrInvalidArgument, "FRAMES must be a palin matrix.") ; } numUserFrames = mxGetN (optarg) ; userFrameDimension = mxGetM (optarg) ; userFrames = mxGetPr (optarg) ; switch (userFrameDimension) { case 2: case 3: case 4: case 5: case 6: /* ok */ break ; default: vlmxError(vlmxErrInvalidArgument, "FRAMES of dimensions %d are not recognised", userFrameDimension); ; } break ; default : abort() ; } } if (descriptorType < 0) descriptorType = VL_COVDET_DESC_SIFT ; switch (descriptorType) { case VL_COVDET_DESC_NONE : break ; case VL_COVDET_DESC_PATCH : if (patchResolution < 0) patchResolution = 20 ; if (patchRelativeExtent < 0) patchRelativeExtent = 6 ; if (patchRelativeSmoothing < 0) patchRelativeSmoothing = 1 ; break ; case VL_COVDET_DESC_SIFT : /* the patch parameters are selected to match the SIFT descriptor geometry */ if (patchResolution < 0) patchResolution = 15 ; if (patchRelativeExtent < 0) patchRelativeExtent = 7.5 ; if (patchRelativeSmoothing < 0) patchRelativeSmoothing = 1 ; break ; case VL_COVDET_DESC_LIOP : if (patchResolution < 0) patchResolution = 20 ; if (patchRelativeExtent < 0) patchRelativeExtent = 4 ; if (patchRelativeSmoothing < 0) patchRelativeSmoothing = 0.5 ; break ; } if (patchResolution > 0) { vl_size w = 2*patchResolution + 1 ; patch = mxMalloc(sizeof(float) * w * w); patchXY = mxMalloc(2 * sizeof(float) * w * w); } if (descriptorType == VL_COVDET_DESC_LIOP && liopRadius > patchResolution) { vlmxError(vlmxErrInconsistentData, "LIOPRADIUS is larger than PATCHRESOLUTION.") ; } /* ----------------------------------------------------------------- * Detector * -------------------------------------------------------------- */ { VlCovDet * covdet = vl_covdet_new(method) ; /* set covdet parameters */ 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) ; if (verbose) { VL_PRINTF("vl_covdet: doubling image: %s\n", VL_YESNO(vl_covdet_get_first_octave(covdet) < 0)) ; } /* process the image */ vl_covdet_put_image(covdet, image, numRows, numCols) ; /* fill with frames: eitehr run the detector of poure them in */ if (numUserFrames > 0) { vl_index k ; if (verbose) { mexPrintf("vl_covdet: sourcing %d frames\n", numUserFrames) ; } for (k = 0 ; k < (signed)numUserFrames ; ++k) { double const * uframe = userFrames + userFrameDimension * k ; double a11, a21, a12, a22 ; VlCovDetFeature feature ; feature.peakScore = VL_INFINITY_F ; feature.edgeScore = 1.0 ; feature.frame.x = (float)uframe[1] - 1 ; feature.frame.y = (float)uframe[0] - 1 ; switch (userFrameDimension) { case 2: a11 = 1.0 ; a21 = 0.0 ; a12 = 0.0 ; a22 = 1.0 ; break ; case 3: a11 = uframe[2] ; a21 = 0.0 ; a12 = 0.0 ; a22 = uframe[2] ; break ; case 4: { double sigma = uframe[2] ; double c = cos(uframe[3]) ; double s = sin(uframe[3]) ; a11 = sigma * c ; a21 = sigma * s ; a12 = sigma * (-s) ; a22 = sigma * c ; break ; } case 5: { double d2 ; if (uframe[2] < 0) { vlmxError(vlmxErrInvalidArgument, "FRAMES(:,%d) does not have a PSD covariance.", k+1) ; } a11 = sqrt(uframe[2]) ; a21 = uframe[3] / VL_MAX(a11, 1e-10) ; a12 = 0.0 ; d2 = uframe[4] - a21*a21 ; if (d2 < 0) { vlmxError(vlmxErrInvalidArgument, "FRAMES(:,%d) does not have a PSD covariance.", k+1) ; } a22 = sqrt(d2) ; break ; } case 6: { a11 = uframe[2] ; a21 = uframe[3] ; a12 = uframe[4] ; a22 = uframe[5] ; break ; } default: a11 = 0 ; a21 = 0 ; a12 = 0 ; a22 = 0 ; assert(0) ; } feature.frame.a11 = (float)a22 ; feature.frame.a21 = (float)a12 ; feature.frame.a12 = (float)a21 ; feature.frame.a22 = (float)a11 ; vl_covdet_append_feature(covdet, &feature) ; } } else { if (verbose) { mexPrintf("vl_covdet: detector: %s\n", vl_enumeration_get_by_value(vlCovdetMethods, method)->name) ; mexPrintf("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_index i ; vl_size numFeatures = vl_covdet_get_num_features(covdet) ; mexPrintf("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)) ; switch (method) { case VL_COVDET_METHOD_HARRIS_LAPLACE: case VL_COVDET_METHOD_HESSIAN_LAPLACE: { vl_size numScales ; vl_size const * numFeaturesPerScale ; numFeaturesPerScale = vl_covdet_get_laplacian_scales_statistics (covdet, &numScales) ; mexPrintf("vl_covdet: Laplacian scales:") ; for (i = 0 ; i <= (signed)numScales ; ++i) { mexPrintf("%d with %d scales;", numFeaturesPerScale[i], i) ; } mexPrintf("\n") ; } break ; default: break ; } mexPrintf("vl_covdet: detected %d features\n", numFeatures) ; } if (boundaryMargin > 0) { vl_covdet_drop_features_outside (covdet, boundaryMargin) ; if (verbose) { vl_size numFeatures = vl_covdet_get_num_features(covdet) ; mexPrintf("vl_covdet: kept %d inside the boundary margin (%g)\n", numFeatures, boundaryMargin) ; } } } /* affine adaptation if needed */ if (estimateAffineShape) { if (verbose) { vl_size numFeaturesBefore = vl_covdet_get_num_features(covdet) ; mexPrintf("vl_covdet: estimating affine shape for %d features\n", numFeaturesBefore) ; } vl_covdet_extract_affine_shape(covdet) ; if (verbose) { vl_size numFeaturesAfter = vl_covdet_get_num_features(covdet) ; mexPrintf("vl_covdet: %d features passed affine adaptation\n", numFeaturesAfter) ; } } /* orientation estimation if needed */ if (estimateOrientation) { vl_size numFeaturesBefore = vl_covdet_get_num_features(covdet) ; vl_size numFeaturesAfter ; vl_covdet_extract_orientations(covdet) ; numFeaturesAfter = vl_covdet_get_num_features(covdet) ; if (verbose && numFeaturesAfter > numFeaturesBefore) { mexPrintf("vl_covdet: %d duplicate features were crated due to ambiguous " "orientation detection (%d total)\n", numFeaturesAfter - numFeaturesBefore, numFeaturesAfter) ; } } /* store results back */ { vl_index i ; vl_size numFeatures = vl_covdet_get_num_features(covdet) ; VlCovDetFeature const * feature = vl_covdet_get_features(covdet); double * pt ; OUT(FRAMES) = mxCreateDoubleMatrix (6, numFeatures, mxREAL) ; pt = mxGetPr(OUT(FRAMES)) ; for (i = 0 ; i < (signed)numFeatures ; ++i) { /* save the transposed frame, adjust origin to MATLAB's*/ *pt++ = feature[i].frame.y + 1 ; *pt++ = feature[i].frame.x + 1 ; *pt++ = feature[i].frame.a22 ; *pt++ = feature[i].frame.a12 ; *pt++ = feature[i].frame.a21 ; *pt++ = feature[i].frame.a11 ; } } if (nout >= 2) { switch (descriptorType) { case VL_COVDET_DESC_NONE: OUT(DESCRIPTORS) = mxCreateDoubleMatrix(0,0,mxREAL); break ; case VL_COVDET_DESC_PATCH: { vl_size numFeatures ; VlCovDetFeature const * feature ; vl_index i ; vl_size w = 2*patchResolution + 1 ; float * desc ; if (verbose) { mexPrintf("vl_covdet: descriptors: type=patch, " "resolution=%d, extent=%g, smoothing=%g\n", patchResolution, patchRelativeExtent, patchRelativeSmoothing); } numFeatures = vl_covdet_get_num_features(covdet) ; feature = vl_covdet_get_features(covdet); OUT(DESCRIPTORS) = mxCreateNumericMatrix(w*w, numFeatures, mxSINGLE_CLASS, mxREAL) ; desc = mxGetData(OUT(DESCRIPTORS)) ; for (i = 0 ; i < (signed)numFeatures ; ++i) { vl_covdet_extract_patch_for_frame(covdet, desc, patchResolution, patchRelativeExtent, patchRelativeSmoothing, feature[i].frame) ; desc += w*w ; } break ; } case VL_COVDET_DESC_SIFT: { vl_size numFeatures = vl_covdet_get_num_features(covdet) ; VlCovDetFeature const * feature = vl_covdet_get_features(covdet); VlSiftFilt * sift = vl_sift_new(16, 16, 1, 3, 0) ; vl_index i ; vl_size dimension = 128 ; vl_size patchSide = 2 * patchResolution + 1 ; double patchStep = (double)patchRelativeExtent / patchResolution ; float tempDesc [128] ; float * desc ; if (verbose) { mexPrintf("vl_covdet: descriptors: type=sift, " "resolution=%d, extent=%g, smoothing=%g\n", patchResolution, patchRelativeExtent, patchRelativeSmoothing); } OUT(DESCRIPTORS) = mxCreateNumericMatrix(dimension, numFeatures, mxSINGLE_CLASS, mxREAL) ; desc = mxGetData(OUT(DESCRIPTORS)) ; vl_sift_set_magnif(sift, 3.0) ; for (i = 0 ; i < (signed)numFeatures ; ++i) { 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) ; /* Note: the patch is transposed, so that x and y are swapped. However, if NBO is not divisible by 4, then the configuration of the SIFT orientations is not symmetric by rotations of pi/2. Hence the only option is to rotate the descriptor further by an angle we need to compute the descriptor rotaed by an additional pi/2 angle. In this manner, x concides and y is flipped. */ 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) ; desc += dimension ; } vl_sift_delete(sift) ; break ; } case VL_COVDET_DESC_LIOP : { /* TODO: get parameters form input */ vl_size numFeatures = vl_covdet_get_num_features(covdet) ; vl_size dimension ; VlCovDetFeature const * feature = vl_covdet_get_features(covdet); vl_index i ; vl_size patchSide = 2 * patchResolution + 1 ; float * desc ; VlLiopDesc * liop = vl_liopdesc_new(liopNumNeighbours, liopNumSpatialBins, liopRadius, (vl_size)patchSide) ; if (!vl_is_nan_f(liopIntensityThreshold)) { vl_liopdesc_set_intensity_threshold(liop, liopIntensityThreshold) ; } dimension = vl_liopdesc_get_dimension(liop) ; if (verbose) { mexPrintf("vl_covdet: descriptors: type=liop, " "resolution=%d, extent=%g, smoothing=%g\n", patchResolution, patchRelativeExtent, patchRelativeSmoothing); } OUT(DESCRIPTORS) = mxCreateNumericMatrix(dimension, numFeatures, mxSINGLE_CLASS, mxREAL); desc = mxGetData(OUT(DESCRIPTORS)) ; vl_tic(); for(i = 0; i < (signed)numFeatures; i++){ vl_covdet_extract_patch_for_frame(covdet, patch, patchResolution, patchRelativeExtent, patchRelativeSmoothing, feature[i].frame); vl_liopdesc_process(liop, desc, patch); desc += dimension; } mexPrintf("time: %f\n",vl_toc()); mexPrintf("threshold: %f\n",liop->intensityThreshold); break; } default: assert(0) ; /* descriptor type */ } } if (nout >= 3) { vl_index i ; vl_size numFeatures = vl_covdet_get_num_features(covdet) ; VlCovDetFeature const * feature = vl_covdet_get_features(covdet); const char* names[] = { "gss", "css", "peakScores", "edgeScores", "orientationScore", "laplacianScaleScore" }; mxArray * gss_array = _createArrayFromScaleSpace(vl_covdet_get_gss(covdet)) ; mxArray * css_array = _createArrayFromScaleSpace(vl_covdet_get_css(covdet)) ; mxArray * peak_array = mxCreateNumericMatrix(1,numFeatures,mxSINGLE_CLASS,mxREAL) ; mxArray * edge_array = mxCreateNumericMatrix(1,numFeatures,mxSINGLE_CLASS,mxREAL) ; mxArray * orientation_array = mxCreateNumericMatrix(1,numFeatures,mxSINGLE_CLASS,mxREAL) ; mxArray * laplacian_array = mxCreateNumericMatrix(1,numFeatures,mxSINGLE_CLASS,mxREAL) ; float * peak = mxGetData(peak_array) ; float * edge = mxGetData(edge_array) ; float * orientation = mxGetData(orientation_array) ; float * laplacian = mxGetData(laplacian_array) ; for (i = 0 ; i < (signed)numFeatures ; ++i) { peak[i] = feature[i].peakScore ; edge[i] = feature[i].edgeScore ; orientation[i] = feature[i].orientationScore ; laplacian[i] = feature[i].laplacianScaleScore ; } OUT(INFO) = mxCreateStructMatrix(1, 1, 6, names) ; mxSetFieldByNumber(OUT(INFO), 0, 0, gss_array) ; mxSetFieldByNumber(OUT(INFO), 0, 1, css_array) ; mxSetFieldByNumber(OUT(INFO), 0, 2, peak_array) ; mxSetFieldByNumber(OUT(INFO), 0, 3, edge_array) ; mxSetFieldByNumber(OUT(INFO), 0, 4, orientation_array) ; mxSetFieldByNumber(OUT(INFO), 0, 5, laplacian_array) ; } /* cleanup */ vl_covdet_delete (covdet) ; } if (patchXY) mxFree(patchXY) ; if (patch) mxFree(patch) ; }
/* driver */ void mexFunction (int nout VL_UNUSED, mxArray * out[], int nin, const mxArray * in[]) { enum {IN_DATA = 0, IN_MEANS, IN_COVARIANCES, IN_PRIORS, IN_END} ; enum {OUT_ENC} ; int opt ; int next = IN_END ; mxArray const *optarg ; vl_size numClusters = 10; vl_size dimension ; vl_size numData ; int flags = 0 ; void * covariances = NULL; void * means = NULL; void * priors = NULL; void * data = NULL ; int verbosity = 0 ; vl_type dataType ; mxClassID classID ; VL_USE_MATLAB_ENV ; /* ----------------------------------------------------------------- * Check the arguments * -------------------------------------------------------------- */ if (nin < 4) { vlmxError (vlmxErrInvalidArgument, "At least four arguments required."); } if (nout > 1) { vlmxError (vlmxErrInvalidArgument, "At most one output argument."); } classID = mxGetClassID (IN(DATA)) ; switch (classID) { case mxSINGLE_CLASS: dataType = VL_TYPE_FLOAT ; break ; case mxDOUBLE_CLASS: dataType = VL_TYPE_DOUBLE ; break ; default: vlmxError (vlmxErrInvalidArgument, "DATA is neither of class SINGLE or DOUBLE.") ; } if (mxGetClassID (IN(MEANS)) != classID) { vlmxError(vlmxErrInvalidArgument, "MEANS is not of the same class as DATA.") ; } if (mxGetClassID (IN(COVARIANCES)) != classID) { vlmxError(vlmxErrInvalidArgument, "COVARIANCES is not of the same class as DATA.") ; } if (mxGetClassID (IN(PRIORS)) != classID) { vlmxError(vlmxErrInvalidArgument, "PRIORS is not of the same class as DATA.") ; } dimension = mxGetM (IN(DATA)) ; numData = mxGetN (IN(DATA)) ; numClusters = mxGetN (IN(MEANS)) ; if (dimension == 0) { vlmxError (vlmxErrInvalidArgument, "SIZE(DATA,1) is zero.") ; } if (!vlmxIsMatrix(IN(MEANS), dimension, numClusters)) { vlmxError (vlmxErrInvalidArgument, "MEANS is not a matrix or does not have the right size.") ; } if (!vlmxIsMatrix(IN(COVARIANCES), dimension, numClusters)) { vlmxError (vlmxErrInvalidArgument, "COVARIANCES is not a matrix or does not have the right size.") ; } if (!vlmxIsVector(IN(PRIORS), numClusters)) { vlmxError (vlmxErrInvalidArgument, "PRIORS is not a vector or does not have the right size.") ; } if (!vlmxIsMatrix(IN(DATA), dimension, numData)) { vlmxError (vlmxErrInvalidArgument, "DATA is not a matrix or does not have the right size.") ; } while ((opt = vlmxNextOption (in, nin, options, &next, &optarg)) >= 0) { switch (opt) { case opt_verbose : ++ verbosity ; break ; case opt_normalized: flags |= VL_FISHER_FLAG_NORMALIZED ; break ; case opt_square_root: flags |= VL_FISHER_FLAG_SQUARE_ROOT ; break ; case opt_improved: flags |= VL_FISHER_FLAG_IMPROVED ; break ; case opt_fast: flags |= VL_FISHER_FLAG_FAST ; break ; default : abort() ; } } /* ----------------------------------------------------------------- * Do the job * -------------------------------------------------------------- */ data = mxGetPr(IN(DATA)) ; means = mxGetPr(IN(MEANS)) ; covariances = mxGetPr(IN(COVARIANCES)) ; priors = mxGetPr(IN(PRIORS)) ; if (verbosity) { mexPrintf("vl_fisher: num data: %d\n", numData) ; mexPrintf("vl_fisher: num clusters: %d\n", numClusters) ; mexPrintf("vl_fisher: data dimension: %d\n", dimension) ; mexPrintf("vl_fisher: code dimension: %d\n", numClusters * dimension) ; mexPrintf("vl_fisher: normalized: %s\n", VL_YESNO(flags & VL_FISHER_FLAG_NORMALIZED)) ; mexPrintf("vl_fisher: square root: %s\n", VL_YESNO(flags & VL_FISHER_FLAG_SQUARE_ROOT)) ; mexPrintf("vl_fisher: normalized: %s\n", VL_YESNO(flags & VL_FISHER_FLAG_NORMALIZED)) ; mexPrintf("vl_fisher: fast: %s\n", VL_YESNO(flags & VL_FISHER_FLAG_FAST)) ; } /* -------------------------------------------------------------- */ /* Encoding */ /* -------------------------------------------------------------- */ OUT(ENC) = mxCreateNumericMatrix (dimension * numClusters * 2, 1, classID, mxREAL) ; vl_fisher_encode (mxGetData(OUT(ENC)), dataType, means, dimension, numClusters, covariances, priors, data, numData, flags) ; }
void mexFunction(int nout, mxArray *out[], int nin, const mxArray *in[]) { enum {IN_DATA, IN_LABELS, IN_LAMBDA, IN_END} ; enum {OUT_MODEL = 0} ; int verbose = 0 ; int opt ; int next = IN_END ; mxArray const *optarg ; double biasMultiplier = 0 ; double lambda ; void * data ; void * preconditioner = NULL ; vl_size preconditionerDimension = 0 ; mxClassID dataClass ; vl_type dataType ; vl_size numSamples ; vl_size dimension ; vl_size numIterations = 0 ; vl_uindex startingIteration = 1 ; vl_uint32 * permutation = NULL ; vl_size permutationSize = 0 ; VL_USE_MATLAB_ENV ; /* ----------------------------------------------------------------- * Check the arguments * -------------------------------------------------------------- */ if (nin < 3) { vlmxError(vlmxErrInvalidArgument, "At least three arguments are required.") ; } else if (nout > 2) { vlmxError(vlmxErrInvalidArgument, "Too many output arguments."); } dataClass = mxGetClassID(IN(DATA)) ; if (! vlmxIsMatrix (IN(DATA), -1, -1) || ! vlmxIsReal (IN(DATA))) { vlmxError(vlmxErrInvalidArgument, "DATA must be a real matrix.") ; } data = mxGetData (IN(DATA)) ; dimension = mxGetM(IN(DATA)) ; numSamples = mxGetN(IN(DATA)) ; switch (dataClass) { case mxSINGLE_CLASS : dataType = VL_TYPE_FLOAT ; break ; case mxDOUBLE_CLASS : dataType = VL_TYPE_DOUBLE ; break ; default: vlmxError(vlmxErrInvalidArgument, "DATA must be either SINGLE or DOUBLE.") ; } if (mxGetClassID(IN(LABELS)) != mxINT8_CLASS) { vlmxError(vlmxErrInvalidArgument, "LABELS must be INT8.") ; } if (! vlmxIsVector(IN(LABELS), numSamples)) { vlmxError(vlmxErrInvalidArgument, "LABELS is not a vector of dimension compatible with DATA.") ; } if (! vlmxIsPlainScalar(IN(LAMBDA))) { vlmxError(vlmxErrInvalidArgument, "LAMBDA is not a plain scalar.") ; } lambda = *mxGetPr(IN(LAMBDA)) ; while ((opt = vlmxNextOption (in, nin, options, &next, &optarg)) >= 0) { switch (opt) { case opt_bias_multiplier : if (!vlmxIsPlainScalar(optarg)) { vlmxError(vlmxErrInvalidArgument, "BIASMULTIPLIER is not a plain scalar.") ; } biasMultiplier = *mxGetPr(optarg) ; break ; case opt_num_iterations : if (!vlmxIsPlainScalar(optarg)) { vlmxError(vlmxErrInvalidArgument, "NUMITERATIONS is not a plain scalar.") ; } if (*mxGetPr(optarg) < 0) { vlmxError(vlmxErrInvalidArgument, "NUMITERATIONS is negative.") ; } numIterations = (vl_size) *mxGetPr(optarg) ; break ; case opt_starting_iteration : if (!vlmxIsPlainScalar(optarg)) { vlmxError(vlmxErrInvalidArgument, "STARTINGITERATION is not a plain scalar.") ; } if (*mxGetPr(optarg) < 1) { vlmxError(vlmxErrInvalidArgument, "STARTINGITERATION is smaller than 1.") ; } startingIteration = (vl_size) *mxGetPr(optarg) ; break ; case opt_starting_model : if (!vlmxIsVector(optarg, -1) || mxIsComplex(optarg) || !mxIsNumeric(optarg)) { vlmxError(vlmxErrInvalidArgument, "STARTINGMODEL is not a real vector.") ; } OUT(MODEL) = mxDuplicateArray(optarg) ; break ; case opt_permutation : if (!vlmxIsVector(optarg, -1) || mxIsComplex(optarg) || mxGetClassID(optarg) != mxUINT32_CLASS) { vlmxError(vlmxErrInvalidArgument, "PERMUTATION is not a UINT32 vector.") ; } permutationSize = mxGetNumberOfElements(optarg) ; permutation = mxMalloc(sizeof(vl_uint32) * permutationSize) ; { /* adjust indexing */ vl_uint32 const * matlabPermutation = mxGetData(optarg) ; vl_uindex k ; for (k = 0 ; k < permutationSize ; ++k) { permutation[k] = matlabPermutation[k] - 1 ; if (permutation[k] >= numSamples) { vlmxError(vlmxErrInconsistentData, "Permutation indexes out of bounds: PERMUTATION(%d) = %d > %d = number of data samples.", k + 1, permutation[k] + 1, numSamples) ; } } } break ; case opt_preconditioner : if (!vlmxIsVector(optarg, -1) || mxIsComplex(optarg) || !mxIsNumeric(optarg)) { vlmxError(vlmxErrInvalidArgument, "PRECONDITIONER is not a real vector.") ; } if (mxGetClassID(optarg) != dataClass) { vlmxError(vlmxErrInvalidArgument, "PRECODNITIONER storage class does not match the data.") ; } preconditioner = mxGetData(optarg) ; preconditionerDimension = mxGetNumberOfElements(optarg) ; break ; case opt_verbose : ++ verbose ; break ; } } if (preconditioner && preconditionerDimension != (dimension + (biasMultiplier > 0))) { vlmxError(vlmxErrInvalidArgument, "PRECONDITIONER has incompatible dimension.") ; } if (numIterations == 0) { numIterations = (vl_size) 10 / (lambda + 1) ; } if (! OUT(MODEL)) { OUT(MODEL) = mxCreateNumericMatrix(dimension + (biasMultiplier > 0), 1, dataClass, mxREAL) ; } else { if (mxGetClassID(OUT(MODEL)) != dataClass) { vlmxError(vlmxErrInvalidArgument, "STARTINGMODEL is not of the same class of DATA.") ; } if (mxGetNumberOfElements(OUT(MODEL)) != dimension + (biasMultiplier > 0)) { vlmxError(vlmxErrInvalidArgument, "STARTINGMODEL has incompatible dimension.") ; } } if (verbose) { mexPrintf("vl_pegasos: Lambda = %g\n", lambda) ; mexPrintf("vl_pegasos: BiasMultiplier = %g\n", biasMultiplier) ; mexPrintf("vl_pegasos: NumIterations = %d\n", numIterations) ; mexPrintf("vl_pegasos: permutation size = %d\n", permutationSize) ; mexPrintf("vl_pegasos: using preconditioner = %s\n", VL_YESNO(preconditioner)) ; } switch (dataType) { case VL_TYPE_FLOAT : vl_pegasos_train_binary_svm_f((float *)mxGetData(OUT(MODEL)), (float const *)mxGetPr(IN(DATA)), dimension, numSamples, (vl_int8 const *)mxGetData(IN(LABELS)), lambda, biasMultiplier, startingIteration, numIterations, NULL, permutation, permutationSize, (float const*)preconditioner) ; break ; case VL_TYPE_DOUBLE: vl_pegasos_train_binary_svm_d((double *)mxGetData(OUT(MODEL)), (double const *)mxGetData(IN(DATA)), dimension, numSamples, (vl_int8 const *)mxGetData(IN(LABELS)), lambda, biasMultiplier, startingIteration, numIterations, NULL, permutation, permutationSize, (double const *)preconditioner) ; break ; } if (permutation) vl_free(permutation) ; }
void mexFunction(int nout, mxArray *out[], int nin, const mxArray *in[]) { enum {IN_I=0, IN_END} ; enum {OUT_FRAMES=0, OUT_DESCRIPTORS} ; int verbose = 0 ; int opt ; int next = IN_END ; mxArray const *optarg ; float const *data ; int M, N ; int step [2] = {1,1} ; vl_bool norm = 0 ; vl_bool floatDescriptors = VL_FALSE ; vl_bool useFlatWindow = VL_FALSE ; double windowSize = -1.0 ; double *bounds = NULL ; double boundBuffer [4] ; VlDsiftDescriptorGeometry geom ; VL_USE_MATLAB_ENV ; geom.numBinX = 4 ; geom.numBinY = 4 ; geom.numBinT = 8 ; geom.binSizeX = 3 ; geom.binSizeY = 3 ; /* ----------------------------------------------------------------- * Check the arguments * -------------------------------------------------------------- */ if (nin < 1) { vlmxError(vlmxErrNotEnoughInputArguments, NULL) ; } else if (nout > 2) { vlmxError(vlmxErrTooManyOutputArguments, NULL) ; } if (mxGetNumberOfDimensions (in[IN_I]) != 2 || mxGetClassID (in[IN_I]) != mxSINGLE_CLASS ) { vlmxError(vlmxErrInvalidArgument, "I must be a matrix of class SINGLE.") ; } data = (float*) mxGetData (in[IN_I]) ; M = mxGetM (in[IN_I]) ; N = mxGetN (in[IN_I]) ; while ((opt = vlmxNextOption (in, nin, options, &next, &optarg)) >= 0) { switch (opt) { case opt_verbose : ++ verbose ; break ; case opt_fast : useFlatWindow = 1 ; break ; case opt_norm : norm = 1 ; break ; case opt_bounds : if (!vlmxIsPlainVector(optarg, 4)) { mexErrMsgTxt("BOUNDS must be a 4-dimensional vector.") ; } bounds = boundBuffer ; bounds [0] = mxGetPr(optarg)[0] - 1 ; bounds [1] = mxGetPr(optarg)[1] - 1 ; bounds [2] = mxGetPr(optarg)[2] - 1 ; bounds [3] = mxGetPr(optarg)[3] - 1 ; break ; case opt_size : if (!vlmxIsPlainVector(optarg,-1)) { vlmxError(vlmxErrInvalidArgument,"SIZE is not a plain vector.") ; } if (mxGetNumberOfElements(optarg) == 1) { geom.binSizeX = (int) mxGetPr(optarg)[0] ; geom.binSizeY = (int) mxGetPr(optarg)[0] ; } else if (mxGetNumberOfElements(optarg) == 2) { geom.binSizeX = (int) mxGetPr(optarg)[1] ; geom.binSizeY = (int) mxGetPr(optarg)[0] ; } else { vlmxError(vlmxErrInvalidArgument,"SIZE is neither a scalar or a 2D vector.") ; } if (geom.binSizeX < 1 || geom.binSizeY < 1) { vlmxError(vlmxErrInvalidArgument,"SIZE value is invalid.") ; } break ; case opt_step : if (!vlmxIsPlainVector(optarg,-1)) { vlmxError(vlmxErrInvalidArgument,"STEP is not a plain vector.") ; } if (mxGetNumberOfElements(optarg) == 1) { step[0] = (int) mxGetPr(optarg)[0] ; step[1] = (int) mxGetPr(optarg)[0] ; } else if (mxGetNumberOfElements(optarg) == 2) { step[0] = (int) mxGetPr(optarg)[1] ; step[1] = (int) mxGetPr(optarg)[0] ; } else { vlmxError(vlmxErrInvalidArgument,"STEP is neither a scalar or a 2D vector.") ; } if (step[0] < 1 || step[1] < 1) { vlmxError(vlmxErrInvalidArgument,"STEP value is invalid.") ; } break ; case opt_window_size : if (!vlmxIsPlainScalar(optarg) || (windowSize = *mxGetPr(optarg)) < 0) { vlmxError(vlmxErrInvalidArgument,"WINDOWSIZE is not a scalar or it is negative.") ; } break ; case opt_float_descriptors : floatDescriptors = VL_TRUE ; break ; case opt_geometry : if (!vlmxIsPlainVector(optarg,3)) { vlmxError(vlmxErrInvalidArgument, "GEOMETRY is not a 3D vector.") ; } geom.numBinY = (int)mxGetPr(optarg)[0] ; geom.numBinX = (int)mxGetPr(optarg)[1] ; geom.numBinT = (int)mxGetPr(optarg)[2] ; if (geom.numBinX < 1 || geom.numBinY < 1 || geom.numBinT < 1) { vlmxError(vlmxErrInvalidArgument, "GEOMETRY value is invalid.") ; } break ; default : abort() ; } } /* ----------------------------------------------------------------- * Do job * -------------------------------------------------------------- */ { int numFrames ; int descrSize ; VlDsiftKeypoint const *frames ; float const *descrs ; int k, i ; VlDsiftFilter *dsift ; /* note that the image received from MATLAB is transposed */ dsift = vl_dsift_new (M, N) ; vl_dsift_set_geometry(dsift, &geom) ; vl_dsift_set_steps(dsift, step[0], step[1]) ; if (bounds) { vl_dsift_set_bounds(dsift, VL_MAX(bounds[1], 0), VL_MAX(bounds[0], 0), VL_MIN(bounds[3], M - 1), VL_MIN(bounds[2], N - 1)); } vl_dsift_set_flat_window(dsift, useFlatWindow) ; if (windowSize >= 0) { vl_dsift_set_window_size(dsift, windowSize) ; } numFrames = vl_dsift_get_keypoint_num (dsift) ; descrSize = vl_dsift_get_descriptor_size (dsift) ; geom = *vl_dsift_get_geometry (dsift) ; if (verbose) { int stepX ; int stepY ; int minX ; int minY ; int maxX ; int maxY ; vl_bool useFlatWindow ; vl_dsift_get_steps (dsift, &stepY, &stepX) ; vl_dsift_get_bounds (dsift, &minY, &minX, &maxY, &maxX) ; useFlatWindow = vl_dsift_get_flat_window(dsift) ; mexPrintf("vl_dsift: image size [W, H] = [%d, %d]\n", N, M) ; mexPrintf("vl_dsift: bounds: [minX,minY,maxX,maxY] = [%d, %d, %d, %d]\n", minX+1, minY+1, maxX+1, maxY+1) ; mexPrintf("vl_dsift: subsampling steps: stepX=%d, stepY=%d\n", stepX, stepY) ; mexPrintf("vl_dsift: num bins: [numBinT, numBinX, numBinY] = [%d, %d, %d]\n", geom.numBinT, geom.numBinX, geom.numBinY) ; mexPrintf("vl_dsift: descriptor size: %d\n", descrSize) ; mexPrintf("vl_dsift: bin sizes: [binSizeX, binSizeY] = [%d, %d]\n", geom.binSizeX, geom.binSizeY) ; mexPrintf("vl_dsift: flat window: %s\n", VL_YESNO(useFlatWindow)) ; mexPrintf("vl_dsift: window size: %g\n", vl_dsift_get_window_size(dsift)) ; mexPrintf("vl_dsift: num of features: %d\n", numFrames) ; } vl_dsift_process (dsift, data) ; frames = vl_dsift_get_keypoints (dsift) ; descrs = vl_dsift_get_descriptors (dsift) ; /* --------------------------------------------------------------- * Create output arrays * ------------------------------------------------------------ */ { mwSize dims [2] ; dims [0] = descrSize ; dims [1] = numFrames ; if (floatDescriptors) { out[OUT_DESCRIPTORS] = mxCreateNumericArray (2, dims, mxSINGLE_CLASS, mxREAL) ; } else { out[OUT_DESCRIPTORS] = mxCreateNumericArray (2, dims, mxUINT8_CLASS, mxREAL) ; } dims [0] = norm ? 3 : 2 ; out[OUT_FRAMES] = mxCreateNumericArray (2, dims, mxDOUBLE_CLASS, mxREAL) ; } /* --------------------------------------------------------------- * Copy back * ------------------------------------------------------------ */ { float *tmpDescr = mxMalloc(sizeof(float) * descrSize) ; double *outFrameIter = mxGetPr(out[OUT_FRAMES]) ; void *outDescrIter = mxGetData(out[OUT_DESCRIPTORS]) ; for (k = 0 ; k < numFrames ; ++k) { *outFrameIter++ = frames[k].y + 1 ; *outFrameIter++ = frames[k].x + 1 ; /* We have an implied / 2 in the norm, because of the clipping below */ if (norm) *outFrameIter++ = frames [k].norm ; vl_dsift_transpose_descriptor (tmpDescr, descrs + descrSize * k, geom.numBinT, geom.numBinX, geom.numBinY) ; if (floatDescriptors) { for (i = 0 ; i < descrSize ; ++i) { float * pt = (float*) outDescrIter ; *pt++ = VL_MIN(512.0F * tmpDescr[i], 255.0F) ; outDescrIter = pt ; } } else { for (i = 0 ; i < descrSize ; ++i) { vl_uint8 * pt = (vl_uint8*) outDescrIter ; *pt++ = (vl_uint8) (VL_MIN(512.0F * tmpDescr[i], 255.0F)) ; outDescrIter = pt ; } } } mxFree(tmpDescr) ; } vl_dsift_delete (dsift) ; } }
/** ------------------------------------------------------------------ ** @brief Python entry point **/ PyObject * vl_dsift_python( PyArrayObject & pyArray, int opt_step, PyArrayObject & opt_bounds, int opt_size, bool opt_fast, bool opt_verbose, bool opt_norm) { // check data type assert(pyArray.descr->type_num == PyArray_FLOAT); assert(pyArray.flags & NPY_FORTRAN); assert(opt_bounds.descr->type_num == PyArray_FLOAT); int verbose = 0; int opt; float const *data; int M, N; int step = 1; int size = 3; vl_bool norm = 0; vl_bool useFlatWindow = VL_FALSE; double *bounds = NULL; double boundBuffer[4]; /* ----------------------------------------------------------------- * Check the arguments * -------------------------------------------------------------- */ data = (float*) pyArray.data; M = pyArray.dimensions[0]; N = pyArray.dimensions[1]; if (opt_verbose) ++verbose; if (opt_fast) useFlatWindow = 1; if (opt_norm) norm = 1; if (opt_bounds.nd == 1 && opt_bounds.dimensions[0] == 4) { double * tmp = (double *) opt_bounds.data; bounds = boundBuffer; for (int i = 0; i < 4; i++) bounds[i] = tmp[i]; } if (opt_size >= 0) size = opt_size; if (opt_step >= 0) step = opt_step; // create PyTuple for outputs PyObject * tuple = PyTuple_New(2); /* ----------------------------------------------------------------- * Do job * -------------------------------------------------------------- */ { int numFrames; int descrSize; VlDsiftKeypoint const *frames; VlDsiftDescriptorGeometry const *geom; float const *descrs; int k, i; VlDsiftFilter *dsift; dsift = vl_dsift_new_basic(M, N, step, size); if (bounds) { vl_dsift_set_bounds(dsift, VL_MAX(bounds[0], 0), VL_MAX( bounds[1], 0), VL_MIN(bounds[2], M - 1), VL_MIN(bounds[3], N - 1)); } vl_dsift_set_flat_window(dsift, useFlatWindow); numFrames = vl_dsift_get_keypoint_num (dsift) ; descrSize = vl_dsift_get_descriptor_size (dsift) ; geom = vl_dsift_get_geometry(dsift); if (verbose) { int stepX; int stepY; int minX; int minY; int maxX; int maxY; vl_bool useFlatWindow; vl_dsift_get_steps(dsift, &stepX, &stepY); vl_dsift_get_bounds(dsift, &minX, &minY, &maxX, &maxY); useFlatWindow = vl_dsift_get_flat_window(dsift); printf("dsift: image size: %d x %d\n", N, M); printf( " bounds: [%d, %d, %d, %d]\n", minY, minX, maxY, maxX); printf(" subsampling steps: %d, %d\n", stepY, stepX); printf( " num bins: [%d, %d, %d]\n", geom->numBinT, geom->numBinX, geom->numBinY); printf(" descriptor size: %d\n", descrSize); printf( " bin sizes: [%d, %d]\n", geom->binSizeX, geom->binSizeY); printf(" flat window: %s\n", VL_YESNO(useFlatWindow)); printf(" number of frames: %d\n", numFrames); } vl_dsift_process(dsift, data); frames = vl_dsift_get_keypoints(dsift); descrs = vl_dsift_get_descriptors(dsift); /* --------------------------------------------------------------- * Create output arrays * ------------------------------------------------------------ */ npy_intp dims[2]; dims[0] = descrSize; dims[1] = numFrames; // allocate PyArray objects PyArrayObject * _descriptors = (PyArrayObject *) PyArray_NewFromDescr( &PyArray_Type, PyArray_DescrFromType(PyArray_UINT8), 2, dims, NULL, NULL, NPY_F_CONTIGUOUS, NULL); if (norm) dims[0] = 3; else dims[0] = 2; PyArrayObject * _frames = (PyArrayObject*) PyArray_NewFromDescr( &PyArray_Type, PyArray_DescrFromType(PyArray_DOUBLE), 2, dims, NULL, NULL, NPY_F_CONTIGUOUS, NULL); // put PyArray objects in PyTuple PyTuple_SetItem(tuple, 0, PyArray_Return(_frames)); PyTuple_SetItem(tuple, 1, PyArray_Return(_descriptors)); /* --------------------------------------------------------------- * Copy back * ------------------------------------------------------------ */ { float *tmpDescr = (float*) vl_malloc(sizeof(float) * descrSize); double *outFrameIter = (double*) _frames->data; vl_uint8 *outDescrIter = (vl_uint8 *) _descriptors->data; for (k = 0; k < numFrames; ++k) { *outFrameIter++ = frames[k].y; *outFrameIter++ = frames[k].x; /* We have an implied / 2 in the norm, because of the clipping below */ if (norm) *outFrameIter++ = frames[k].norm; vl_dsift_transpose_descriptor( tmpDescr, descrs + descrSize * k, geom->numBinT, geom->numBinX, geom->numBinY); for (i = 0; i < descrSize; ++i) { *outDescrIter++ = (vl_uint8) (VL_MIN( 512.0F * tmpDescr[i], 255.0F)); } } vl_free(tmpDescr); } vl_dsift_delete(dsift); } return tuple; }