From 3ae780df71e0b058886c29c2391f3540006b9a23 Mon Sep 17 00:00:00 2001 From: yuxue Date: Sat, 16 May 2020 21:17:56 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81=E7=BB=93?= =?UTF-8?q?=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/yuxue/aop/AroundMethod.java | 2 +- .../java/com/yuxue/constant/Constant.java | 98 ++++++--- .../com/yuxue/easypr/core/CharsIdentify.java | 81 +------- .../java/com/yuxue/easypr/core/CoreFunc.java | 3 +- src/main/java/com/yuxue/train/ANNTrain.java | 21 +- .../java/com/yuxue/train/PlateRecoTrain.java | 1 + .../java/com/yuxue/train/PlateRecoTrain1.java | 192 ------------------ src/main/java/com/yuxue/train/SVMTrain.java | 1 + 8 files changed, 96 insertions(+), 303 deletions(-) delete mode 100644 src/main/java/com/yuxue/train/PlateRecoTrain1.java diff --git a/src/main/java/com/yuxue/aop/AroundMethod.java b/src/main/java/com/yuxue/aop/AroundMethod.java index ff5626ec..5afeda8c 100644 --- a/src/main/java/com/yuxue/aop/AroundMethod.java +++ b/src/main/java/com/yuxue/aop/AroundMethod.java @@ -33,7 +33,7 @@ public class AroundMethod implements MethodInterceptor{ RetExclude re = methodInvocation.getMethod().getAnnotation(RetExclude.class); if(null != re && null != re.value()) { - // log.info("api添加了封装排除注解"); + log.info("api添加了封装排除注解"); return ret; } // log.info("封装返回值"); diff --git a/src/main/java/com/yuxue/constant/Constant.java b/src/main/java/com/yuxue/constant/Constant.java index b18d8769..34ee0697 100644 --- a/src/main/java/com/yuxue/constant/Constant.java +++ b/src/main/java/com/yuxue/constant/Constant.java @@ -1,5 +1,7 @@ package com.yuxue.constant; +import java.util.HashMap; +import java.util.Map; /** * 系统常量 @@ -8,33 +10,40 @@ package com.yuxue.constant; */ public class Constant { - public static final String UTF8 = "UTF-8"; - - // 车牌识别, 默认车牌图片保存路径 - // public static String DEFAULT_DIR = "./PlateDetect/"; // 使用项目的相对路径 - public static String DEFAULT_DIR = "D:/PlateDetect/"; // 使用盘符的绝对路径 - - // 车牌识别, 默认车牌图片处理过程temp路径 - // public static String DEFAULT_TEMP_DIR = "./PlateDetect/temp/"; // 使用项目的相对路径 - public static String DEFAULT_TEMP_DIR = "D:/PlateDetect/temp/"; // 使用盘符的绝对路径 - - // 车牌识别,默认处理图片类型 - public static String DEFAULT_TYPE = "png,jpg,jpeg"; - - // 车牌识别,判断是否车牌的正则表达式 - public static String plateReg = "([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}(([0-9]{5}[DF])|([DF]([A-HJ-NP-Z0-9])[0-9]{4})))|([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳]{1})"; - - public static int predictSize = 10; - - public static int neurons = 40; - - // 中国车牌; 34个字符; 没有 字母I、字母O - public final static char strCharacters[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + public static final String UTF8 = "UTF-8"; + + // 车牌识别, 默认车牌图片保存路径 + // public static String DEFAULT_DIR = "./PlateDetect/"; // 使用项目的相对路径 + public static String DEFAULT_DIR = "D:/PlateDetect/"; // 使用盘符的绝对路径 + + // 车牌识别, 默认车牌图片处理过程temp路径 + // public static String DEFAULT_TEMP_DIR = "./PlateDetect/temp/"; // 使用项目的相对路径 + public static String DEFAULT_TEMP_DIR = "D:/PlateDetect/temp/"; // 使用盘符的绝对路径 + + // 车牌识别,默认处理图片类型 + public static String DEFAULT_TYPE = "png,jpg,jpeg"; + + public static String DEFAULT_ANN_PATH = "res/model/ann.xml"; + + + + // 车牌识别,判断是否车牌的正则表达式 + public static String plateReg = "([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}(([0-9]{5}[DF])|([DF]([A-HJ-NP-Z0-9])[0-9]{4})))|([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳]{1})"; + + public static int predictSize = 10; + + public static int neurons = 40; + + // 中国车牌; 34个字符; 没有 字母I、字母O + public final static char strCharacters[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', /* 没有I */ 'J', 'K', 'L', 'M', 'N', /* 没有O */'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' }; - // 并不全面,有些省份没有训练数据所以没有字符 + // 没有I和0, 10个数字与24个英文字符之和 + public final static Integer numCharacter = strCharacters.length; + + // 并不全面,有些省份没有训练数据所以没有字符 // 有些后面加数字2的表示在训练时常看到字符的一种变形,也作为训练数据存储 - public final static String strChinese[] = { + public final static String strChinese[] = { "zh_cuan", /*川*/ "zh_e", /*鄂*/ "zh_gan", /*赣*/ @@ -67,7 +76,46 @@ public class Constant { "zh_zang", /*藏*/ "zh_zhe" /*浙*/ }; - + /* 34+31=65 34个字符跟31个汉字 */ + public final static Integer numAll = strCharacters.length + strChinese.length; + + public static Map KEY_CHINESE_MAP = new HashMap(); + static { + if (KEY_CHINESE_MAP.isEmpty()) { + KEY_CHINESE_MAP.put("zh_cuan", "川"); + KEY_CHINESE_MAP.put("zh_e", "鄂"); + KEY_CHINESE_MAP.put("zh_gan", "赣"); + KEY_CHINESE_MAP.put("zh_gan1", "甘"); + KEY_CHINESE_MAP.put("zh_gui", "贵"); + KEY_CHINESE_MAP.put("zh_gui1", "桂"); + KEY_CHINESE_MAP.put("zh_hei", "黑"); + KEY_CHINESE_MAP.put("zh_hu", "沪"); + KEY_CHINESE_MAP.put("zh_ji", "冀"); + KEY_CHINESE_MAP.put("zh_jin", "津"); + KEY_CHINESE_MAP.put("zh_jing", "京"); + KEY_CHINESE_MAP.put("zh_jl", "吉"); + KEY_CHINESE_MAP.put("zh_liao", "辽"); + KEY_CHINESE_MAP.put("zh_lu", "鲁"); + KEY_CHINESE_MAP.put("zh_meng", "蒙"); + KEY_CHINESE_MAP.put("zh_min", "闽"); + KEY_CHINESE_MAP.put("zh_ning", "宁"); + KEY_CHINESE_MAP.put("zh_qing", "青"); + KEY_CHINESE_MAP.put("zh_qiong", "琼"); + KEY_CHINESE_MAP.put("zh_shan", "陕"); + KEY_CHINESE_MAP.put("zh_su", "苏"); + KEY_CHINESE_MAP.put("zh_sx", "晋"); + KEY_CHINESE_MAP.put("zh_wan", "皖"); + KEY_CHINESE_MAP.put("zh_xiang", "湘"); + KEY_CHINESE_MAP.put("zh_xin", "新"); + KEY_CHINESE_MAP.put("zh_yu", "豫"); + KEY_CHINESE_MAP.put("zh_yu1", "渝"); + KEY_CHINESE_MAP.put("zh_yue", "粤"); + KEY_CHINESE_MAP.put("zh_yun", "云"); + KEY_CHINESE_MAP.put("zh_zang", "藏"); + KEY_CHINESE_MAP.put("zh_zhe", "浙"); + } + } + } diff --git a/src/main/java/com/yuxue/easypr/core/CharsIdentify.java b/src/main/java/com/yuxue/easypr/core/CharsIdentify.java index 0b9d5ad5..d55a3431 100644 --- a/src/main/java/com/yuxue/easypr/core/CharsIdentify.java +++ b/src/main/java/com/yuxue/easypr/core/CharsIdentify.java @@ -1,10 +1,6 @@ package com.yuxue.easypr.core; -import static org.bytedeco.javacpp.opencv_core.CV_32FC1; - -import java.util.HashMap; -import java.util.Map; - +import org.bytedeco.javacpp.opencv_core; import org.bytedeco.javacpp.opencv_core.Mat; import org.bytedeco.javacpp.opencv_ml.ANN_MLP; @@ -19,66 +15,19 @@ import com.yuxue.util.Convert; */ public class CharsIdentify { - private final static int numCharacter = 34; // 没有I和0, 10个数字与24个英文字符之和 - - private final static int numAll = 65; /* 34+31=65 34个字符跟31个汉字 */ - private ANN_MLP ann=ANN_MLP.create(); - private String path = "res/model/ann.xml"; - - static boolean hasPrint = false; - - private Map map = new HashMap(); - public CharsIdentify() { - loadModel(); // 加载ann配置文件 - - if (this.map.isEmpty()) { - map.put("zh_cuan", "川"); - map.put("zh_e", "鄂"); - map.put("zh_gan", "赣"); - map.put("zh_gan1", "甘"); - map.put("zh_gui", "贵"); - map.put("zh_gui1", "桂"); - map.put("zh_hei", "黑"); - map.put("zh_hu", "沪"); - map.put("zh_ji", "冀"); - map.put("zh_jin", "津"); - map.put("zh_jing", "京"); - map.put("zh_jl", "吉"); - map.put("zh_liao", "辽"); - map.put("zh_lu", "鲁"); - map.put("zh_meng", "蒙"); - map.put("zh_min", "闽"); - map.put("zh_ning", "宁"); - map.put("zh_qing", "青"); - map.put("zh_qiong", "琼"); - map.put("zh_shan", "陕"); - map.put("zh_su", "苏"); - map.put("zh_sx", "晋"); - map.put("zh_wan", "皖"); - map.put("zh_xiang", "湘"); - map.put("zh_xin", "新"); - map.put("zh_yu", "豫"); - map.put("zh_yu1", "渝"); - map.put("zh_yue", "粤"); - map.put("zh_yun", "云"); - map.put("zh_zang", "藏"); - map.put("zh_zhe", "浙"); - } - } - - private void loadModel() { - loadModel(this.path); + loadModel(Constant.DEFAULT_ANN_PATH); } public void loadModel(String s) { this.ann.clear(); - //ann=ANN_MLP.loadANN_MLP(s, "ann"); // 加载ann配置文件 图像转文字的训练库文件 + // 加载ann配置文件 图像转文字的训练库文件 + //ann=ANN_MLP.loadANN_MLP(s, "ann"); ann = ANN_MLP.load(s); } - + /** * @param input @@ -95,20 +44,20 @@ public class CharsIdentify { if (!isChinese) { result = String.valueOf(Constant.strCharacters[index]); } else { - String s = Constant.strChinese[index - numCharacter]; - result = map.get(s); + String s = Constant.strChinese[index - Constant.numCharacter]; + result = Constant.KEY_CHINESE_MAP.get(s); // 编码转中文 } return result; } private int classify(final Mat f, final Boolean isChinses, final Boolean isSpeci) { int result = -1; - Mat output = new Mat(1, numAll, CV_32FC1); + Mat output = new Mat(1, Constant.numAll, opencv_core.CV_32FC1); ann.predict(f, output, 0); // 预测结果 - int ann_min = (!isChinses) ? ((isSpeci) ? 10 : 0) : numCharacter; - int ann_max = (!isChinses) ? numCharacter : numAll; + int ann_min = (!isChinses) ? ((isSpeci) ? 10 : 0) : Constant.numCharacter; + int ann_max = (!isChinses) ? Constant.numCharacter : Constant.numAll; float maxVal = -2; @@ -122,14 +71,4 @@ public class CharsIdentify { return result; } - public final void setModelPath(String path) { - this.path = path; - } - - public final String getModelPath() { - return this.path; - } - - - } diff --git a/src/main/java/com/yuxue/easypr/core/CoreFunc.java b/src/main/java/com/yuxue/easypr/core/CoreFunc.java index cd6cd40a..0d91855a 100644 --- a/src/main/java/com/yuxue/easypr/core/CoreFunc.java +++ b/src/main/java/com/yuxue/easypr/core/CoreFunc.java @@ -23,8 +23,9 @@ import com.yuxue.enumtype.PlateColor; /** - * @author lin.yao * + * @author yuxue + * @date 2020-05-16 21:09 */ public class CoreFunc { diff --git a/src/main/java/com/yuxue/train/ANNTrain.java b/src/main/java/com/yuxue/train/ANNTrain.java index 5543e86c..485d4a01 100644 --- a/src/main/java/com/yuxue/train/ANNTrain.java +++ b/src/main/java/com/yuxue/train/ANNTrain.java @@ -1,6 +1,5 @@ package com.yuxue.train; - import java.util.Vector; import org.opencv.core.Core; @@ -23,7 +22,7 @@ import com.yuxue.util.FileUtil; * 基于org.opencv包实现的训练 * * 图片文字识别训练 - * 训练出来的库文件,用于判断切图是否包含车牌 + * 训练出来的库文件,用于识别图片中的文字 * * 训练的ann.xml应用: * 1、替换res/model/ann.xml文件 @@ -40,14 +39,13 @@ public class ANNTrain { System.loadLibrary(Core.NATIVE_LIBRARY_NAME); } - private final int numCharacter = Constant.strCharacters.length; - // 默认的训练操作的根目录 private static final String DEFAULT_PATH = "D:/PlateDetect/train/chars_recognise_ann/"; // 训练模型文件保存位置 private static final String MODEL_PATH = DEFAULT_PATH + "ann.xml"; + public static float[] projectedHistogram(final Mat img, Direction direction) { int sz = 0; switch (direction) { @@ -120,7 +118,7 @@ public class ANNTrain { Mat samples = new Mat(); // 使用push_back,行数列数不能赋初始值 Vector trainingLabels = new Vector(); // 加载数字及字母字符 - for (int i = 0; i < numCharacter; i++) { + for (int i = 0; i < Constant.numCharacter; i++) { String str = DEFAULT_PATH + "learn/" + Constant.strCharacters[i]; Vector files = new Vector(); FileUtil.getFiles(str, files); @@ -147,22 +145,19 @@ public class ANNTrain { // System.err.println(files.get(j)); // 文件名不能包含中文 Mat f = features(img, _predictsize); samples.push_back(f); - trainingLabels.add(i + numCharacter); + trainingLabels.add(i + Constant.numCharacter); } } //440 vhist.length + hhist.length + lowData.cols() * lowData.rows(); // CV_32FC1 CV_32SC1 CV_32F - Mat classes = new Mat(trainingLabels.size(), 65, CvType.CV_32F); + Mat classes = new Mat(trainingLabels.size(), Constant.numAll, CvType.CV_32F); float[] labels = new float[trainingLabels.size()]; for (int i = 0; i < labels.length; ++i) { - // labels[i] = trainingLabels.get(i).intValue(); classes.put(i, trainingLabels.get(i), 1.f); } - - // classes.put(0, 0, labels); // samples.type() == CV_32F || samples.type() == CV_32S TrainData train_data = TrainData.create(samples, Ml.ROW_SAMPLE, classes); @@ -194,11 +189,12 @@ public class ANNTrain { Vector files = new Vector(); FileUtil.getFiles(DEFAULT_PATH + "test/", files); - int i = 0; for (String string : files) { Mat img = Imgcodecs.imread(string, 0); Mat f = features(img, Constant.predictSize); + // 140 predictSize = 10; vhist.length + hhist.length + lowData.cols() * lowData.rows(); + // 440 predictSize = 20; Mat output = new Mat(1, 140, CvType.CV_32F); //ann.predict(f, output, 0); // 预测结果 System.err.println(string + "===>" + (int) ann.predict(f, output, 0)); @@ -207,7 +203,6 @@ public class ANNTrain { // System.err.println(string + "===>" + output.get(0, 0)[0]); } - } public static void main(String[] args) { @@ -216,7 +211,7 @@ public class ANNTrain { // 这里演示只训练model文件夹下的ann.xml,此模型是一个predictSize=10,neurons=40的ANN模型 // 可根据需要训练不同的predictSize或者neurons的ANN模型 // 根据机器的不同,训练时间不一样,但一般需要10分钟左右,所以慢慢等一会吧。 - annT.train(Constant.predictSize, Constant.neurons); + // annT.train(Constant.predictSize, Constant.neurons); annT.predict(); diff --git a/src/main/java/com/yuxue/train/PlateRecoTrain.java b/src/main/java/com/yuxue/train/PlateRecoTrain.java index 7e83012c..969aa4a4 100644 --- a/src/main/java/com/yuxue/train/PlateRecoTrain.java +++ b/src/main/java/com/yuxue/train/PlateRecoTrain.java @@ -19,6 +19,7 @@ import com.yuxue.util.FileUtil; /** * 基于org.opencv官方包实现的训练 * + * * windows下环境配置: * 1、官网下载对应版本的openvp:https://opencv.org/releases/page/2/ 当前使用4.0.1版本 * 2、双击exe文件安装,将 安装目录下\build\java\x64\opencv_java401.dll 拷贝到\build\x64\vc14\bin\目录下 diff --git a/src/main/java/com/yuxue/train/PlateRecoTrain1.java b/src/main/java/com/yuxue/train/PlateRecoTrain1.java deleted file mode 100644 index 88e610eb..00000000 --- a/src/main/java/com/yuxue/train/PlateRecoTrain1.java +++ /dev/null @@ -1,192 +0,0 @@ -package com.yuxue.train; - -import java.io.File; -import java.util.List; - -import org.bytedeco.javacpp.opencv_core; -import org.bytedeco.javacpp.opencv_core.Mat; -import org.bytedeco.javacpp.opencv_core.TermCriteria; -import org.bytedeco.javacpp.opencv_imgcodecs; -import org.bytedeco.javacpp.opencv_imgproc; -import org.bytedeco.javacpp.opencv_ml.SVM; -import org.bytedeco.javacpp.opencv_ml.TrainData; -import org.opencv.ml.Ml; - -import com.yuxue.constant.Constant; -import com.yuxue.easypr.core.Features; -import com.yuxue.easypr.core.SVMCallback; -import com.yuxue.util.FileUtil; - -/** - * 基于org.bytedeco.javacpp包实现的训练 - * - * 图片识别车牌训练 - * 训练出来的库文件,用于判断切图是否包含车牌 - * - * 训练的svm.xml应用: - * 1、替换res/model/svm.xml文件 - * 2、修改com.yuxue.easypr.core.PlateJudge.plateJudge(Mat) 方法 - * 将样本处理方法切换一下,即将对应被注释掉的模块代码取消注释 - * @author yuxue - * @date 2020-05-13 10:10 - */ -public class PlateRecoTrain1 { - - 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 + "svm.xml"; - - - public static void main(String[] arg) { - // 训练, 生成svm.xml库文件 - // train(); - - // 识别,判断样本文件是否是车牌 - pridect(); - } - - - public static void train() { - - // 正样本 // 136 × 36 像素 训练的源图像文件要相同大小 - List imgList0 = FileUtil.listFile(new File(DEFAULT_PATH + "/learn/HasPlate"), Constant.DEFAULT_TYPE, false); - - // 负样本 // 136 × 36 像素 训练的源图像文件要相同大小 - List imgList1 = FileUtil.listFile(new File(DEFAULT_PATH + "/learn/NoPlate"), Constant.DEFAULT_TYPE, false); - - // 标记:正样本用 0 表示,负样本用 1 表示。 - int labels[] = createLabelArray(imgList0.size(), imgList1.size()); - int sample_num = labels.length; // 图片数量 - - // 用于存放所有样本的矩阵 - Mat trainingDataMat = null; - - // 存放标记的Mat,每个图片都要给一个标记 - Mat labelsMat = new Mat(sample_num, 1, opencv_core.CV_32FC1); - // labelsMat.put(0, 0, labels); - - for (int i = 0; i < sample_num; i++) { // 遍历所有的正负样本,处理样本用于生成训练的库文件 - String path = ""; - if(i < imgList0.size()) { - path = imgList0.get(i).getAbsolutePath(); - } else { - path = imgList1.get(i - imgList0.size()).getAbsolutePath(); - } - - Mat inMat = opencv_imgcodecs.imread(path); // 读取样本文件 - - // 创建一个行数为sample_num, 列数为 rows*cols 的矩阵; 用于存放样本 - if (trainingDataMat == null) { - trainingDataMat = new Mat(sample_num, inMat.rows() * inMat.cols(), opencv_core.CV_32FC1);// CV_32FC1 是规定的训练用的图片格式。 - } - - // 样本文件处理,这里是为了过滤不需要的特征,减少训练时间 // 根据实际情况需要进行处理 - Mat greyMat = new Mat(); - opencv_imgproc.cvtColor(inMat, greyMat, opencv_imgproc.COLOR_BGR2GRAY); // 转成灰度图 - - Mat dst = new Mat(inMat.rows(), inMat.cols(), inMat.type()); - opencv_imgproc.Canny(greyMat, dst, 130, 250); // 边缘检测 - - // 将样本矩阵转换成只有一行的矩阵,保存为float数组 - float[] arr = new float[dst.rows() * dst.cols()]; - int l = 0; - for (int j = 0; j < dst.rows(); j++) { // 遍历行 - for (int k = 0; k < dst.cols(); k++) { // 遍历列 - double[] a = null;//dst.get(j, k); - arr[l] = (float) a[0]; - l++; - } - } - - // trainingDataMat.put(i, 0, arr); // 多张图合并到一张 - } - - // opencv_imgcodecs.imwrite(DEFAULT_PATH + "trainingDataMat.jpg", trainingDataMat); - - // 配置SVM训练器参数 - TermCriteria criteria = new TermCriteria(TermCriteria.EPS + TermCriteria.MAX_ITER, 20000, 0.0001); - SVM svm = SVM.create(); - 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优化问题的参数C - svm.setP(0.1); - svm.setDegree(0.1); - svm.setCoef0(0.1); - - TrainData td = TrainData.create(trainingDataMat, Ml.ROW_SAMPLE, labelsMat);// 类封装的训练数据 - boolean success = svm.train(td.getSamples(), Ml.ROW_SAMPLE, td.getResponses());// 训练统计模型 - System.out.println("svm training result: " + success); - svm.save(MODEL_PATH);// 保存模型 - } - - - - public static void pridect() { - // 加载训练得到的 xml 模型文件 - SVM svm = SVM.load(MODEL_PATH); - - // 136 × 36 像素 需要跟训练的源图像文件保持相同大小 - doPridect(svm, DEFAULT_PATH + "test/A01_NMV802_0.jpg"); - doPridect(svm, DEFAULT_PATH + "test/debug_resize_1.jpg"); - doPridect(svm, DEFAULT_PATH + "test/debug_resize_2.jpg"); - doPridect(svm, DEFAULT_PATH + "test/debug_resize_3.jpg"); - doPridect(svm, DEFAULT_PATH + "test/S22_KG2187_3.jpg"); - doPridect(svm, DEFAULT_PATH + "test/S22_KG2187_5.jpg"); - doPridect(svm, DEFAULT_PATH + "test/result_0.png"); - doPridect(svm, DEFAULT_PATH + "test/result_1.png"); - doPridect(svm, DEFAULT_PATH + "test/result_2.png"); - doPridect(svm, DEFAULT_PATH + "test/result_3.png"); - doPridect(svm, DEFAULT_PATH + "test/result_4.png"); - doPridect(svm, DEFAULT_PATH + "test/result_5.png"); - doPridect(svm, DEFAULT_PATH + "test/result_6.png"); - doPridect(svm, DEFAULT_PATH + "test/result_7.png"); - doPridect(svm, DEFAULT_PATH + "test/result_8.png"); - - } - - public static void doPridect(SVM svm, String imgPath) { - - Mat src = opencv_imgcodecs.imread(imgPath);// 图片大小要和样本一致 - opencv_imgproc.cvtColor(src, src, opencv_imgproc.CV_RGB2GRAY); - Mat dst = new Mat(); - opencv_imgproc.Canny(src, dst, 130, 250); - - Mat samples = dst.reshape(1, 1); - samples.convertTo(samples, opencv_core.CV_32FC1); - - // opencv_imgcodecs.imwrite(DEFAULT_PATH + "test_1.jpg", samples); - - // 如果训练时使用这个标识,那么符合的图像会返回9.0 - float flag = svm.predict(samples); - System.err.println(flag); - - if (flag == 0) { - System.err.println(imgPath + ": 目标符合"); - } - if (flag == 1) { - System.out.println(imgPath + ": 目标不符合"); - } - } - - 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; - } else { - labels[i] = 1; - } - } - return labels; - } - -} diff --git a/src/main/java/com/yuxue/train/SVMTrain.java b/src/main/java/com/yuxue/train/SVMTrain.java index 413ff94a..8f6b5e17 100644 --- a/src/main/java/com/yuxue/train/SVMTrain.java +++ b/src/main/java/com/yuxue/train/SVMTrain.java @@ -15,6 +15,7 @@ import com.yuxue.util.FileUtil; /** * 基于org.bytedeco.javacpp包实现的训练 + * JavaCPP 是一个开源库,它提供了在 Java 中高效访问本地 C++的方法 * * 图片识别车牌训练 * 训练出来的库文件,用于判断切图是否包含车牌