Ask Your Question
0

Cannot get alpha when use SVM in Java

asked 2017-08-28 03:59:11 -0600

updated 2017-08-28 04:20:21 -0600

berak gravatar image

Hi,

I want to use the Java API 3.0 to detect food image with HOG feature. After I trained the SVM, I want to get the svmdetector with alpha and rho. But when I call getDecisionFunction function, the alpha returns a 1*1 mat. How can I get the right data?

SVM csvm=SVM.create();
            csvm.setType(SVM.C_SVC);
            csvm.setKernel(SVM.LINEAR);
            csvm.setC(0.01);
            TermCriteria tc=new TermCriteria(TermCriteria.MAX_ITER, 3000, 1e-6);
            csvm.setTermCriteria(tc);
            csvm.train(dataMat, Ml.ROW_SAMPLE, labelMat);
            csvm.save(this.svmModelPath+"\\"+labelname+".xml");
            System.out.println(csvm.getDegree());
            System.out.println(csvm.getVarCount());
            System.out.println(csvm.getSupportVectors());
            int svdim=csvm.getVarCount();
            int numofsv=csvm.getSupportVectors().rows();
            Mat alpha=Mat.zeros(numofsv,svdim,CvType.CV_32FC1);
            Mat svidx=Mat.zeros(1, numofsv,CvType.CV_64FC1);
            System.out.println(alpha);
            System.out.println(svidx);
            double rho=csvm.getDecisionFunction(0, alpha, svidx);
            alpha.convertTo(alpha, CvType.CV_32FC1);
            System.out.println(rho);
            System.out.println(alpha);
            System.out.println(svidx);

The output is :

0.0
2304
Mat [1128*2304*CV_32FC1, isCont=true, isSubmat=false, nativeObj=0xa10850, dataAddr=0x1d611080]
Mat [1128*2304*CV_32FC1, isCont=true, isSubmat=false, nativeObj=0xa10af0, dataAddr=0x1c509080]
Mat [1*1128*CV_64FC1, isCont=true, isSubmat=false, nativeObj=0xa10e70, dataAddr=0xa30d80]
-1.0566525311046109
Mat [1*1*CV_32FC1, isCont=true, isSubmat=false, nativeObj=0xa10af0, dataAddr=0xa29e00]
Mat [1*1*CV_32SC1, isCont=true, isSubmat=false, nativeObj=0xa10e70, dataAddr=0xa292c0]
edit retag flag offensive close merge delete

Comments

do you want to use rho & the sv for detectMultiScale() later ?

berak gravatar imageberak ( 2017-08-28 04:25:13 -0600 )edit

Yes. That's exactly what I am going to do.

semoryang gravatar imagesemoryang ( 2017-08-28 21:31:54 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
0

answered 2017-08-28 21:49:01 -0600

berak gravatar image

updated 2017-08-29 03:42:10 -0600

in the case of a LINEAR svm, the support vectors get compressed to a single one, thus also alpha and svidx contain only a single element.

to use this single sv with the HOGDescriptor later, you will need only the sv and rho, not alpha or svindex, you'll have to append -rho as last elem to the sv, before passing the resulting float array to HOGDescriptor.setSVMDetector() (sounds weird,but it's just a matter of transporting it to the actual algorithm).

you'll probably also have to change C_SVC to C_SVR or C_SVR_EPS in your SVM params (should it be optimized for distance to the sv not for classification)

edit flag offensive delete link more

Comments

Thank you so much for your reply. But I still get error.

    int svdim=csvm.getVarCount();
            int numofsv=csvm.getSupportVectors().rows();
            Mat alpha=Mat.zeros(numofsv,svdim,CvType.CV_32FC1);
            Mat svidx=Mat.zeros(1, numofsv,CvType.CV_64FC1);
            double rho=csvm.getDecisionFunction(0, alpha, svidx);
            Mat detectormat=new Mat(1,csvm.getVarCount()+1,CvType.CV_32FC1);
            Mat sv=csvm.getSupportVectors();
            //sv.copyTo(detectormat);
            float[] svdata=new float[csvm.getVarCount()];
            sv.get(0, 0, svdata);
            detectormat.put(0, 0, svdata);
 double[] rhodata= {-rho};
            detectormat.put(0, csvm.getVarCount(), rhodata);
semoryang gravatar imagesemoryang ( 2017-08-29 20:48:37 -0600 )edit

HOGDescriptor d=new HOGDescriptor(); d.setSVMDetector(detectormat);

Program got error here. OpenCV Error: Assertion failed (checkDetectorSize()) in cv::HOGDescriptor::setSVMDetector, file C:\build\master_winpack-bindings-win64-vc14-static\opencv\modules\objdetect\src\hog.cpp, line 117 I think the size of svmdetector would be 1*csvm.getVarCount()+1 Isn't that right?

semoryang gravatar imagesemoryang ( 2017-08-29 20:50:42 -0600 )edit

you'll have to setup the HOGDescriptor in the same way, you did for training (winSize and all) before setting the svm vector (else the descriptorSize() does not match the size of the sv)

(your assumptions are correct, btw.)

berak gravatar imageberak ( 2017-08-29 22:30:28 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2017-08-28 03:59:11 -0600

Seen: 243 times

Last updated: Aug 29 '17