From 849b5271b880ff717a00299d28ef053f28397d4e Mon Sep 17 00:00:00 2001 From: yuxue Date: Wed, 13 May 2020 12:57:48 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=BD=A6=E7=89=8C=E6=A3=80?= =?UTF-8?q?=E6=9F=A5=20=E6=A8=A1=E5=9E=8B=E8=AE=AD=E7=BB=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yuxue/test/CharRecoTrainTest.java | 13 ++ .../com/yuxue/test/PlateDetectTrainTest.java | 142 ++++++++++++++++++ .../java/com/yuxue/test/PlatePridectTest.java | 77 ++++++++++ .../{EasyPrTest.java => PlateRecoTest.java} | 2 +- src/test/java/com/yuxue/test/PridectTest.java | 70 --------- src/test/java/com/yuxue/test/TrainTest.java | 117 --------------- 6 files changed, 233 insertions(+), 188 deletions(-) create mode 100644 src/test/java/com/yuxue/test/CharRecoTrainTest.java create mode 100644 src/test/java/com/yuxue/test/PlateDetectTrainTest.java create mode 100644 src/test/java/com/yuxue/test/PlatePridectTest.java rename src/test/java/com/yuxue/test/{EasyPrTest.java => PlateRecoTest.java} (99%) delete mode 100644 src/test/java/com/yuxue/test/PridectTest.java delete mode 100644 src/test/java/com/yuxue/test/TrainTest.java diff --git a/src/test/java/com/yuxue/test/CharRecoTrainTest.java b/src/test/java/com/yuxue/test/CharRecoTrainTest.java new file mode 100644 index 00000000..2e2fc4eb --- /dev/null +++ b/src/test/java/com/yuxue/test/CharRecoTrainTest.java @@ -0,0 +1,13 @@ +package com.yuxue.test; + + + +/** + * 图片识别文字训练 + * + * @author yuxue + * @date 2020-05-13 10:11 + */ +public class CharRecoTrainTest { + +} diff --git a/src/test/java/com/yuxue/test/PlateDetectTrainTest.java b/src/test/java/com/yuxue/test/PlateDetectTrainTest.java new file mode 100644 index 00000000..c4681345 --- /dev/null +++ b/src/test/java/com/yuxue/test/PlateDetectTrainTest.java @@ -0,0 +1,142 @@ +package com.yuxue.test; + +import java.io.File; +import java.util.List; + +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.imgproc.Imgproc; +import org.opencv.ml.Ml; +import org.opencv.ml.SVM; +import org.opencv.ml.TrainData; + +import com.yuxue.constant.Constant; +import com.yuxue.util.FileUtil; + +/** + * windows下环境配置: + * 1、官网下载对应版本的openvp:https://opencv.org/releases/page/2/ 当前使用4.0.1版本 + * 2、双击exe文件安装,将 安装目录下\build\java\x64\opencv_java401.dll 拷贝到\build\x64\vc14\bin\目录下 + * 3、eclipse添加User Libraries + * 4、项目右键build path,添加步骤三新增的lib + * + * 图片识别车牌训练 + * 训练出来的库文件,用于判断切图是否包含车牌 + * @author yuxue + * @date 2020-05-13 10:10 + */ +public class PlateDetectTrainTest { + + // 默认的训练操作的根目录 + private static final String DEFAULT_PATH = "D:/PlateDetect/train/plate_detect_svm/"; + + static { + System.loadLibrary(Core.NATIVE_LIBRARY_NAME); + } + + 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,每个图片都要给一个标记 + Mat labelsMat = new Mat(sample_num, 1, CvType.CV_32SC1); + labelsMat.put(0, 0, labels); + + // 这里的意思是,trainingDataMat 存放18张图片的矩阵,trainingDataMat 的每一行存放一张图片的矩阵。 + for (int i = 0; i < sample_num; i++) { + + String path = ""; + if(i < imgList1.size()) { + path = imgList1.get(i).getAbsolutePath(); + } else { + path = imgList2.get(i - imgList1.size()).getAbsolutePath(); + } + + Mat src = Imgcodecs.imread(path); + + // 创建一个行数为18(正负样本总数量为18),列数为 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。 + Imgproc.Canny(src, dst, 130, 250); // 边缘检测 + + // 转成数组再添加。 + // 失败案例:这里我试图用 get(row,col,data)方法获取数组,但是结果和这个结果不一样,原因未知。 + 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 = dst.get(j, k); + arr[l] = (float) a[0]; + l++; + } + } + trainingDataMat.put(i, 0, arr); + } + + String module = DEFAULT_PATH + "svm.xml"; + MySvm(trainingDataMat, labelsMat, module); + } + + /** + * SVM 支持向量机 + * + * @param trainingDataMat 存放样本的矩阵 + * @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(); + 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.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; + } else { + labels[i] = 1; + } + } + return labels; + } + +} diff --git a/src/test/java/com/yuxue/test/PlatePridectTest.java b/src/test/java/com/yuxue/test/PlatePridectTest.java new file mode 100644 index 00000000..bc95991a --- /dev/null +++ b/src/test/java/com/yuxue/test/PlatePridectTest.java @@ -0,0 +1,77 @@ +package com.yuxue.test; + +import org.opencv.core.Core; +import org.opencv.core.CvType; +import org.opencv.core.Mat; +import org.opencv.imgcodecs.Imgcodecs; +import org.opencv.imgproc.Imgproc; +import org.opencv.ml.SVM; + +/** + * windows下环境配置: + * 1、官网下载对应版本的openvp:https://opencv.org/releases/page/2/ 当前使用4.0.1版本 + * 2、双击exe文件安装,将 安装目录下\build\java\x64\opencv_java401.dll 拷贝到\build\x64\vc14\bin\目录下 3、eclipse添加User Libraries + * 4、项目右键build path,添加步骤三新增的lib + * + * https://blog.csdn.net/marooon/article/details/80265247 + * + * 测试 + * + * @author yuxue + * @date 2020-05-12 21:34 + */ +public class PlatePridectTest { + + // 默认的训练操作的根目录 + private static final String DEFAULT_PATH = "D:/PlateDetect/train/plate_detect_svm/"; + + static { + System.loadLibrary(Core.NATIVE_LIBRARY_NAME); + } + + + public static void main(String[] args) { + + String module = DEFAULT_PATH + "svm.xml"; + SVM svm = SVM.load(module); // 加载训练得到的 xml 模型文件 + + // 136 × 36 像素 + pridect(svm, DEFAULT_PATH + "test/A01_NMV802_0.jpg"); + pridect(svm, DEFAULT_PATH + "test/S22_KG2187_3.jpg"); + pridect(svm, DEFAULT_PATH + "test/S22_KG2187_5.jpg"); + + } + + public static void pridect(SVM svm, String imgPath) { + + Mat src = Imgcodecs.imread(imgPath);// 图片大小要和样本一致 + Imgproc.cvtColor(src, src, Imgproc.COLOR_BGR2GRAY); + Mat dst = new Mat(); + Imgproc.Canny(src, dst, 130, 250); + + Mat samples = new Mat(1, dst.cols() * dst.rows(), CvType.CV_32FC1); + + // 转换 src 图像的 cvtype + // 失败案例:我试图用 dst.convertTo(src, CvType.CV_32FC1); 转换,但是失败了,原因未知。猜测: 内部的数据类型没有转换? + float[] dataArr = new float[dst.cols() * dst.rows()]; + for (int i = 0, f = 0; i < dst.rows(); i++) { + for (int j = 0; j < dst.cols(); j++) { + double pixel = dst.get(i, j)[0]; + dataArr[f] = (float) pixel; + f++; + } + } + + samples.put(0, 0, dataArr); + + // 如果训练时使用这个标识,那么符合的图像会返回9.0 + float flag = svm.predict(samples); + + if (flag == 0) { + System.err.println(imgPath + ": 目标符合"); + } + if (flag == 1) { + System.out.println(imgPath + ": 目标不符合"); + } + } +} \ No newline at end of file diff --git a/src/test/java/com/yuxue/test/EasyPrTest.java b/src/test/java/com/yuxue/test/PlateRecoTest.java similarity index 99% rename from src/test/java/com/yuxue/test/EasyPrTest.java rename to src/test/java/com/yuxue/test/PlateRecoTest.java index 29383edd..fb32f5ce 100644 --- a/src/test/java/com/yuxue/test/EasyPrTest.java +++ b/src/test/java/com/yuxue/test/PlateRecoTest.java @@ -28,7 +28,7 @@ import com.yuxue.enumtype.PlateColor; * @author yuxue * @date 2020-04-19 21:20 */ -public class EasyPrTest { +public class PlateRecoTest { /** * 图片车牌识别 diff --git a/src/test/java/com/yuxue/test/PridectTest.java b/src/test/java/com/yuxue/test/PridectTest.java deleted file mode 100644 index 0e00e351..00000000 --- a/src/test/java/com/yuxue/test/PridectTest.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.yuxue.test; - -import org.opencv.core.Core; -import org.opencv.core.CvType; -import org.opencv.core.Mat; -import org.opencv.imgcodecs.Imgcodecs; -import org.opencv.imgproc.Imgproc; -import org.opencv.ml.SVM; - - -/** - * windows下环境配置: - * 1、官网下载对应版本的openvp:https://opencv.org/releases/page/2/ 当前使用4.0.1版本 - * 2、双击exe文件安装,将 安装目录下\build\java\x64\opencv_java401.dll 拷贝到\build\x64\vc14\bin\目录下 - * 3、eclipse添加User Libraries - * 4、项目右键build path,添加步骤三新增的lib - * - * https://blog.csdn.net/marooon/article/details/80265247 - * - * 未完待续 - * @author yuxue - * @date 2020-05-12 21:34 - */ -public class PridectTest { - - static { - System.loadLibrary(Core.NATIVE_LIBRARY_NAME); - } - - public static void main(String[] args) { - Mat src = Imgcodecs.imread("D:\\xunlian\\a\\0.jpg");//图片大小要和样本一致 - Imgproc.cvtColor(src, src, Imgproc.COLOR_BGR2GRAY); - Mat dst = new Mat(); - Imgproc.Canny(src, dst, 40, 200); - test(dst); - } - - public static void test(Mat src) { - SVM svm = SVM.load("./Result/a.xml");//加载训练得到的 xml - - Mat samples = new Mat(1,src.cols()*src.rows(),CvType.CV_32FC1); - - //转换 src 图像的 cvtype - //失败案例:我试图用 src.convertTo(src, CvType.CV_32FC1); 转换,但是失败了,原因未知。猜测: 内部的数据类型没有转换? - float[] dataArr = new float[src.cols()*src.rows()]; - for(int i =0,f = 0 ;i