增加车牌检查 模型训练

devA
yuxue 5 years ago
parent a500f9a1cd
commit 849b5271b8

@ -0,0 +1,13 @@
package com.yuxue.test;
/**
*
*
* @author yuxue
* @date 2020-05-13 10:11
*/
public class CharRecoTrainTest {
}

@ -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
* 1openvphttps://opencv.org/releases/page/2/ 当前使用4.0.1版本
* 2exe \build\java\x64\opencv_java401.dll \build\x64\vc14\bin\
* 3eclipseUser Libraries
* 4build pathlib
*
*
*
* @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<File> imgList1 = FileUtil.listFile(new File(DEFAULT_PATH + "/learn/HasPlate"), Constant.DEFAULT_TYPE, false);
// 负样本 // 136 × 36 像素
List<File> 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;
}
}

@ -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
* 1openvphttps://opencv.org/releases/page/2/ 当前使用4.0.1版本
* 2exe \build\java\x64\opencv_java401.dll \build\x64\vc14\bin\ 3eclipseUser Libraries
* 4build pathlib
*
* 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 + " 目标不符合");
}
}
}

@ -28,7 +28,7 @@ import com.yuxue.enumtype.PlateColor;
* @author yuxue
* @date 2020-04-19 21:20
*/
public class EasyPrTest {
public class PlateRecoTest {
/**
*

@ -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
* 1openvphttps://opencv.org/releases/page/2/ 当前使用4.0.1版本
* 2exe \build\java\x64\opencv_java401.dll \build\x64\vc14\bin\
* 3eclipseUser Libraries
* 4build pathlib
*
* 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<src.rows();i++) {
for(int j = 0;j<src.cols();j++) {
float pixel = (float)src.get(i, j)[0];
dataArr[f] = pixel;
f++;
}
}
samples.put(0, 0, dataArr);
//预测用的方法,返回定义的标识。
// int labels[] = {9,9,9,9,
// 1,1,1,1,1,1,1,
// 1,1,1,1,1,1,1};
// 如果训练时使用这个标识那么符合的图像会返回9.0
float flag = svm.predict(samples);
System.out.println("预测结果:"+flag);
if(flag == 0) {
System.out.println("目标符合");
}
if(flag == 1) {
System.out.println("目标不符合");
}
}
}

@ -1,117 +0,0 @@
package com.yuxue.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.imgproc.Imgproc;
import org.opencv.ml.Ml;
import org.opencv.ml.SVM;
import org.opencv.ml.TrainData;
/**
* windows
* 1openvphttps://opencv.org/releases/page/2/ 当前使用4.0.1版本
* 2exe \build\java\x64\opencv_java401.dll \build\x64\vc14\bin\
* 3eclipseUser Libraries
* 4build pathlib
*
* https://blog.csdn.net/marooon/article/details/80265247
*
*
* @author yuxue
* @date 2020-05-12 21:34
*/
public class TrainTest {
static {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
}
/**
* @author idmin
*
*/
private static final int SAMPLE_NUMBER=18;
public static void main(String[] args) {
//用于存放所有样本矩阵
Mat trainingDataMat = null;
//标记:正样本用 0 表示,负样本用 1 表示。
//图片命名:
//正样本: 0.jpg 1.jpg 2.jpg 3.jpg 4.jpg
//负样本5.jpg 6.jpg 7.jpg ... 17.jpg
int labels[] = {0,0,0,0,
1,1,1,1,1,1,1,1,1,1,1,1,1,1};
//存放标记的Mat,每个图片都要给一个标记。SAMPLE_NUMBER 是自己定义的图片数量
Mat labelsMat = new Mat(SAMPLE_NUMBER, 1, CvType.CV_32SC1);
labelsMat.put(0, 0, labels);
//这里的意思是trainingDataMat 存放18张图片的矩阵trainingDataMat 的每一行存放一张图片的矩阵。
for(int i = 0;i<SAMPLE_NUMBER;i++) {
String path = "D:\\xunlian\\a\\" + i + ".jpg" ;
Mat src = Imgcodecs.imread(path);
//创建一个行数为18(正负样本总数量为18),列数为 rows*cols 的矩阵
if(trainingDataMat == null) {
trainingDataMat = new Mat(SAMPLE_NUMBER, 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);
}
//每次训练的结果得到的 xml 文件都不一样,原因未知。猜测是我的样本数太太太太小
// MySvm(trainingDataMat, labelsMat, "./Result/a.xml");
// MySvm(trainingDataMat, labelsMat, "./Result/b.xml");
// MySvm(trainingDataMat, labelsMat, "./Result/c.xml");
// MySvm(trainingDataMat, labelsMat, "./Result/d.xml");
// MySvm(trainingDataMat, labelsMat, "./Result/e.xml");
MySvm(trainingDataMat, labelsMat, "./Result/f.xml");
}
/**
* SVM
* @param trainingDataMat
* @param labelsMat
* @param savePath d:/svm.xml
*/
public static void MySvm(Mat trainingDataMat, Mat labelsMat, String savePath) {
SVM svm = SVM.create();
// 配置SVM训练器参数
TermCriteria criteria = new TermCriteria(TermCriteria.EPS + TermCriteria.MAX_ITER, 1000, 0);
svm.setTermCriteria(criteria);// 指定
svm.setKernel(SVM.LINEAR);// 使用预先定义的内核初始化
svm.setType(SVM.C_SVC); // SVM的类型,默认是SVM.C_SVC
svm.setGamma(0.5);// 核函数的参数
svm.setNu(0.5);// SVM优化问题参数
svm.setC(1);// SVM优化问题的参数C
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(savePath);// 保存模型
}
}
Loading…
Cancel
Save