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 version of negative image
negGrayMat = Highgui.imread(imageAbsPathAsStr, Highgui.CV_LOAD_IMAGE_GRAYSCALE);
// resize negGrayMat to HOG default size 64x128
Imgproc.resize(negGrayMat, negGrayMat, new Size(64, 128));
// reshape negGrayMat from 2D to 1D
negGrayMat = negGrayMat.reshape(0, 1);
// compute HOG features using winStride of 8 x 8 to match hog cellSize and padding to 64 x 128 to match hog winSize
hog.compute(negGrayMat, 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.zeros(1, 1, CvType.CV_32FC1));
}
}
catch(Exception e)
{
// display error
e.printStackTrace();
}
// check SVM data
//Size data = SVMtrainingData.size();
//Size label = labels.size();
//System.out.println("Data size: " + data);
//System.out.println("Label size: " + label);
//check: are the labels all the same?
//System.out.println("Labels:\n" + labels.dump());
// build SVM classifier
CvSVMParams params = new CvSVMParams();
params.set_svm_type(CvSVM.C_SVC);
params.set_kernel_type(CvSVM.LINEAR);
params.set_degree(0);
params.set_gamma(1);
params.set_coef0(0);
params.set_C(1);
params.set_nu(0);
params.set_p(0);
TermCriteria tc = new TermCriteria(TermCriteria.EPS, 1000, 0.00001);
params.set_term_crit(tc);
CvSVM svmClassifier = new CvSVM();
svmClassifier.train(SVMtrainingData, labels, new Mat(), new Mat(), params);
svmClassifier.save("C://Users//mark//Documents//CSC7057_Individual_Project_For_MSc//acer_campestre_classifier.xml");
// ****************test svmClassifier****************
// create sample matrix
Mat sample = new Mat(1, 1, CvType.CV_32FC1);
// create HOG descriptors
MatOfFloat sampleDers = new MatOfFloat();
// create outData matrix
MatOfFloat outData = new MatOfFloat(1, 1, CvType.CV_32FC1);
// load svmClassifier
svmClassifier.load("C://Users//mark//Documents//CSC7057_Individual_Project_For_MSc//acer_campestre_classifier.xml");
// create new file to contain positive and negative images
File testImages = null;
// create String to hold absolute path of image file
String testImageAbsPathAsStr = "";
// create an array of image file paths
File[] testImageFilePaths;
// try getting a sample image from test image directory
try
{
// initialise test images with file path to test image directory
testImages = new File("Images//test_images");
// assign test image path names to testImageFilePaths
testImageFilePaths = testImages.listFiles();
// traverse test image file paths
for(File path : testImageFilePaths)
{
// get absolute path of test image file
testImageAbsPathAsStr = path.getAbsolutePath();
// load sample image as gray scale
sample = Highgui.imread(testImageAbsPathAsStr, Highgui.CV_LOAD_IMAGE_GRAYSCALE);
// resize sample to HOG default size 64x128
Imgproc.resize(sample, sample, new Size(64, 128));
// reshape negGrayMat from 2D to 1D
sample = sample.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(sample, sampleDers, new Size(8, 8), new Size(64, 128), locs);
// push sampleDers to outData
outData.push_back(sampleDers);
// predict positive or negative
System.out.println(svmClassifier.predict(outData));
}
}
catch(Exception e)
{
// display error
e.printStackTrace();
}
}
}