diff --git a/src/main/java/com/yuxue/controller/FaceController.java b/src/main/java/com/yuxue/controller/FaceController.java index c3aee1dd..3b5f4cd7 100644 --- a/src/main/java/com/yuxue/controller/FaceController.java +++ b/src/main/java/com/yuxue/controller/FaceController.java @@ -4,6 +4,8 @@ import org.opencv.core.Core; import org.opencv.core.Mat; import org.opencv.core.MatOfRect; import org.opencv.core.Rect; +import org.opencv.imgcodecs.Imgcodecs; +import org.opencv.imgproc.Imgproc; import org.opencv.objdetect.CascadeClassifier; /** @@ -18,25 +20,20 @@ public class FaceController { } public static void main(String[] args) { - FaceController demo = new FaceController(); - demo.run(); - } - - public void run() { - - // Create a face detector from the cascade file in the resources directory. + + // Create a face detector from the cascade file in the resources directory. // 创建识别器 - CascadeClassifier faceDetector = new CascadeClassifier(getClass().getResource("/haarcascades/lbpcascade_frontalface.xml").getPath()); + CascadeClassifier faceDetector = new CascadeClassifier("/src/main/resources/haarcascades/lbpcascade_frontalface.xml"); - String imgPath = "/src/main/resources/DetectFace/huge.jpg"; - Mat image = null; //Highgui.imread(imgPath,3); + String imgPath = "/src/main/resources/DetectFace/AverageMaleFace.jpg"; + Mat image = Imgcodecs.imread(imgPath); - String filename = "D:/DetectFace/huge1.png"; - // System.out.println(String.format("Writing %s", filename)); + Mat dst = new Mat(); + Imgproc.Canny(image, dst, 130, 250); // Detect faces in the image. MatOfRect is a special container class for Rect. MatOfRect faceDetections = new MatOfRect(); - faceDetector.detectMultiScale(image, faceDetections); + faceDetector.detectMultiScale(dst, faceDetections); System.out.println(String.format("识别出 %s 张人脸", faceDetections.toArray().length)); @@ -48,6 +45,5 @@ public class FaceController { // Save the visualized detection. // System.out.println(String.format("Writing %s", filename)); //Highgui.imwrite(filename, image); - return; } } diff --git a/src/main/java/com/yuxue/easypr/core/PlateJudge.java b/src/main/java/com/yuxue/easypr/core/PlateJudge.java index ad89fc11..17483796 100644 --- a/src/main/java/com/yuxue/easypr/core/PlateJudge.java +++ b/src/main/java/com/yuxue/easypr/core/PlateJudge.java @@ -9,6 +9,9 @@ import org.bytedeco.javacpp.opencv_core.Mat; import org.bytedeco.javacpp.opencv_core.Rect; import org.bytedeco.javacpp.opencv_core.Size; import org.bytedeco.javacpp.opencv_ml.SVM; +import org.opencv.core.CvType; +import org.opencv.imgcodecs.Imgcodecs; +import org.opencv.imgproc.Imgproc; /** @@ -17,9 +20,9 @@ import org.bytedeco.javacpp.opencv_ml.SVM; * @date 2020-04-26 15:21 */ public class PlateJudge { - + private SVM svm = SVM.create(); - + /** * EasyPR的getFeatures回调函数, 用于从车牌的image生成svm的训练特征features */ @@ -29,13 +32,14 @@ public class PlateJudge { * 模型存储路径 */ private String path = "res/model/svm.xml"; - + public PlateJudge() { svm.clear(); - svm=SVM.loadSVM(path, "svm"); + // svm=SVM.loadSVM(path, "svm"); + svm=SVM.load(path); } - + /** * 对单幅图像进行SVM判断 * @param inMat @@ -43,13 +47,21 @@ public class PlateJudge { */ public int plateJudge(final Mat inMat) { Mat features = this.features.getHistogramFeatures(inMat); - // 通过直方图均衡化后的彩色图进行预测 Mat p = features.reshape(1, 1); p.convertTo(p, opencv_core.CV_32FC1); float ret = svm.predict(features); - return (int) ret; + + /*opencv_imgproc.cvtColor(inMat, inMat, Imgproc.COLOR_BGR2GRAY); + Mat features = new Mat(); + opencv_imgproc.Canny(inMat, features, 130, 250); + + Mat p = features.reshape(1, 1); + p.convertTo(p, opencv_core.CV_32FC1); + + float ret = svm.predict(p); + return (int) ret;*/ } /** @@ -81,7 +93,7 @@ public class PlateJudge { return 0; } - + public void setModelPath(String path) { this.path = path; } @@ -89,5 +101,5 @@ public class PlateJudge { public final String getModelPath() { return path; } - + } diff --git a/src/test/java/com/yuxue/test/PlateDetectTrainTest.java b/src/test/java/com/yuxue/test/PlateDetectTrainTest.java index aa73e640..cc9a5b68 100644 --- a/src/test/java/com/yuxue/test/PlateDetectTrainTest.java +++ b/src/test/java/com/yuxue/test/PlateDetectTrainTest.java @@ -38,20 +38,22 @@ public class PlateDetectTrainTest { } public static void main(String[] arg) { - // 用于存放所有样本矩阵 - Mat trainingDataMat = null; - + + // 正样本 // 136 × 36 像素 训练的源图像文件要相同大小 List imgList1 = FileUtil.listFile(new File(DEFAULT_PATH + "/learn/HasPlate"), Constant.DEFAULT_TYPE, false); - + // 负样本 // 136 × 36 像素 训练的源图像文件要相同大小 List imgList2 = FileUtil.listFile(new File(DEFAULT_PATH + "/learn/NoPlate"), Constant.DEFAULT_TYPE, false); - + // 标记:正样本用 0 表示,负样本用 1 表示。 int labels[] = createLabelArray(imgList1.size(), imgList2.size()); - + // 图片数量 int sample_num = labels.length; + + // 用于存放所有样本矩阵 + Mat trainingDataMat = null; // 存放标记的Mat,每个图片都要给一个标记 Mat labelsMat = new Mat(sample_num, 1, CvType.CV_32SC1); @@ -66,14 +68,13 @@ public class PlateDetectTrainTest { } else { path = imgList2.get(i - imgList1.size()).getAbsolutePath(); } - - Mat src = Imgcodecs.imread(path); - // 创建一个行数为18(正负样本总数量为18),列数为 rows*cols 的矩阵 + Mat src = Imgcodecs.imread(path); + + // 创建一个行数为sample_num, 列数为 rows*cols 的矩阵 if (trainingDataMat == null) { trainingDataMat = new Mat(sample_num, src.rows() * src.cols(), CvType.CV_32FC1);// CV_32FC1 是规定的训练用的图片格式。 } - // 转成灰度图并检测边缘 // 这里是为了过滤不需要的特征,减少训练时间。实际处理按情况论。 Imgproc.cvtColor(src, src, Imgproc.COLOR_BGR2GRAY); // 转成灰度图 Mat dst = new Mat(src.rows(), src.cols(), src.type());// 此时的 dst 是8u1c。 @@ -104,7 +105,7 @@ public class PlateDetectTrainTest { * @param labelsMat 存放标识的矩阵 */ public static void MySvm(Mat trainingDataMat, Mat labelsMat, String savePath) { - + // 配置SVM训练器参数 TermCriteria criteria = new TermCriteria(TermCriteria.EPS + TermCriteria.MAX_ITER, 20000, 0.0001); SVM svm = SVM.create(); @@ -121,14 +122,14 @@ public class PlateDetectTrainTest { TrainData td = TrainData.create(trainingDataMat, Ml.ROW_SAMPLE, labelsMat);// 类封装的训练数据 boolean success = svm.train(td.getSamples(), Ml.ROW_SAMPLE, td.getResponses());// 训练统计模型 System.err.println("Svm training result: " + success); - + svm.save(savePath);// 保存模型 } - - + + public static int[] createLabelArray(Integer i1, Integer i2) { int labels[] = new int[i1 + i2]; - + for (int i = 0; i < labels.length; i++) { if(i < i1) { labels[i] = 0; diff --git a/src/test/java/com/yuxue/test/PlatePridectTest.java b/src/test/java/com/yuxue/test/PlatePridectTest.java index 393f732f..5e5bfd0f 100644 --- a/src/test/java/com/yuxue/test/PlatePridectTest.java +++ b/src/test/java/com/yuxue/test/PlatePridectTest.java @@ -28,7 +28,6 @@ public class PlatePridectTest { static { System.loadLibrary(Core.NATIVE_LIBRARY_NAME); } - public static void main(String[] args) { diff --git a/src/test/java/com/yuxue/test/trainsvm.java b/src/test/java/com/yuxue/test/trainsvm.java new file mode 100644 index 00000000..873d8083 --- /dev/null +++ b/src/test/java/com/yuxue/test/trainsvm.java @@ -0,0 +1,98 @@ +package com.yuxue.test; + +import java.io.File; +import java.util.ArrayList; + +import org.junit.Test; +import org.opencv.core.Core; +import org.opencv.core.CvType; +import org.opencv.core.Mat; +import org.opencv.core.TermCriteria; +import org.opencv.imgcodecs.Imgcodecs; +import org.opencv.ml.Ml; +import org.opencv.ml.SVM; +import org.opencv.ml.TrainData; + + +/** + * 网上找来的训练方案 + * @author yuxue + * @date 2020-05-13 16:53 + */ +public class trainsvm { + static { + System.loadLibrary(Core.NATIVE_LIBRARY_NAME); + } + + // 默认的训练操作的根目录 + private static final String DEFAULT_PATH = "D:/PlateDetect/train/plate_detect_svm/"; + + //存储训练集 + static ArrayList trainingImages = new ArrayList(); + //存储标签 + static ArrayList trainingLabels = new ArrayList(); + + public static void main(String[] args) { + + openFile(1, DEFAULT_PATH + "/learn/HasPlate"); + openFile(0, DEFAULT_PATH + "/learn/NoPlate"); + Mat srcImgs = new Mat(); + Mat flags = new Mat(trainingLabels.size(), 1, CvType.CV_32SC1); + + Core.vconcat(trainingImages, srcImgs); // 样本数量不能太大,trainingImages.size有限制 + + for (int i = 0; i < trainingLabels.size(); i++) { + int[] val = { trainingLabels.get(i) }; + flags.put(i, 0, val); + } + SVM svm = SVM.create(); + svm.setKernel(SVM.LINEAR); + svm.setType(SVM.C_SVC); + svm.setGamma(1); + svm.setC(1); + svm.setCoef0(0); + svm.setNu(0); + svm.setP(0); + svm.setTermCriteria(new TermCriteria(TermCriteria.MAX_ITER, 20000, 0.0001)); + TrainData trainData = TrainData.create(srcImgs, Ml.ROW_SAMPLE, flags); + boolean success = svm.train(trainData); + System.out.println(success); + svm.save( DEFAULT_PATH + "svm.xml"); + + } + + //读取本地文件 + public static void openFile(int flag, String path) { + File file = new File(path); + File[] files = file.listFiles(); + int i = 0; + for (File file2 : files) { + Mat input = Imgcodecs.imread(file2.getPath(), 0); + input.convertTo(input, CvType.CV_32FC1); + Mat reshape = input.reshape(0, 1); + // System.out.println(input.dump()); + trainingImages.add(reshape); + trainingLabels.add(flag); + i++; + if(i >100) { + break; + } + } + } + + @Test + public void test1() { + + // 测试训练的效果 + SVM svm = SVM.load("E:\\svmTrain\\bp.xml"); + Mat responseMat = new Mat(); + Mat imread = Imgcodecs.imread("C:\\Users\\98432\\Desktop\\platetest\\NoPlate\\S22_KG2187_3.jpg", 0); + imread.convertTo(imread, CvType.CV_32FC1); + Mat reshape = imread.reshape(0, 1); + svm.predict(reshape, responseMat, 0); + System.out.println(responseMat.dump()); + + + } + +} \ No newline at end of file