package com.yuxue.train; import java.util.*; import static org.bytedeco.javacpp.opencv_core.*; import static org.bytedeco.javacpp.opencv_ml.*; import org.bytedeco.javacpp.opencv_core; import org.bytedeco.javacpp.opencv_imgcodecs; import com.yuxue.easypr.core.Features; import com.yuxue.easypr.core.SVMCallback; import com.yuxue.util.Convert; import com.yuxue.util.FileUtil; /** * 鍩轰簬org.bytedeco.javacpp鍖呭疄鐜扮殑璁粌 * JavaCPP 鏄竴涓紑婧愬簱锛屽畠鎻愪緵浜嗗湪 Java 涓珮鏁堣闂湰鍦� C++鐨勬柟娉� * * 鍥剧墖璇嗗埆杞︾墝璁粌 * 璁粌鍑烘潵鐨勫簱鏂囦欢锛岀敤浜庡垽鏂垏鍥炬槸鍚﹀寘鍚溅鐗� * * 璁粌鐨剆vm.xml搴旂敤锛� * 1銆佹浛鎹es/model/svm.xml鏂囦欢 * 2銆佷慨鏀筩om.yuxue.easypr.core.PlateJudge.plateJudge(Mat) 鏂规硶 * 灏嗘牱鏈鐞嗘柟娉曞垏鎹竴涓嬶紝鍗冲皢瀵瑰簲琚敞閲婃帀鐨勬ā鍧椾唬鐮佸彇娑堟敞閲� * @author yuxue * @date 2020-05-14 22:16 */ public class SVMTrain1 { private SVMCallback callback = new Features(); // 榛樿鐨勮缁冩搷浣滅殑鏍圭洰褰� private static final String DEFAULT_PATH = "D:/PlateDetect/train/plate_detect_svm/"; // 璁粌妯″瀷鏂囦欢淇濆瓨浣嶇疆 private static final String MODEL_PATH = DEFAULT_PATH + "svm4.xml"; private static final String hasPlate = "HasPlate"; private static final String noPlate = "NoPlate"; public SVMTrain1() { } public SVMTrain1(SVMCallback callback) { this.callback = callback; } /** * 灏唋earn鏂囦欢澶逛笅鐨勫浘鐗囷紝杞瓨鍒皌ain test鏂囦欢澶逛笅锛屽尯鍒唄asPalte noPlate * 闅忔満閫夊彇bound%浣滀负璁粌鏁版嵁锛�30%浣滀负娴嬭瘯鏁版嵁 * @param bound * @param name */ private void learn2Plate(float bound, final String name) { final String filePath = DEFAULT_PATH + "learn/" + name; Vector files = new Vector(); //// 鑾峰彇璇ヨ矾寰勪笅鐨勬墍鏈夋枃浠� FileUtil.getFiles(filePath, files); int size = files.size(); if (0 == size) { System.err.println("褰撳墠鐩綍涓嬫病鏈夋枃浠�: " + filePath); return; } Collections.shuffle(files, new Random(new Date().getTime())); //// 闅忔満閫夊彇70%浣滀负璁粌鏁版嵁锛�30%浣滀负娴嬭瘯鏁版嵁 int boundry = (int) (bound * size); // 閲嶆柊鍒涘缓鐩綍 FileUtil.recreateDir(DEFAULT_PATH + "train/" + name); FileUtil.recreateDir(DEFAULT_PATH + "test/" + name); for (int i = 0; i < boundry; i++) { Mat img = opencv_imgcodecs.imread(files.get(i)); String str = DEFAULT_PATH + "train/" + name + "/" + name + "_" + Integer.valueOf(i).toString() + ".jpg"; opencv_imgcodecs.imwrite(str, img); } for (int i = boundry; i < size; i++) { Mat img = opencv_imgcodecs.imread(files.get(i)); String str = DEFAULT_PATH + "test/" + name + "/" + name + "_" + Integer.valueOf(i).toString() + ".jpg"; opencv_imgcodecs.imwrite(str, img); } } /** * 鑾峰彇璁粌鍥剧墖 * @param trainingImages * @param trainingLabels * @param name */ private void getPlateTrain(Mat trainingImages, Vector trainingLabels, final String name, int label) { // int label = 1; final String filePath = DEFAULT_PATH + "train/" + name; Vector files = new Vector(); // 鑾峰彇璇ヨ矾寰勪笅鐨勬墍鏈夋枃浠� FileUtil.getFiles(filePath, files); int size = files.size(); if (null == files || size <= 0) { System.out.println("File not found in " + filePath); return; } for (int i = 0; i < size; i++) { // System.out.println(files.get(i)); Mat inMat = opencv_imgcodecs.imread(files.get(i)); // 璋冪敤鍥炶皟鍑芥暟鍐冲畾鐗瑰緛 // Mat features = this.callback.getHisteqFeatures(inMat); Mat features = this.callback.getHistogramFeatures(inMat); // 閫氳繃鐩存柟鍥惧潎琛″寲鍚庣殑褰╄壊鍥捐繘琛岄娴� Mat p = features.reshape(1, 1); p.convertTo(p, opencv_core.CV_32F); // 136 36 14688 1 鍙樻崲灏哄 // System.err.println(inMat.cols() + "\t" + inMat.rows() + "\t" + p.cols() + "\t" + p.rows()); trainingImages.push_back(p); // 鍚堝苟鎴愪竴寮犲浘鐗� trainingLabels.add(label); } } private void getPlateTest(MatVector testingImages, Vector testingLabels, final String name, int label) { // int label = 1; final String filePath = DEFAULT_PATH + "test/" + name; Vector files = new Vector(); FileUtil.getFiles(filePath, files); int size = files.size(); if (0 == size) { System.out.println("File not found in " + filePath); return; } System.out.println("get " + name + " test!"); for (int i = 0; i < size; i++) { Mat inMat = opencv_imgcodecs.imread(files.get(i)); testingImages.push_back(inMat); testingLabels.add(label); } } // ! 娴嬭瘯SVM鐨勫噯纭巼锛屽洖褰掔巼浠ュ強FScore public void getAccuracy(Mat testingclasses_preditc, Mat testingclasses_real) { int channels = testingclasses_preditc.channels(); System.out.println("channels: " + Integer.valueOf(channels).toString()); int nRows = testingclasses_preditc.rows(); System.out.println("nRows: " + Integer.valueOf(nRows).toString()); int nCols = testingclasses_preditc.cols() * channels; System.out.println("nCols: " + Integer.valueOf(nCols).toString()); int channels_real = testingclasses_real.channels(); System.out.println("channels_real: " + Integer.valueOf(channels_real).toString()); int nRows_real = testingclasses_real.rows(); System.out.println("nRows_real: " + Integer.valueOf(nRows_real).toString()); int nCols_real = testingclasses_real.cols() * channels; System.out.println("nCols_real: " + Integer.valueOf(nCols_real).toString()); double count_all = 0; double ptrue_rtrue = 0; double ptrue_rfalse = 0; double pfalse_rtrue = 0; double pfalse_rfalse = 0; for (int i = 0; i < nRows; i++) { final float predict = Convert.toFloat(testingclasses_preditc.ptr(i)); final float real = Convert.toFloat(testingclasses_real.ptr(i)); count_all++; // System.out.println("predict:" << predict).toString()); // System.out.println("real:" << real).toString()); if (predict == 1.0 && real == 1.0) ptrue_rtrue++; if (predict == 1.0 && real == 0) ptrue_rfalse++; if (predict == 0 && real == 1.0) pfalse_rtrue++; if (predict == 0 && real == 0) pfalse_rfalse++; } System.out.println("count_all: " + Double.valueOf(count_all).toString()); System.out.println("ptrue_rtrue: " + Double.valueOf(ptrue_rtrue).toString()); System.out.println("ptrue_rfalse: " + Double.valueOf(ptrue_rfalse).toString()); System.out.println("pfalse_rtrue: " + Double.valueOf(pfalse_rtrue).toString()); System.out.println("pfalse_rfalse: " + Double.valueOf(pfalse_rfalse).toString()); double precise = 0; if (ptrue_rtrue + ptrue_rfalse != 0) { precise = ptrue_rtrue / (ptrue_rtrue + ptrue_rfalse); System.out.println("precise: " + Double.valueOf(precise).toString()); } else { System.out.println("precise: NA"); } double recall = 0; if (ptrue_rtrue + pfalse_rtrue != 0) { recall = ptrue_rtrue / (ptrue_rtrue + pfalse_rtrue); System.out.println("recall: " + Double.valueOf(recall).toString()); } else { System.out.println("recall: NA"); } if (precise + recall != 0) { double F = (precise * recall) / (precise + recall); System.out.println("F: " + Double.valueOf(F).toString()); } else { System.out.println("F: NA"); } } /** * 璁粌 * @param dividePrepared * @return */ public int svmTrain(boolean dividePrepared) { Mat classes = new Mat(); Mat trainingData = new Mat(); Mat trainingImages = new Mat(); Vector trainingLabels = new Vector(); // 鍒嗗壊learn閲岀殑鏁版嵁鍒皌rain鍜宼est閲� // 浠庡簱閲岄潰閫夊彇璁粌鏍锋湰 if (!dividePrepared) { learn2Plate(0.1f, hasPlate); // 鎬ц兘涓嶅ソ鐨勬満鍣紝鏈�濂戒笉瑕佹寫閫夊お澶氱殑鏍锋湰锛岃繖涓柟妗堝お娑堣�楄祫婧愪簡銆� learn2Plate(0.1f, noPlate); } // System.err.println("Begin to get train data to memory"); getPlateTrain(trainingImages, trainingLabels, hasPlate, 0); getPlateTrain(trainingImages, trainingLabels, noPlate, 1); // System.err.println(trainingImages.cols()); trainingImages.copyTo(trainingData); trainingData.convertTo(trainingData, CV_32F); int[] labels = new int[trainingLabels.size()]; for (int i = 0; i < trainingLabels.size(); ++i) { labels[i] = trainingLabels.get(i).intValue(); } new Mat(labels).copyTo(classes); TrainData train_data = TrainData.create(trainingData, ROW_SAMPLE, classes); SVM svm = SVM.create(); try { TermCriteria criteria = new TermCriteria(TermCriteria.EPS + TermCriteria.MAX_ITER, 20000, 0.0001); svm.setTermCriteria(criteria); // 鎸囧畾 svm.setKernel(SVM.RBF); // 浣跨敤棰勫厛瀹氫箟鐨勫唴鏍稿垵濮嬪寲 svm.setType(SVM.C_SVC); // SVM鐨勭被鍨�,榛樿鏄細SVM.C_SVC svm.setGamma(0.1); // 鏍稿嚱鏁扮殑鍙傛暟 svm.setNu(0.1); // SVM浼樺寲闂鍙傛暟 svm.setC(1); // SVM浼樺寲闂鐨勫弬鏁癈 svm.setP(0.1); svm.setDegree(0.1); svm.setCoef0(0.1); svm.trainAuto(train_data, 10, SVM.getDefaultGrid(SVM.C), SVM.getDefaultGrid(SVM.GAMMA), SVM.getDefaultGrid(SVM.P), SVM.getDefaultGrid(SVM.NU), SVM.getDefaultGrid(SVM.COEF), SVM.getDefaultGrid(SVM.DEGREE), true); } catch (Exception err) { System.out.println(err.getMessage()); } System.out.println("Svm generate done!"); /*FileStorage fsTo = new FileStorage(MODEL_PATH, FileStorage.WRITE); svm.write(fsTo, "svm");*/ svm.save(MODEL_PATH); return 0; } // 娴嬭瘯 public int svmPredict() { SVM svm = SVM.create(); try { svm.clear(); // svm = SVM.loadSVM(MODEL_PATH, "svm"); svm = SVM.load(MODEL_PATH); } catch (Exception err) { System.err.println(err.getMessage()); return 0; // next predict requires svm } System.out.println("Begin to predict"); // Test SVM MatVector testingImages = new MatVector(); Vector testingLabels_real = new Vector(); // 灏嗘祴璇曟暟鎹姞杞藉叆鍐呭瓨 getPlateTest(testingImages, testingLabels_real, hasPlate, 0); getPlateTest(testingImages, testingLabels_real, noPlate, 1); double count_all = 0; double ptrue_rtrue = 0; double ptrue_rfalse = 0; double pfalse_rtrue = 0; double pfalse_rfalse = 0; long size = testingImages.size(); System.err.println(size); for (int i = 0; i < size; i++) { Mat inMat = testingImages.get(i); // Mat features = callback.getHisteqFeatures(inMat); Mat features = callback.getHistogramFeatures(inMat); Mat p = features.reshape(1, 1); p.convertTo(p, opencv_core.CV_32F); // System.out.println(p.cols() + "\t" + p.rows() + "\t" + p.type()); // samples.cols == var_count && samples.type() == CV_32F // var_count 鐨勫�间細鍦╯vm.xml搴撴枃浠朵腑鏈変綋鐜� float predoct = svm.predict(features); int predict = (int) predoct; // 棰勬湡鍊� int real = testingLabels_real.get(i); // 瀹為檯鍊� if (predict == 1 && real == 1) ptrue_rtrue++; if (predict == 1 && real == 0) ptrue_rfalse++; if (predict == 0 && real == 1) pfalse_rtrue++; if (predict == 0 && real == 0) pfalse_rfalse++; } count_all = size; System.out.println("Get the Accuracy!"); System.out.println("count_all: " + Double.valueOf(count_all).toString()); System.out.println("ptrue_rtrue: " + Double.valueOf(ptrue_rtrue).toString()); System.out.println("ptrue_rfalse: " + Double.valueOf(ptrue_rfalse).toString()); System.out.println("pfalse_rtrue: " + Double.valueOf(pfalse_rtrue).toString()); System.out.println("pfalse_rfalse: " + Double.valueOf(pfalse_rfalse).toString()); double precise = 0; if (ptrue_rtrue + ptrue_rfalse != 0) { precise = ptrue_rtrue / (ptrue_rtrue + ptrue_rfalse); System.out.println("precise: " + Double.valueOf(precise).toString()); } else System.out.println("precise: NA"); double recall = 0; if (ptrue_rtrue + pfalse_rtrue != 0) { recall = ptrue_rtrue / (ptrue_rtrue + pfalse_rtrue); System.out.println("recall: " + Double.valueOf(recall).toString()); } else System.out.println("recall: NA"); double Fsocre = 0; if (precise + recall != 0) { Fsocre = 2 * (precise * recall) / (precise + recall); System.out.println("Fsocre: " + Double.valueOf(Fsocre).toString()); } else System.out.println("Fsocre: NA"); return 0; } public static void main(String[] args) { SVMTrain1 s = new SVMTrain1(); s.svmTrain(true); s.svmPredict(); } }