Ejemplo n.º 1
0
/**
 * 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);
}