/** * Inputs: filename (string), matrix */ static void _load_index(int nOutArray, mxArray* OutArray[], int nInArray, const mxArray* InArray[]) { if(nInArray != 2) { mexErrMsgTxt("Incorrect number of input arguments"); } // get the selector if(!mxIsChar(InArray[0])) { mexErrMsgTxt("'filename' should be a string"); } char filename[128]; mxGetString(InArray[0],filename,128); const mxArray* datasetMat = InArray[1]; check_allowed_type(datasetMat); int dcount = mxGetN(datasetMat); int length = mxGetM(datasetMat); TypedIndex* typedIndex = new TypedIndex(); if (mxIsSingle(datasetMat)) { float* dataset = copy_array<float>(datasetMat); typedIndex->index = flann_load_index_float(filename, dataset,dcount,length); typedIndex->type = FLANN_FLOAT32; typedIndex->dataset = dataset; } else if (mxIsDouble(datasetMat)) { double* dataset = copy_array<double>(datasetMat); typedIndex->index = flann_load_index_double(filename, dataset,dcount,length); typedIndex->type = FLANN_FLOAT64; typedIndex->dataset = dataset; } else if (mxIsUint8(datasetMat)) { unsigned char* dataset = copy_array<unsigned char>(datasetMat); typedIndex->index = flann_load_index_byte(filename, dataset,dcount,length); typedIndex->type = FLANN_UINT8; typedIndex->dataset = dataset; } else if (mxIsInt32(datasetMat)) { int* dataset = copy_array<int>(datasetMat); typedIndex->index = flann_load_index_int(filename, dataset,dcount,length); typedIndex->type = FLANN_INT32; typedIndex->dataset = dataset; } mxClassID classID; if (sizeof(flann_index_t)==4) { classID = mxUINT32_CLASS; } else if (sizeof(flann_index_t)==8) { classID = mxUINT64_CLASS; } /* Allocate memory for Output Matrix */ OutArray[0] = mxCreateNumericMatrix(1, 1, classID, mxREAL); /* Get pointer to Output matrix and store result*/ TypedIndex** pOut = (TypedIndex**)mxGetData(OutArray[0]); pOut[0] = typedIndex; }
/** * Input arguments: dataset (matrix), params (struct) * Output arguments: index (pointer to index), params (struct), speedup(double) */ static void _build_index(int nOutArray, mxArray* OutArray[], int nInArray, const mxArray* InArray[]) { /* Check the number of input arguments */ if(nInArray != 2) { mexErrMsgTxt("Incorrect number of input arguments"); } /* Check the number of output arguments */ if ((nOutArray == 0)||(nOutArray > 3)) { mexErrMsgTxt("Incorrect number of outputs."); } const mxArray* datasetMat = InArray[0]; check_allowed_type(datasetMat); int dcount = mxGetN(datasetMat); int length = mxGetM(datasetMat); const mxArray* pStruct = InArray[1]; /* get index parameters */ FLANNParameters p; matlabStructToFlannStruct(pStruct, p); float speedup = -1; TypedIndex* typedIndex = new TypedIndex(); if (mxIsSingle(datasetMat)) { float* dataset = (float*) mxGetData(datasetMat); typedIndex->index = flann_build_index_float(dataset,dcount,length, &speedup, &p); typedIndex->type = FLANN_FLOAT32; } else if (mxIsDouble(datasetMat)) { double* dataset = (double*) mxGetData(datasetMat); typedIndex->index = flann_build_index_double(dataset,dcount,length, &speedup, &p); typedIndex->type = FLANN_FLOAT64; } else if (mxIsUint8(datasetMat)) { unsigned char* dataset = (unsigned char*) mxGetData(datasetMat); typedIndex->index = flann_build_index_byte(dataset,dcount,length, &speedup, &p); typedIndex->type = FLANN_UINT8; } else if (mxIsInt32(datasetMat)) { int* dataset = (int*) mxGetData(datasetMat); typedIndex->index = flann_build_index_int(dataset,dcount,length, &speedup, &p); typedIndex->type = FLANN_INT32; } mxClassID classID; if (sizeof(flann_index_t)==4) { classID = mxUINT32_CLASS; } else if (sizeof(flann_index_t)==8) { classID = mxUINT64_CLASS; } /* Allocate memory for Output Matrix */ OutArray[0] = mxCreateNumericMatrix(1, 1, classID, mxREAL); /* Get pointer to Output matrix and store result*/ TypedIndex** pOut = (TypedIndex**)mxGetData(OutArray[0]); pOut[0] = typedIndex; if (nOutArray > 1) { OutArray[1] = flannStructToMatlabStruct(p); } if (nOutArray > 2) { OutArray[2] = mxCreateDoubleMatrix(1, 1, mxREAL); double* pSpeedup = mxGetPr(OutArray[2]); *pSpeedup = speedup; } }
/** * Input arguments: index (pointer), testset (matrix), n (int), params (struct) * Output arguments: indices(matrix), dists(matrix) */ static void _index_find_nn(int nOutArray, mxArray* OutArray[], int nInArray, const mxArray* InArray[]) { /* Check the number of input arguments */ if(nInArray != 4) { mexErrMsgTxt("Incorrect number of input arguments"); } /* Check if there is one Output matrix */ if(nOutArray > 2) { mexErrMsgTxt("One or two outputs required."); } const mxArray* indexMat = InArray[0]; TypedIndex* typedIndex = *(TypedIndex**)mxGetData(indexMat); const mxArray* testsetMat = InArray[1]; check_allowed_type(testsetMat); int tcount = mxGetN(testsetMat); const mxArray* nnMat = InArray[2]; if ((mxGetM(nnMat)!=1)||(mxGetN(nnMat)!=1)) { mexErrMsgTxt("Number of nearest neighbors should be a scalar."); } int nn = (int)(*mxGetPr(nnMat)); int* result = (int*)malloc(tcount*nn*sizeof(int)); float* dists = NULL; double* ddists = NULL; const mxArray* pStruct = InArray[3]; FLANNParameters p; matlabStructToFlannStruct(pStruct, p); if (mxIsSingle(testsetMat)) { if (typedIndex->type != FLANN_FLOAT32) { mexErrMsgTxt("Index type must match testset type"); } float* testset = (float*) mxGetData(testsetMat); dists = (float*)malloc(tcount*nn*sizeof(float)); flann_find_nearest_neighbors_index_float(typedIndex->index,testset, tcount, result, dists, nn, &p); } else if (mxIsDouble(testsetMat)) { if (typedIndex->type != FLANN_FLOAT64) { mexErrMsgTxt("Index type must match testset type"); } double* testset = (double*) mxGetData(testsetMat); ddists = (double*)malloc(tcount*nn*sizeof(double)); flann_find_nearest_neighbors_index_double(typedIndex->index,testset, tcount, result, ddists, nn, &p); } else if (mxIsUint8(testsetMat)) { if (typedIndex->type != FLANN_UINT8) { mexErrMsgTxt("Index type must match testset type"); } unsigned char* testset = (unsigned char*) mxGetData(testsetMat); dists = (float*)malloc(tcount*nn*sizeof(float)); flann_find_nearest_neighbors_index_byte(typedIndex->index,testset, tcount, result, dists, nn, &p); } else if (mxIsInt32(testsetMat)) { if (typedIndex->type != FLANN_INT32) { mexErrMsgTxt("Index type must match testset type"); } int* testset = (int*) mxGetData(testsetMat); dists = (float*)malloc(tcount*nn*sizeof(float)); flann_find_nearest_neighbors_index_int(typedIndex->index,testset, tcount, result, dists, nn, &p); } /* Allocate memory for Output Matrix */ OutArray[0] = mxCreateDoubleMatrix(nn, tcount, mxREAL); /* Get pointer to Output matrix and store result*/ double* pOut = mxGetPr(OutArray[0]); for (int i=0; i<tcount*nn; ++i) { pOut[i] = result[i]+1; // matlab uses 1-based indexing } free(result); if (nOutArray > 1) { /* Allocate memory for Output Matrix */ OutArray[1] = mxCreateDoubleMatrix(nn, tcount, mxREAL); /* Get pointer to Output matrix and store result*/ double* pDists = mxGetPr(OutArray[1]); if (dists!=NULL) { for (int i=0; i<tcount*nn; ++i) { pDists[i] = dists[i]; } } if (ddists!=NULL) { for (int i=0; i<tcount*nn; ++i) { pDists[i] = ddists[i]; } } } if (dists!=NULL) free(dists); if (ddists!=NULL) free(ddists); }
/** * Input arguments: dataset (matrix), testset (matrix), n (int), params (struct) * Output arguments: indices(matrix), dists(matrix) */ static void _find_nn(int nOutArray, mxArray* OutArray[], int nInArray, const mxArray* InArray[]) { /* Check the number of input arguments */ if(nInArray != 4) { mexErrMsgTxt("Incorrect number of input arguments, expecting:\n" "dataset, testset, nearest_neighbors, params"); } /* Check the number of output arguments */ if(nOutArray > 2) { mexErrMsgTxt("One or two outputs required."); } const mxArray* datasetMat = InArray[0]; const mxArray* testsetMat = InArray[1]; check_allowed_type(datasetMat); check_allowed_type(testsetMat); int dcount = mxGetN(datasetMat); int length = mxGetM(datasetMat); int tcount = mxGetN(testsetMat); if (mxGetM(testsetMat) != length) { mexErrMsgTxt("Dataset and testset features should have the same size."); } const mxArray* nnMat = InArray[2]; if ((mxGetM(nnMat)!=1)||(mxGetN(nnMat)!=1)|| !mxIsNumeric(nnMat)) { mexErrMsgTxt("Number of nearest neighbors should be a scalar."); } int nn = (int)(*mxGetPr(nnMat)); const mxArray* pStruct = InArray[3]; if (!mxIsStruct(pStruct)) { mexErrMsgTxt("Params must be a struct object."); } FLANNParameters p; matlabStructToFlannStruct(pStruct, p); int* result = (int*)malloc(tcount*nn*sizeof(int)); float* dists = NULL; double* ddists = NULL; /* do the search */ if (mxIsSingle(datasetMat)) { float* dataset = (float*) mxGetData(datasetMat); float* testset = (float*) mxGetData(testsetMat); dists = (float*)malloc(tcount*nn*sizeof(float)); flann_find_nearest_neighbors_float(dataset,dcount,length,testset, tcount, result, dists, nn, &p); } else if (mxIsDouble(datasetMat)) { double* dataset = (double*) mxGetData(datasetMat); double* testset = (double*) mxGetData(testsetMat); ddists = (double*)malloc(tcount*nn*sizeof(double)); flann_find_nearest_neighbors_double(dataset,dcount,length,testset, tcount, result, ddists, nn, &p); } else if (mxIsUint8(datasetMat)) { unsigned char* dataset = (unsigned char*) mxGetData(datasetMat); unsigned char* testset = (unsigned char*) mxGetData(testsetMat); dists = (float*)malloc(tcount*nn*sizeof(float)); flann_find_nearest_neighbors_byte(dataset,dcount,length,testset, tcount, result, dists, nn, &p); } else if (mxIsInt32(datasetMat)) { int* dataset = (int*) mxGetData(datasetMat); int* testset = (int*) mxGetData(testsetMat); dists = (float*)malloc(tcount*nn*sizeof(float)); flann_find_nearest_neighbors_int(dataset,dcount,length,testset, tcount, result, dists, nn, &p); } /* Allocate memory for Output Matrix */ OutArray[0] = mxCreateDoubleMatrix(nn, tcount, mxREAL); /* Get pointer to Output matrix and store result */ double* pOut = mxGetPr(OutArray[0]); for (int i=0; i<tcount*nn; ++i) { pOut[i] = result[i]+1; // matlab uses 1-based indexing } free(result); if (nOutArray > 1) { /* Allocate memory for Output Matrix */ OutArray[1] = mxCreateDoubleMatrix(nn, tcount, mxREAL); /* Get pointer to Output matrix and store result*/ double* pDists = mxGetPr(OutArray[1]); if (dists!=NULL) { for (int i=0; i<tcount*nn; ++i) { pDists[i] = dists[i]; } } if (ddists!=NULL) { for (int i=0; i<tcount*nn; ++i) { pDists[i] = ddists[i]; } } } if (dists!=NULL) free(dists); if (ddists!=NULL) free(ddists); }