public class Svm_train { /** * SVM训练 */ public void svm_train(){ Integer ITERATION_NUM = 3000; String traintxt = "E:\\biyesheji\\image\\traindata.txt";//行人 //String traintxt = "E:\\biyesheji\\image\\traindata2.txt";//人脸 ArrayList<String> img_path = new ArrayList<String>(); ArrayList<Float> img_label = new ArrayList<Float>(); //System.loadLibrary(Core.NATIVE_LIBRARY_NAME); System.load("E:\\biyesheji\\opencv\\build\\java\\x64\\opencv_java330.dll"); System.out.println("类库加载成功·"); try { BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(new File(traintxt)), "UTF-8")); //System.out.println("读取文件"); String linetxt = null; Integer nline = 0; while((linetxt = br.readLine()) !=null){ nline++; String []path_label = linetxt.split("\t"); //System.out.println(path_label[0] + ' ' + path_label[1]); img_path.add(path_label[0]); img_label.add(Float.valueOf(path_label[1]).floatValue()); } br.close(); //一个block内有4个cell,每个cell含9维特征向量,故每个block就由4x9=36维特征向量来表征 //128x64(高128,宽64),即有(128÷8)x(64÷8)=16x8个cell,也即有15x7个block //在提取每个窗口的HOG特征,则可得到105x36=3780维HOG特征向量 Integer SAMPLE_COUNT = nline; //样本数 Integer PICTURE_FEATURE_DIM = 3780;//图片特征维数,64*64(1764),64*128(3780),128*128(8100) //Integer PICTURE_FEATURE_DIM = 1764;//人脸 Mat data_mat = new Mat(SAMPLE_COUNT, PICTURE_FEATURE_DIM, CvType.CV_32FC1);//行,列,类型 Mat res_mat = new Mat(SAMPLE_COUNT, 1, CvType.CV_32SC1); //svm descriptors ArrayList<float[]> descriptors = new ArrayList<float[]>(); for (Integer i=0;i<img_path.size();i++){ System.out.println("GetHog:"+img_path.get(i)); Mat src = Imgcodecs.imread(img_path.get(i)); if(src.empty()){ System.out.println(img_path.get(i)); throw new Exception("no such picture"); } if(img_label.get(i)==1) { if(src.cols()>64 || src.rows()>128)//行人128 { //去掉上下左右16个像素 Rect Roi=new Rect(new Point(16,16),new Size(64,128));//行人128 Mat image= src.submat(Roi);//子图 HOGDescriptor hog = new HOGDescriptor(new Size(64, 128), new Size(16, 16), new Size(8, 8), new Size(8, 8), 9);//行人128 MatOfFloat descriptorsOfMat = new MatOfFloat(); hog.compute(image, descriptorsOfMat);//调用计算函数 float[] descriptor = descriptorsOfMat.toArray();//一列 descriptors.add(descriptor); }else{ HOGDescriptor hog = new HOGDescriptor(new Size(64, 128), new Size(16, 16), new Size(8, 8), new Size(8, 8), 9);//行人 //HOGDescriptor hog = new HOGDescriptor(new Size(64, 64), new Size(16, 16), new Size(8, 8), new Size(8, 8), 9);//人脸 MatOfFloat descriptorsOfMat = new MatOfFloat(); hog.compute(src, descriptorsOfMat);//调用计算函数 float[] descriptor = descriptorsOfMat.toArray();//一列 descriptors.add(descriptor); } }else if(img_label.get(i)==0){ //Hog特征,窗口大小(宽,高),块大小,块滑动增量,胞元大小,梯度方向数 HOGDescriptor hog = new HOGDescriptor(new Size(64, 128), new Size(16, 16), new Size(8, 8), new Size(8, 8), 9);//行人128 MatOfFloat descriptorsOfMat = new MatOfFloat(); hog.compute(src, descriptorsOfMat);//调用计算函数 float[] descriptor = descriptorsOfMat.toArray();//一列 descriptors.add(descriptor); } } for (Integer m = 0; m < descriptors.size(); m++) { for (int n = 0; n < descriptors.get(m).length; n++) { data_mat.put(m, n, descriptors.get(m)[n]);//按行存储 } res_mat.put(m, 0, img_label.get(m));//一列向量 } System.out.println("开始训练。。。。。"); SVM svm = SVM.create(); svm.setType(SVM.C_SVC); svm.setKernel(SVM.LINEAR);//线性,HogDescriptor检测函数只支持线性检测 svm.setC(0.01); svm.setGamma(0.5); svm.setTermCriteria(new TermCriteria(TermCriteria.MAX_ITER, ITERATION_NUM, 1e-6)); svm.train(data_mat, Ml.ROW_SAMPLE, res_mat); svm.save("E:\\biyesheji\\image\\svm_java");//行人 //svm.save("E:\\biyesheji\\image\\svm_java2");//人脸 System.out.println("保存模型。。"); }catch (Exception e){ System.err.println("read err:" + e); } } //自定义检测器 public Mat myDetector() { System.loadLibrary(Core.NATIVE_LIBRARY_NAME); //SVM svm = SVM.load("E:\\biyesheji\\image\\svm_java2");//人脸 SVM svm = SVM.load("E:\\biyesheji\\image\\svm_java");//行人 //获取支持向量 Mat svecsmat = svm.getSupportVectors(); int numofsv = svecsmat.rows();//支持向量个数 System.out.println("支持向量个数:"+numofsv); int svdim = svm.getVarCount();//特征向量维数,即HOG描述子的维数 System.out.println("特征向量维数:"+svdim); //初始化alphamat和svindex Mat alphaMat = Mat.zeros(1, numofsv, CvType.CV_32F); Mat supportVectorMat = Mat.zeros(numofsv, svdim, CvType.CV_32FC1); Mat resultMat = Mat.zeros(1, svdim, CvType.CV_32FC1); Mat svidx = Mat.zeros(1, numofsv, CvType.CV_32F); //获得模型中的rho double rho = svm.getDecisionFunction(0, alphaMat, svidx); System.out.println("rho:"+rho); alphaMat.convertTo(alphaMat, CvType.CV_32F); //System.out.println(alphaMat.rows()+","+alphaMat.cols()); //将支持向量和alpha复制到对应Mat中 supportVectorMat = svecsmat; //alpha*src1*src2 + beta*src3,-1 * alphamat * supportVectorMat,点乘 Core.gemm(alphaMat, supportVectorMat, -1, new Mat(), 0, resultMat); //定义一个大一维的向量,便于后面添加rho Mat myDetector = new Mat(1, svdim+1, CvType.CV_32FC1); for(int j=0;j<svdim;j++) { double[] value2 = resultMat.get(0, j); myDetector.put(0, j, value2[0]); } //添加rho myDetector.put(0, svdim, rho); System.out.println("rho:"+myDetector.get(0, svdim)[0]); return myDetector; //开始检测 } } |