SVM application causing my system to hang
I am using OpenCV java to build a leaf classifier. I extract HOG features from two datasets, one containing 100 images of a target leaf and another containing 100 negative images, images are sized to 50x50 pixels for both datasets. The extracted HOG descriptors are feed into a SVM for training and the application then tests the classifier with a sample dataset containing images sized to the training set. Here is my code:
public static void main(String[] args)
{
// load opencv library
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
// create new file to contain positive and negative images
File images = null;
// create String to hold absolute path of image file
String imageAbsPathAsStr = "";
// create an array of image file paths
File[] imageFilePaths;
// set size of leaf image data and labels for SVM
final int leafFileSize = 100;
// set size of negative image data
final int negFileSize = 100;
final int numFiles = leafFileSize + negFileSize;
// set leaf/neg image width
final int width = 64;
// set leaf/neg image height
final int height = 128;
final int imageArea = width * height;
// create matrix for gray scale leaf image
Mat leafGrayMat = new Mat(1, 1, CvType.CV_32FC1);
// create matrix for neg image
Mat negGrayMat = new Mat(1, 1, CvType.CV_32FC1);
// create matrix of SVMtrainingData
MatOfFloat SVMtrainingData = new MatOfFloat(numFiles, imageArea, CvType.CV_32FC1);
// create matrix of image labels
Mat labels = new Mat(numFiles, 1, CvType.CV_32FC1);
// create HOG descriptor
HOGDescriptor hog = new HOGDescriptor();
// display hog params
//System.out.println("winSize: " + hog.get_winSize());
//System.out.println("winSigma: " + hog.get_winSigma());
//System.out.println("blockSize: " + hog.get_blockSize());
//System.out.println("cellSize: " + hog.get_cellSize());
//System.out.println("blockStride: " + hog.get_blockStride());
//System.out.println("descriptorSize: " + hog.getDescriptorSize());
//System.out.println("L2HysThrehold: " + hog.get_L2HysThreshold());
// create HOG matrices
MatOfFloat ders = new MatOfFloat(1, 1, CvType.CV_32FC1);
MatOfPoint locs = new MatOfPoint();
// try opening leaf image folder
try
{
// initialise leaf images with file path to leaf image directory
images = new File("Images//acer_campestre_100_images");
// assign leaf image path names to imageFilePaths
imageFilePaths = images.listFiles();
// traverse leaf image file paths
for(File path : imageFilePaths)
{
// get absolute path of leaf image file
imageAbsPathAsStr = path.getAbsolutePath();
// initialise gray leaf matrix with gray scale version of leaf image
leafGrayMat = Highgui.imread(imageAbsPathAsStr, Highgui.CV_LOAD_IMAGE_GRAYSCALE);
// resize leafGrayMat to HOG default size 64x128
Imgproc.resize(leafGrayMat, leafGrayMat, new Size(64, 128));
// reshape leafGrayMat from 2D to 1D
leafGrayMat = leafGrayMat.reshape(0, 1);
// compute HOG features winStride of 8 x 8 to match hog cellSize and padding to 64 x 128 to match hog winSize
hog.compute(leafGrayMat, ders, new Size(8, 8), new Size(64, 128), locs);
// push ders to SVM training data
SVMtrainingData.push_back(ders);
// update labels
labels.push_back(Mat.ones(1, 1, CvType.CV_32FC1));
}
}
catch(Exception e)
{
// display error
e.printStackTrace();
}
// try opening negative image folder
try
{
// initialise images with file path to negative image directory
images = new File("Images//neg_images_100");
// assign negative image path names to imageFilePaths
imageFilePaths = images.listFiles();
// traverse negative image file paths
for(File path : imageFilePaths)
{
// get absolute path of negative image file
imageAbsPathAsStr = path.getAbsolutePath();
// initialise gray negative matrix with gray scale ...
btw:
negGrayMat = negGrayMat.reshape(0, 1 );
please don't do this to any of your images. hog.compute needs a 2d image, not an 1d one.(but you might have to reshape() the hog output from a column to a row vector.you should add some print() s and timig code, to see, which part of your prog is the bottleneck.
can you check the size of the resulting hog features ? also the size of your svm trainData ?
(i'm somewhat guessing, your params for hog.compute() result in unreasonable large vectors)
I made the changes as you suggested regarding the images, I dont know how to reshape the hog. The size of the training data is 1x424116003 and since the labels are 1x200 this is now throwing the error: 'Sizes of input arguments do not match (Response array must contain as many elements as the total number of samples) in cvPreprocessCategoricalResponses' when training the classifier: svmClassifier.train(SVMtrainingData, labels, new Mat(), new Mat(), params);
yea, your hog features need to be rows not cols (reshape)
also , if my calculation is correct, you get like 5.7mil features from hog.compute(), way too much (1760 for the standard person classifier.
your train Mat should have 200 rows, and like ~2000 cols (depending on the hog params)
SVMtrainingData.push_back(ders.reshape(1,1));
(reshape shouldbe applied onto the hog features, not the image)I reshaped the HOG descriptors as you suggested. But the error keeps being generated because the training data and the label matrices are not equally sized in order for the train() method to work - labels matrix is 1x200 whereas the SVMtrainingData matrix is 1x424116003 . My understanding is that each image from the data set is given a flag value (for example 1 or 0) according to whether it is a positive image or a negative one. However, the training data for the HOG features will produce a much larger matrix. How can i resolve this conundrum?