diff options
Diffstat (limited to 'sci_gateway1/cpp/opencv_extractLBPFeatures.cpp')
-rw-r--r-- | sci_gateway1/cpp/opencv_extractLBPFeatures.cpp | 515 |
1 files changed, 515 insertions, 0 deletions
diff --git a/sci_gateway1/cpp/opencv_extractLBPFeatures.cpp b/sci_gateway1/cpp/opencv_extractLBPFeatures.cpp new file mode 100644 index 0000000..291f6bb --- /dev/null +++ b/sci_gateway1/cpp/opencv_extractLBPFeatures.cpp @@ -0,0 +1,515 @@ +/*************************************************** +Author : Tanmay Chaudhari + +TO DO: +1) nearest neighbor interpolation +2) upright parameter implementation + ***************************************************/ + +#include "opencv2/core/core.hpp" +#include "opencv2/highgui/highgui.hpp" +#include "opencv2/opencv.hpp" +#include "opencv2/imgproc/imgproc.hpp" +#include <bits/stdc++.h> +using namespace cv; +using namespace std; +extern "C" +{ +#include "api_scilab.h" +#include "Scierror.h" +#include "BOOL.h" +#include <localization.h> +#include "sciprint.h" +#include "../common.h" +//#include "../common.cpp" + + void ELBP(const Mat& src, Mat& dst, int radius, int neighbors) + { + neighbors = max(min(neighbors,31),1); // set bounds... + // Note: alternatively you can switch to the new OpenCV Mat_ + // type system to define an unsigned int matrix... I am probably + // mistaken here, but I didn't see an unsigned int representation + // in OpenCV's classic typesystem... + dst = Mat::zeros(src.rows-2*radius, src.cols-2*radius, CV_32SC1); + for(int n=0; n<neighbors; n++) + { + // sample points + float x = static_cast<float>(radius) * cos(2.0*M_PI*n/static_cast<float>(neighbors)); + float y = static_cast<float>(radius) * -sin(2.0*M_PI*n/static_cast<float>(neighbors)); + // relative indices + int fx = static_cast<int>(floor(x)); + int fy = static_cast<int>(floor(y)); + int cx = static_cast<int>(ceil(x)); + int cy = static_cast<int>(ceil(y)); + // fractional part + float ty = y - fy; + float tx = x - fx; + // set interpolation weights + float w1 = (1 - tx) * (1 - ty); + float w2 = tx * (1 - ty); + float w3 = (1 - tx) * ty; + float w4 = tx * ty; + // iterate through your data + for(int i=radius; i < src.rows-radius;i++) + { + for(int j=radius;j < src.cols-radius;j++) + { + float t = w1*src.at<float>(i+fy,j+fx) + w2*src.at<float>(i+fy,j+cx) + w3*src.at<float>(i+cy,j+fx) + w4*src.at<float>(i+cy,j+cx); + // we are dealing with floating point precision, so add some little tolerance + dst.at<unsigned int>(i-radius,j-radius) += ((t > src.at<float>(i,j)) && (abs(t-src.at<float>(i,j)) > std::numeric_limits<float>::epsilon())) << n; + } + } + } + } + + /*void ELBP(const Mat& src, Mat& dst, int radius, int neighbors) + { + switch(src.type()) { + case CV_8SC1: ELBP_<char>(src, dst, radius, neighbors); break; + case CV_8UC1: ELBP_<unsigned char>(src, dst, radius, neighbors); break; + case CV_16SC1: ELBP_<short>(src, dst, radius, neighbors); break; + case CV_16UC1: ELBP_<unsigned short>(src, dst, radius, neighbors); break; + case CV_32SC1: ELBP_<int>(src, dst, radius, neighbors); break; + case CV_32FC1: ELBP_<float>(src, dst, radius, neighbors); break; + case CV_64FC1: ELBP_<double>(src, dst, radius, neighbors); break; + } + }*/ + + static Mat histc_(const Mat& src, int minVal=0, int maxVal=255, bool normed=false) + { + Mat result; + // Establish the number of bins. + int histSize = maxVal-minVal+1; + // Set the ranges. + float range[] = { static_cast<float>(minVal), static_cast<float>(maxVal+1) }; + const float* histRange = { range }; + // calc histogram + calcHist(&src, 1, 0, Mat(), result, 1, &histSize, &histRange, true, false); + // normalize + if(normed) { + result /= (int)src.total(); + } + return result.reshape(1,1); + } + + static Mat histc(InputArray _src, int minVal, int maxVal, bool normed) + { + Mat src = _src.getMat(); + switch (src.type()) { + case CV_8SC1: + return histc_(Mat_<float>(src), minVal, maxVal, normed); + break; + case CV_8UC1: + return histc_(src, minVal, maxVal, normed); + break; + case CV_16SC1: + return histc_(Mat_<float>(src), minVal, maxVal, normed); + break; + case CV_16UC1: + return histc_(src, minVal, maxVal, normed); + break; + case CV_32SC1: + return histc_(Mat_<float>(src), minVal, maxVal, normed); + break; + case CV_32FC1: + return histc_(src, minVal, maxVal, normed); + break; + } + return Mat(); + } + + + static Mat spatial_histogram(InputArray _src, int numPatterns, int grid_x, int grid_y, bool normed) + { + Mat src = _src.getMat(); + // calculate LBP patch size + //int width = src.cols/grid_x; + //int height = src.rows/grid_y; + int width = grid_x; + int height = grid_y; + + // allocate memory for the spatial histogram + Mat result = Mat::zeros(grid_x * grid_y, numPatterns, CV_32FC1); + // return matrix with zeros if no data was given + if(src.empty()) + return result.reshape(1,1); + // initial result_row + int resultRowIdx = 0; + // iterate through grid + for(int i = 0; i < grid_y; i++) { + for(int j = 0; j < grid_x; j++) { + Mat src_cell = Mat(src, Range(i*height,(i+1)*height), Range(j*width,(j+1)*width)); + Mat cell_hist = histc(src_cell, 0, (numPatterns-1), normed); + // copy to the result matrix + Mat result_row = result.row(resultRowIdx); + cell_hist.reshape(1,1).convertTo(result_row, CV_32FC1); + // increase row count in result matrix + resultRowIdx++; + } + } + // return result as reshaped feature vector + return result.reshape(1,1); + } + + int opencv_extractLBPFeatures(char *fname, unsigned long fname_len) + { + //Error management variable + SciErr sciErr; + + //Variable declaration + int iRows = 0; + int iCols = 0; + int intErr = 0; + int nbInputArguments = 0; + int *piLen = NULL; + int *piAddr = NULL; + bool *providedArgs = NULL; + bool linearInterpolation = 1; + bool normalization = 1; + char *currentArg = NULL; + char **pstData = NULL; + double radius = 1; + double upright = 1; + double neighbors = 8; + double *cellSize = NULL; + double *outputHist = NULL; + Mat image; + Mat grayscaleImage; + Mat lbpImage; + Mat spatialHistogram; + + //Check input output arguments + CheckInputArgument(pvApiCtx, 1, 13); + CheckOutputArgument(pvApiCtx, 1, 1); + + nbInputArguments = *getNbInputArgument(pvApiCtx); + + if((nbInputArguments-1)%2!=0) + { + Scierror(999, "Incorrect number of arguments provided. Please check the documentation for more information.\n"); + return 0; + } + + providedArgs = (bool*)malloc(sizeof(bool) * 6); + for(int i=0;i<6;i++) + providedArgs[i] = 0; + + //getting input arguments + retrieveImage(image, 1); + cellSize = (double*)malloc(sizeof(double) * 2); + + for(int iter=2;iter<=nbInputArguments;iter++) + { + // Getting address of next argument + sciErr = getVarAddressFromPosition(pvApiCtx, iter, &piAddr); + if (sciErr.iErr) + { + printError(&sciErr, 0); + return 0; + } + + // Extracting name of next argument takes three calls to getMatrixOfString + sciErr = getMatrixOfString(pvApiCtx, piAddr, &iRows, &iCols, NULL, NULL); + if (sciErr.iErr) + { + printError(&sciErr, 0); + return 0; + } + + piLen = (int*) malloc(sizeof(int) * iRows * iCols); + + sciErr = getMatrixOfString(pvApiCtx, piAddr, &iRows, &iCols, piLen, NULL); + if (sciErr.iErr) + { + printError(&sciErr, 0); + return 0; + } + + pstData = (char**) malloc(sizeof(char*) * iRows * iCols); + for(int iterPstData = 0; iterPstData < iRows * iCols; iterPstData++) + { + pstData[iterPstData] = (char*) malloc(sizeof(char) * piLen[iterPstData] + 1); + } + + sciErr = getMatrixOfString(pvApiCtx, piAddr, &iRows, &iCols, piLen, pstData); + if (sciErr.iErr) + { + printError(&sciErr, 0); + return 0; + } + + currentArg = pstData[0]; + // providedArgs[] makes sure that no optional argument is provided more than once + + if(strcmp(currentArg, "NumNeighbors")==0) + { + if(!providedArgs[0]) + { + sciErr = getVarAddressFromPosition(pvApiCtx, ++iter, &piAddr); + if (sciErr.iErr) + { + printError(&sciErr, 0); + return 0; + } + + intErr = getScalarDouble(pvApiCtx, piAddr, &neighbors); + if(intErr) + { + return intErr; + } + // Checking if values are in proper range. Same for all optional arguments + if(neighbors < 4 || neighbors > 24) + { + Scierror(999, "Error: Please provide proper value for \"%s\". Permissible range is [4, 24].\n", currentArg); + return 0; + } + providedArgs[0] = 1; + + } + else if(providedArgs[0]) + { + Scierror(999, "Please provide optional arguments only once.\n"); + return 0; + } + } + else if(strcmp(currentArg, "Radius")==0) + { + if(!providedArgs[1]) + { + sciErr = getVarAddressFromPosition(pvApiCtx, ++iter, &piAddr); + if (sciErr.iErr) + { + printError(&sciErr, 0); + return 0; + } + + intErr = getScalarDouble(pvApiCtx, piAddr, &radius); + if(intErr) + { + return intErr; + } + // Checking if values are in proper range. Same for all optional arguments + if(radius < 1 || radius > 5) + { + Scierror(999, "Error: Please provide proper value for \"%s\". Permissible range is [1, 5].\n", currentArg); + return 0; + } + providedArgs[1] = 1; + } + else if(providedArgs[1]) + { + Scierror(999, "Please provide optional arguments only once.\n"); + return 0; + } + } + else if(strcmp(currentArg, "Upright")==0) + { + if(!providedArgs[2]) + { + sciErr = getVarAddressFromPosition(pvApiCtx, ++iter, &piAddr); + if (sciErr.iErr) + { + printError(&sciErr, 0); + return 0; + } + + intErr = getScalarDouble(pvApiCtx, piAddr, &upright); + if(intErr) + { + return intErr; + } + // Checking if values are in proper range. Same for all optional arguments + if(upright!=0.0 && upright!=1.0) + { + Scierror(999, "Error: Please provide proper value for \"%s\". Permissible values are 0 or 1.\n", currentArg); + return 0; + } + providedArgs[2] = 1; + } + else if(providedArgs[2]) + { + Scierror(999, "Please provide optional arguments only once.\n"); + return 0; + } + } + else if(strcmp(currentArg, "Interpolation")==0) + { + if(!providedArgs[3]) + { + sciErr = getVarAddressFromPosition(pvApiCtx, ++iter, &piAddr); + if (sciErr.iErr) + { + printError(&sciErr, 0); + return 0; + } + + sciErr = getMatrixOfString(pvApiCtx, piAddr, &iRows, &iCols, NULL, NULL); + if (sciErr.iErr) + { + printError(&sciErr, 0); + return 0; + } + + piLen = (int*) malloc(sizeof(int) * iRows * iCols); + + sciErr = getMatrixOfString(pvApiCtx, piAddr, &iRows, &iCols, piLen, NULL); + if (sciErr.iErr) + { + printError(&sciErr, 0); + return 0; + } + + pstData = (char**) malloc(sizeof(char*) * iRows * iCols); + for(int iterPstData = 0; iterPstData < iRows * iCols; iterPstData++) + { + pstData[iterPstData] = (char*) malloc(sizeof(char) * piLen[iterPstData] + 1); + } + + sciErr = getMatrixOfString(pvApiCtx, piAddr, &iRows, &iCols, piLen, pstData); + if (sciErr.iErr) + { + printError(&sciErr, 0); + return 0; + } + + if(strcmp(pstData[0],"Mean square error")==0) + linearInterpolation=1; + else if(strcmp(pstData[0], "Nearest")==0) + linearInterpolation=0; + else + { + Scierror(999, "Error: Please provide proper value for \"%s\". Permissible values are Linear or Nearest.\n", currentArg); + return 0; + } + providedArgs[3]=1; + } + else if(providedArgs[3]) + { + Scierror(999, "Please provide optional arguments only once.\n"); + return 0; + } + } + else if(strcmp(currentArg, "CellSize")==0) + { + if(!providedArgs[4]) + { + sciErr = getVarAddressFromPosition(pvApiCtx, ++iter, &piAddr); + if (sciErr.iErr) + { + printError(&sciErr, 0); + return 0; + } + if(!isDoubleType(pvApiCtx, piAddr) || isVarComplex(pvApiCtx, piAddr)) + { + Scierror(999, "%s: Wrong type for input argument #%d: A real matrix expected.\n", fname, iter); + return 0; + } + sciErr = getMatrixOfDouble(pvApiCtx, piAddr, &iRows, &iCols, &cellSize); + if(sciErr.iErr) + { + printError(&sciErr, 0); + return 0; + } + if(iRows!=1 || iCols!=2) + { + Scierror(999, "Incorrect dimension of matrix for argument CellSize.\n"); + return 0; + } + providedArgs[4]=1; + } + else if(providedArgs[4]) + { + Scierror(999, "Please provide optional arguments only once.\n"); + return 0; + } + } + else if(strcmp(currentArg, "Normalization")==0) + { + if(!providedArgs[5]) + { + sciErr = getVarAddressFromPosition(pvApiCtx, ++iter, &piAddr); + if (sciErr.iErr) + { + printError(&sciErr, 0); + return 0; + } + + sciErr = getMatrixOfString(pvApiCtx, piAddr, &iRows, &iCols, NULL, NULL); + if (sciErr.iErr) + { + printError(&sciErr, 0); + return 0; + } + + piLen = (int*) malloc(sizeof(int) * iRows * iCols); + + sciErr = getMatrixOfString(pvApiCtx, piAddr, &iRows, &iCols, piLen, NULL); + if (sciErr.iErr) + { + printError(&sciErr, 0); + return 0; + } + + pstData = (char**) malloc(sizeof(char*) * iRows * iCols); + for(int iterPstData = 0; iterPstData < iRows * iCols; iterPstData++) + { + pstData[iterPstData] = (char*) malloc(sizeof(char) * piLen[iterPstData] + 1); + } + + sciErr = getMatrixOfString(pvApiCtx, piAddr, &iRows, &iCols, piLen, pstData); + if (sciErr.iErr) + { + printError(&sciErr, 0); + return 0; + } + + if(strcmp(pstData[0],"L2")==0) + normalization=1; + else if(strcmp(pstData[0], "None")==0) + normalization=0; + else + { + Scierror(999, "Error: Please provide proper value for \"%s\". Permissible values are L2 or None.\n", currentArg); + return 0; + } + providedArgs[5]=1; + } + else if(providedArgs[5]) + { + Scierror(999, "Please provide optional arguments only once.\n"); + return 0; + } + } + } + //onvert RGB image to gray + cvtColor(image, grayscaleImage, CV_BGR2GRAY); + ELBP(grayscaleImage, lbpImage, radius, neighbors); + + if(!providedArgs[4]) + { + cellSize[0] = lbpImage.cols; + cellSize[1] = lbpImage.rows; + } + + //calculate the spatial histogram + spatialHistogram = spatial_histogram(lbpImage, static_cast<int>(pow(2.0, static_cast<double>(neighbors))), int(cellSize[0]), int(cellSize[1]), normalization); + + outputHist = (double*)malloc(sizeof(double) * spatialHistogram.cols); + for(int i=0;i<spatialHistogram.cols;i++) + outputHist[i] = spatialHistogram.at<double>(0,i); + + //create output argument + sciErr = createMatrixOfDouble(pvApiCtx, nbInputArgument(pvApiCtx)+1, 1, spatialHistogram.cols, outputHist); + if(sciErr.iErr) + { + printError(&sciErr, 0); + return 0; + } + + //return output Arguments + AssignOutputVariable(pvApiCtx, 1) = nbInputArgument(pvApiCtx) + 1; + ReturnArguments(pvApiCtx); + return 0; + } + /* ==================================================================== */ +} |