Ask Your Question
0

Preparing LBP Texture Feature for SVM

asked 2016-10-21 02:46:12 -0600

Angulu gravatar image

updated 2016-10-21 03:12:31 -0600

I have extracted LBP Texture features on an image by splitting the image into small cells and then calculating LBP for each sub-image and then latter concatenating spatial histograms of each sub-image following the Philip Code. I push these spatial histograms to a vector<Mat>. I understand my spatial texture features are now contained in the histograms.

The problem I have is, I want to prepare this texture feature vector for training SVM. I convert the vector<Mat>hists of histograms to a row Mat where each row represent a sample. I use the code below to convert to row Mat.

Mat cv::asRowMatrix(const vector<Mat>& src, int rtype, double alpha, double beta) {
// number of samples
size_t n = src.size();
// return empty matrix if no matrices given
if (n == 0)
    return Mat();
// dimensionality of (reshaped) samples
size_t d = src[0].total();
// create data matrix
Mat data(n, d, rtype);
// now copy data
for (int i = 0; i < n; i++) {
    // make sure data can be reshaped, throw exception if not!
    if (src[i].total() != d) {
        string error_message = format("Wrong number of elements in matrix #%d! Expected %d was %d.", i, d, src[i].total());
        CV_Error(CV_StsBadArg, error_message);
    }
    // get a hold of the current row
    Mat xi = data.row(i);
    // make reshape happy by cloning for non-continuous matrices
    if (src[i].isContinuous()) {
        src[i].reshape(1, 1).convertTo(xi, rtype, alpha, beta);
    }
    else {
        src[i].clone().reshape(1, 1).convertTo(xi, rtype, alpha, beta);
    }
}
return data;}

When I do this as Mat data = asRowMatrix(hists, CV_32F, 1, 0) the matrix data comes with same values in each column, showing that all the images are identical. I get the same results if I use LBP image itself instead of its histogram. I would like to prepare LBP texture for training SVM. I have spent weeks figuring out this but am now stuck. Kindly help. Regards

This is how am filling the vector with the code below

string path = ".\\Images\\*.JPG"; //path to my images
vector<String> names; //hold all URLs to images
cv::glob(path, names, false); //Reading URLs to names
//Loop through names, load image and calculate lbp and hists
vector<Mat> hists;
Mat img;
Mat lbp;
Mat hist;
for(int i = 0; i < names.size(); i++)
{
      img = imread(names[i]);
      cvtColor(img, img, CV_BGR2GRAY);
      lbp::OLBP(img, lbp); //call OLBP function in Phillip code
      lbp::spatial_histogram(lbp, hist, 256, Size(10, 10)); //Call to spatial histograms function in Phillip code
      hists.push_back(hist); //push back histogram of this image to vector of mat
}
edit retag flag offensive close merge delete

Comments

i suspect, that somehow, already your vector of histograms contains identical data, can you edit again, and show, how you fill that ?

berak gravatar imageberak ( 2016-10-21 03:00:14 -0600 )edit

thanks for doing so ;)

berak gravatar imageberak ( 2016-10-21 03:13:57 -0600 )edit
1

I have edited and added the part am calculating LBP, histograms and populating the vector. Thank you too

Angulu gravatar imageAngulu ( 2016-10-21 03:19:40 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
1

answered 2016-10-21 03:19:31 -0600

berak gravatar image

updated 2016-10-21 03:22:16 -0600

the fault is not with the asRowMatrix function, but in the code where you setup your histogram vector.

your hist Mat is global, meaning, you use the same one over and over in your calculation, and in the end, all of them are the same (push_back copies only the Mat header, they all share the same "pixels", it's a "shallow" copy there)

so, use fresh (local) Mat's for each image, do not re-use them:

vector<Mat> hists;
for(int i = 0; i < names.size(); i++)
{
      Mat img, lbp, hist; // all local now !
      img = imread(names[i]);
      cvtColor(img, img, CV_BGR2GRAY);
      lbp::OLBP(img, lbp); 
      lbp::spatial_histogram(lbp, hist, 256, Size(10, 10)); 
      hists.push_back(hist); //push back histogram of this image to vector of mat
}
edit flag offensive delete link more

Comments

Thank you berak. This solves the problem. But the resultant data as so many zeros which I think is ok.

Angulu gravatar imageAngulu ( 2016-10-21 03:34:22 -0600 )edit

so many zeros

think of it, if you have a 10x10 patch, there are only 100 lbp values, and a 256 bin histogram will be very "sparse", but that's totally ok. zeros are as significant as any other number here.

you also might want to read up on "uniform lbp histograms", where thy find, that only 59 of that 256 possible histogram bins are actually statistically relevant ;)

berak gravatar imageberak ( 2016-10-21 03:50:39 -0600 )edit

Yes, I know the theory of uniform patterns. But I have no clue of how to use this to compress 256 bin histogram to 59 bin histogram. I have tried to follow your answer at Uniform LBP but I am not getting it clearly. I will appreciate any further explanations especially how to do Look-up table with LUT. Regards

Angulu gravatar imageAngulu ( 2016-10-21 04:56:53 -0600 )edit

basically:

  • in your OLBP function, instead of lbp.at<uchar>(i,j) = value , use: lbp.at<uchar>(i,j) = lookup[value];
  • when calculating the histogram, use 59 bins instead of 256
berak gravatar imageberak ( 2016-10-21 05:13:54 -0600 )edit

Thank you. I will give it a shot in a short while and get back here

Angulu gravatar imageAngulu ( 2016-10-21 05:28:09 -0600 )edit

maybe even postpone it for later. there are only rare cases, where it actually improves the classification, rather try to get your original setup running (so you can do actual tests), and then try optimizing..

berak gravatar imageberak ( 2016-10-21 05:32:18 -0600 )edit

I will take that advice. Thank you for you help sir

Angulu gravatar imageAngulu ( 2016-10-21 05:58:50 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2016-10-21 02:46:12 -0600

Seen: 787 times

Last updated: Oct 21 '16