How to use opencv BOWKMeansTrainer in Java? - opencv

I am using opencv 3.2 for Java (build source with contrib modules), and trying to use SURF + BOWKMeansTrainer for detect, but it throws an error when I run it.
My code:
//read jpg to variable trainMats
//...
//train
Mat allDesc = new Mat();
int clusterCount = 30;
FeatureDetector detector = FeatureDetector.create(FeatureDetector.SURF);
DescriptorExtractor extractor = DescriptorExtractor.create(DescriptorExtractor.SURF);
BOWTrainer bowTrainer = new BOWKMeansTrainer(clusterCount);
for(int i = 0; i < trainMats.size(); i++) {
Mat trainMat = trainMats.get(i);
MatOfKeyPoint matOfKeyPoint = new MatOfKeyPoint();
Mat desc = new Mat();
detector.detect(trainMat, matOfKeyPoint);
extractor.compute(trainMat, matOfKeyPoint, desc);
allDesc.push_back(desc);
}
Mat dictionary = bowTrainer.cluster(allDesc);
//...
throw error:
Exception in thread "main" java.lang.Exception: unknown exception
at org.opencv.features2d.BOWKMeansTrainer.cluster_1(Native Method)
at org.opencv.features2d.BOWKMeansTrainer.cluster(BOWKMeansTrainer.java:62)

Is by the OpenCV version.
Try using 2.4.11

Related

java.io.FileNotFoundException: Access denied on Image.IO.write

Im cropping 64x128 pixel Images in 4x8 and 8x16 grids and saving them in a Temp Folder to extract features from for image classification. While im doing this in a loop for multiple Images (I crop the first Image, get 8x16 subimages, extract features for each subimage, move to the next image and overwrite the existing subimages) I get an "File not found" Exception at random grid cells because access is denied for said grid cell. This only occurs when working with a big number (say 20+) of Images. How can I work around this ?
My code for the cropping part:
package imageProcess;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class Crop_Raster {
BufferedImage src;
BufferedImage dst;
public Crop_Raster(BufferedImage src) {
super();
this.src = src;
}
public void cropImage_4x8() throws IOException{
int filenumber = 1;
for (int y = 0;y<4;y++){
for (int x = 0; x<8;x++){
File output = new File("Temp/"+filenumber+".jpg");
dst = src.getSubimage(16*x,16*y, 16, 16);
ImageIO.write(dst, "jpg", output);
filenumber ++;
}
}
}
public void cropImage_8x16() throws IOException{
int filenumber = 1;
for (int y = 0;y<8;y++){
for (int x = 0; x<16;x++){
File output = new File("Temp/"+filenumber+".jpg");
dst = src.getSubimage(8*x,8*y, 8, 8);
ImageIO.write(dst, "jpg", output);
filenumber ++;
}
}
}
I get the following Exception, happening while handling the second subimage of my 6th Training Image:
java.io.FileNotFoundException: Temp\2.jpg (Zugriff verweigert)
at java.io.RandomAccessFile.open0(Native Method)
at java.io.RandomAccessFile.open(Unknown Source)
at java.io.RandomAccessFile.<init>(Unknown Source)
at javax.imageio.stream.FileImageOutputStream.<init>(Unknown Source)
at com.sun.imageio.spi.FileImageOutputStreamSpi.createOutputStreamInstance(Unknown Source)
at javax.imageio.ImageIO.createImageOutputStream(Unknown Source)
at javax.imageio.ImageIO.write(Unknown Source)
at imageProcess.Crop_Raster.cropImage_8x16(Crop_Raster.java:38)
at svm.CreateVektor.createVector_8x16(CreateVektor.java:94)
at Main_Test.main(Main_Test.java:107)
The error occurs during the cropping part, the rest of my methods should work fine.
Clearing the Temp folder after each Image fixed the issue.

How to convert Mat to IplImage in Javacv?

Is any one know how i can convert Mat to IplImage ?
to achieve this i have converted Mat to BufferedImage but again not able to find conversion in BufferedImage to IplImage.
is there any way where i can convert Mat to IplImage?
Thanks
I believe you can convert BufferedImage to IplImage as follows.
public static IplImage toIplImage(BufferedImage src) {
Java2DFrameConverter bimConverter = new Java2DFrameConverter();
OpenCVFrameConverter.ToIplImage iplConverter = new OpenCVFrameConverter.ToIplImage();
Frame frame = bimConverter.convert(src);
IplImage img = iplConverter.convert(frame);
IplImage result = img.clone();
img.release();
return result;
}
I got this from this question. Try this for now. I'll check if direct conversion is possible.
UPDATE:
Please have a look at this api docs. I haven't tested the following. Wrote it just now. Please do try and let me know.
public static IplImage toIplImage(Mat src) {
OpenCVFrameConverter.ToIplImage iplConverter = new OpenCVFrameConverter.ToIplImage();
OpenCVFrameConverter.ToMat matConverter = new OpenCVFrameConverter.ToMat();
Frame frame = matConverter.convert(src);
IplImage img = iplConverter.convert(frame);
IplImage result = img.clone();
img.release();
return result;
}

Javacv Face Recognition

I'm trying to use FaceRecognition with javacv. But when I have more than 5 train images I get this error:
# A fatal error has been detected by the Java Runtime Environment:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x6a30b400, pid=4856, tid=32
#
# JRE version: Java(TM) SE Runtime Environment (7.0_51-b13) (build 1.7.0_51-b13)
# Java VM: Java HotSpot(TM) Client VM (24.51-b03 mixed mode, sharing windows-x86 )
# Problematic frame:
# C [opencv_core246.dll+0x4b400]
#
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
#
# An error report file with more information is saved as:
# C:\Users\reco\workspace\hellow\hs_err_pid4856.log
#
# If you would like to submit a bug report, please visit:
# http://bugreport.sun.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#
This is my code:
import com.googlecode.javacv.cpp.opencv_core;
import static com.googlecode.javacv.cpp.opencv_highgui.*;
import static com.googlecode.javacv.cpp.opencv_core.*;
import static com.googlecode.javacv.cpp.opencv_imgproc.*;
import static com.googlecode.javacv.cpp.opencv_contrib.*;
import java.io.File;
import java.io.FilenameFilter;
public class OpenCVFaceRecognizer {
public static void main(String[] args) {
String trainingDir = "C:/Users/reco/workspace/hellow";
IplImage testImage = cvLoadImage("C:/Users/reco/workspace/0.png");
File root = new File(trainingDir);
FilenameFilter pngFilter = new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.toLowerCase().endsWith(".png");
}
};
File[] imageFiles = root.listFiles(pngFilter);
MatVector images = new MatVector(imageFiles.length);
int[] labels = new int[imageFiles.length];
int counter = 0;
int label;
IplImage img;
IplImage grayImg;
for (File image : imageFiles) {
img = cvLoadImage(image.getAbsolutePath());
String temp= image.getName();
label = Integer.parseInt(temp.charAt(0)+"");
grayImg = IplImage.create(img.width(), img.height(), IPL_DEPTH_8U, 1);
cvCvtColor(img, grayImg, CV_BGR2GRAY);
images.put(counter, grayImg);
labels[counter] = label;
counter++;
}
IplImage greyTestImage = IplImage.create(testImage.width(), testImage.height(), IPL_DEPTH_8U, 1);
//FaceRecognizer faceRecognizer = createFisherFaceRecognizer();
FaceRecognizer faceRecognizer = createEigenFaceRecognizer();
// FaceRecognizer faceRecognizer = createLBPHFaceRecognizer()
faceRecognizer.train(images, labels);
cvCvtColor(testImage, greyTestImage, CV_BGR2GRAY);
int predictedLabel = faceRecognizer.predict(greyTestImage);
System.out.println("Predicted label: " + predictedLabel);
}
}
edit::i just removed
grayImg = IplImage.create(img.width(), img.height(), IPL_DEPTH_8U, 1);
cvCvtColor(img, grayImg, CV_BGR2GRAY);
and it worked :)
IplImage img;
IplImage grayImg=null;
for (File image : imageFiles) {
img = cvLoadImage(image.getAbsolutePath(),CV_BGR2GRAY);
int yer = image.getName().indexOf(".");
String isim=image.getName().substring(0,yer);
label = Integer.parseInt(isim);
images.put(counter, img);
labels[counter] = label;
counter++;
}
it is the final of my code and it works like a charm :)

Gathering the confidence with JAVACV program

Trying to figure out a way to gather the confidence level when it actually does the face recognizing on the target image. I have searched through a few examples but haven't found anything I can see how to implement. All help appreciated, thanks guys.
public static void facecompare() {
String trainingDir = "C:/TrainingDirectory"; //training directory
IplImage testImage = cvLoadImage("C:/TargetImages/boland_straight_happy_open_4.pgm"); //the target image
File root = new File(trainingDir);
FilenameFilter pngFilter = new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.toLowerCase().endsWith(".pgm");
}
};
File[] imageFiles = root.listFiles(pngFilter);
MatVector images = new MatVector(imageFiles.length);
int[] labels = new int[imageFiles.length];
int counter = 0;
int label;
IplImage img;
IplImage grayImg;
for (File image : imageFiles) {
img = cvLoadImage(image.getAbsolutePath());
label = Integer.parseInt(image.getName().split("\\-")[0]);
grayImg = IplImage.create(img.width(), img.height(), IPL_DEPTH_8U, 1);
cvCvtColor(img, grayImg, CV_BGR2GRAY);
images.put(counter, grayImg);
labels[counter] = label;
counter++;
}
IplImage greyTestImage = IplImage.create(testImage.width(), testImage.height(), IPL_DEPTH_8U, 1);
// FaceRecognizer faceRecognizer = createFisherFaceRecognizer();
// FaceRecognizer faceRecognizer = createEigenFaceRecognizer();
FaceRecognizer faceRecognizer = createLBPHFaceRecognizer();
faceRecognizer.train(images, labels);
cvCvtColor(testImage, greyTestImage, CV_BGR2GRAY);
int predictedLabel = faceRecognizer.predict(greyTestImage);
System.out.println("Predicted label: " + predictedLabel);
}
There is another predict method that returns the confidence:
// pointer-like output parameters
// only the first element of these arrays will be changed
int[] plabel = new int[1];
double[] pconfidence = new double[1];
faceRecognizer.predict(greyTestImage, plabel, pconfidence);
int predictedLabel = plabel[0];
double confidence = pconfidence[0];

detector->detect(img, keypoint); error

I want to implement bag of words in opencv. after detector->detect(img, keypoint); detects keypoints, when i want to clean keypoints using keypoint.clear(); or when the function wants to return the following error will be appeared.
"Unhandled exception at 0x011f45bb in BOW.exe: 0xC0000005: Access violation reading location 0x42ebe098."
and also detected keypoints have bizarre points coordinates like cv::Point_ pt{x=-1.5883997e+038y=-1.5883997e+038 }
Part of the code
Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create("FlannBased");
Ptr<DescriptorExtractor> extractor = new SurfDescriptorExtractor();
Ptr<FeatureDetector> detector = new SurfFeatureDetector(2000);
void extractTrainingVocabulary() {
IplImage *img;
int i,j;
CvSeq *imageKeypoints = 0;
for(j=1;j<=60;j++)
for(i=1;i<=60;i++){
sprintf( ch,"%d%s%d%s",j," (",i,").jpg");
const char* imageName = ch;
Mat img = imread(ch);
vector<KeyPoint> keypoint;
detector->detect(img, keypoint);
Mat features;
extractor->compute(img, keypoint, features);
bowTrainer.add(features);
keypoint.clear();//problem
}
return;
}
I noticed something about your code, on extractTrainingVocabulary() you declare IplImage* img; and inside the loop you declare another variable with the same name (but different type): Mat img = imread(ch);.
Even though that might not be the problem, it's certainly not good practice. I would fix that immediately and update the code on your question.

Resources