优化代码结构

devA
yuxue 5 years ago
parent 28ed2a5565
commit 6111a17f48

@ -27,6 +27,9 @@ public class Constant {
//public static String DEFAULT_ANN_PATH = "D:/PlateDetect/train/chars_recognise_ann/ann.xml"; //public static String DEFAULT_ANN_PATH = "D:/PlateDetect/train/chars_recognise_ann/ann.xml";
public static String DEFAULT_SVM_PATH = "res/model/svm.xml"; public static String DEFAULT_SVM_PATH = "res/model/svm.xml";
public static final int DEFAULT_WIDTH = 136; // cols
public static final int DEFAULT_HEIGHT = 36; // rows
// 车牌识别,判断是否车牌的正则表达式 // 车牌识别,判断是否车牌的正则表达式
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 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})";

@ -24,6 +24,7 @@ import org.opencv.imgproc.Imgproc;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.yuxue.constant.Constant;
import com.yuxue.enumtype.PlateColor; import com.yuxue.enumtype.PlateColor;
@ -70,23 +71,28 @@ public class ImageUtil {
public static void main(String[] args) { public static void main(String[] args) {
Instant start = Instant.now(); Instant start = Instant.now();
String tempPath = DEFAULT_BASE_TEST_PATH + "test/"; String tempPath = DEFAULT_BASE_TEST_PATH + "test/";
String filename = tempPath + "/100_yuantu.jpg"; String filename = tempPath + "/100_yuantu.jpg";
filename = tempPath + "/100_yuantu1.jpg"; filename = tempPath + "/100_yuantu1.jpg";
// filename = tempPath + "/109_crop_0.png"; // filename = tempPath + "/109_crop_0.png";
// 读取原图
Mat src = Imgcodecs.imread(filename); Mat src = Imgcodecs.imread(filename);
Boolean debug = true; Boolean debug = true;
// 高斯模糊
Mat gsMat = ImageUtil.gaussianBlur(src, debug, tempPath); Mat gsMat = ImageUtil.gaussianBlur(src, debug, tempPath);
// 灰度图
Mat gray = ImageUtil.gray(gsMat, debug, tempPath); Mat gray = ImageUtil.gray(gsMat, debug, tempPath);
Mat sobel = ImageUtil.sobel(gray, debug, tempPath); Mat sobel = ImageUtil.sobel(gray, debug, tempPath);
// Mat sobel = ImageUtil.scharr(gray, debug, tempPath);
Mat threshold = ImageUtil.threshold(sobel, debug, tempPath); Mat threshold = ImageUtil.threshold(sobel, debug, tempPath);
// Mat scharr = ImageUtil.scharr(gray, debug, tempPath);
// Mat threshold = ImageUtil.threshold(scharr, debug, tempPath);
Mat morphology = ImageUtil.morphology(threshold, debug, tempPath); Mat morphology = ImageUtil.morphology(threshold, debug, tempPath);
List<MatOfPoint> contours = ImageUtil.contours(src, morphology, debug, tempPath); List<MatOfPoint> contours = ImageUtil.contours(src, morphology, debug, tempPath);
@ -95,10 +101,10 @@ public class ImageUtil {
PlateUtil.loadSvmModel("D:/PlateDetect/train/plate_detect_svm/svm2.xml"); PlateUtil.loadSvmModel("D:/PlateDetect/train/plate_detect_svm/svm2.xml");
PlateUtil.loadAnnModel("D:/PlateDetect/train/chars_recognise_ann/ann.xml"); PlateUtil.loadAnnModel("D:/PlateDetect/train/chars_recognise_ann/ann.xml");
Vector<Mat> dst = new Vector<Mat>(); Vector<Mat> dst = new Vector<Mat>();
PlateUtil.hasPlate(rects, dst, debug, tempPath); PlateUtil.hasPlate(rects, dst, debug, tempPath);
System.err.println("识别到的车牌数量:" + dst.size()); System.err.println("识别到的车牌数量:" + dst.size());
dst.stream().forEach(inMat -> { dst.stream().forEach(inMat -> {
PlateColor color = PlateUtil.getPlateColor(inMat, true, debug, tempPath); PlateColor color = PlateUtil.getPlateColor(inMat, true, debug, tempPath);
@ -106,19 +112,20 @@ public class ImageUtil {
Vector<Mat> charMat = new Vector<Mat>(); Vector<Mat> charMat = new Vector<Mat>();
PlateUtil.charsSegment(inMat, color, charMat, debug, tempPath); PlateUtil.charsSegment(inMat, color, charMat, debug, tempPath);
}); });
/*String filename = tempPath + "/hsvMat_1590994270425.jpg"; /*String filename = tempPath + "/hsvMat_1590994270425.jpg";
Mat src = Imgcodecs.imread(filename); Mat src = Imgcodecs.imread(filename);
Vector<Mat> charMat = new Vector<Mat>(); Vector<Mat> charMat = new Vector<Mat>();
PlateUtil.charsSegment(src, PlateColor.BLUE, charMat, true, tempPath);*/ PlateUtil.charsSegment(src, PlateColor.BLUE, charMat, true, tempPath);*/
// ImageUtil.rgb2Hsv(src, debug, tempPath);
// ImageUtil.getHSVValue(src, debug, tempPath);
Instant end = Instant.now(); Instant end = Instant.now();
System.err.println("总耗时:" + Duration.between(start, end).toMillis()); System.err.println("总耗时:" + Duration.between(start, end).toMillis());
// ImageUtil.rgb2Hsv(src, debug, tempPath);
// ImageUtil.getHSVValue(src, debug, tempPath);
} }
@ -160,7 +167,7 @@ public class ImageUtil {
/** /**
* Sobel * Sobel
* @param inMat * @param inMat
* @param debug * @param debug
* @param tempPath * @param tempPath
* @return * @return
@ -170,22 +177,22 @@ public class ImageUtil {
public static final int SOBEL_X_WEIGHT = 1; public static final int SOBEL_X_WEIGHT = 1;
public static final int SOBEL_Y_WEIGHT = 0; public static final int SOBEL_Y_WEIGHT = 0;
public static Mat sobel(Mat inMat, Boolean debug, String tempPath) { public static Mat sobel(Mat inMat, Boolean debug, String tempPath) {
Mat dst = new Mat(); Mat dst = new Mat();
Mat grad_x = new Mat(); Mat grad_x = new Mat();
Mat grad_y = new Mat(); Mat grad_y = new Mat();
Mat abs_grad_x = new Mat(); Mat abs_grad_x = new Mat();
Mat abs_grad_y = new Mat(); Mat abs_grad_y = new Mat();
Imgproc.Sobel(inMat, grad_x, CvType.CV_16S, 1, 0, 3, SOBEL_SCALE, SOBEL_DELTA, Core.BORDER_DEFAULT); // Sobel滤波 计算水平方向灰度梯度的绝对值
Core.convertScaleAbs(grad_x, abs_grad_x); Imgproc.Sobel(inMat, grad_x, CvType.CV_16S, 1, 0, 3, SOBEL_SCALE, SOBEL_DELTA, Core.BORDER_DEFAULT);
Core.convertScaleAbs(grad_x, abs_grad_x); // 增强对比度
Imgproc.Sobel(inMat, grad_y, CvType.CV_16S, 0, 1, 3, SOBEL_SCALE, SOBEL_DELTA, Core.BORDER_DEFAULT); Imgproc.Sobel(inMat, grad_y, CvType.CV_16S, 0, 1, 3, SOBEL_SCALE, SOBEL_DELTA, Core.BORDER_DEFAULT);
Core.convertScaleAbs(grad_y, abs_grad_y); Core.convertScaleAbs(grad_y, abs_grad_y);
grad_x.release(); grad_x.release();
grad_y.release(); grad_y.release();
// 计算结果梯度
Core.addWeighted(abs_grad_x, SOBEL_X_WEIGHT, abs_grad_y, SOBEL_Y_WEIGHT, 0, dst); Core.addWeighted(abs_grad_x, SOBEL_X_WEIGHT, abs_grad_y, SOBEL_Y_WEIGHT, 0, dst);
abs_grad_x.release(); abs_grad_x.release();
abs_grad_y.release(); abs_grad_y.release();
@ -235,8 +242,8 @@ public class ImageUtil {
/** /**
* 256 * 256 0255
* 1 0 * 10
* @param inMat * @param inMat
* @param debug * @param debug
* @param tempPath * @param tempPath
@ -260,7 +267,7 @@ public class ImageUtil {
* @param tempPath * @param tempPath
* @return * @return
*/ */
//public static final int DEFAULT_MORPH_SIZE_WIDTH = 15; // public static final int DEFAULT_MORPH_SIZE_WIDTH = 15;
// public static final int DEFAULT_MORPH_SIZE_HEIGHT = 3; // public static final int DEFAULT_MORPH_SIZE_HEIGHT = 3;
public static final int DEFAULT_MORPH_SIZE_WIDTH = 9; public static final int DEFAULT_MORPH_SIZE_WIDTH = 9;
public static final int DEFAULT_MORPH_SIZE_HEIGHT = 3; public static final int DEFAULT_MORPH_SIZE_HEIGHT = 3;
@ -328,8 +335,6 @@ public class ImageUtil {
* @return * @return
*/ */
public static final int DEFAULT_ANGLE = 30; // 角度判断所用常量 public static final int DEFAULT_ANGLE = 30; // 角度判断所用常量
public static final int WIDTH = 136;
public static final int HEIGHT = 36;
public static final int TYPE = CvType.CV_8UC3; public static final int TYPE = CvType.CV_8UC3;
public static Vector<Mat> screenBlock(Mat src, List<MatOfPoint> contours, Boolean debug, String tempPath){ public static Vector<Mat> screenBlock(Mat src, List<MatOfPoint> contours, Boolean debug, String tempPath){
Vector<Mat> dst = new Vector<Mat>(); Vector<Mat> dst = new Vector<Mat>();
@ -353,18 +358,20 @@ public class ImageUtil {
} }
// 旋转角度,根据需要是否进行角度旋转 // 旋转角度,根据需要是否进行角度旋转
Mat img_rotated = new Mat(); /*Mat img_rotated = new Mat();
Mat rotmat = Imgproc.getRotationMatrix2D(mr.center, angle, 1); // 旋转 Mat rotmat = Imgproc.getRotationMatrix2D(mr.center, angle, 1); // 旋转
Imgproc.warpAffine(src, img_rotated, rotmat, src.size()); // 仿射变换 Imgproc.warpAffine(src, img_rotated, rotmat, src.size()); // 仿射变换 考虑是否需要进行投影变换?
*/
// 切图 // 切图
Mat img_crop = new Mat(); Mat img_crop = new Mat();
Imgproc.getRectSubPix(src, rect_size, mr.center, img_crop); Imgproc.getRectSubPix(src, rect_size, mr.center, img_crop);
if (debug) { if (debug) {
// Imgcodecs.imwrite(tempPath + debugMap.get("crop") + "_crop_" + j + ".png", img_crop); Imgcodecs.imwrite(tempPath + debugMap.get("crop") + "_crop_" + j + ".png", img_crop);
} }
// 处理切图,调整为指定大小 // 处理切图,调整为指定大小
Mat resized = new Mat(HEIGHT, WIDTH, TYPE); Mat resized = new Mat(Constant.DEFAULT_HEIGHT, Constant.DEFAULT_WIDTH, TYPE);
Imgproc.resize(img_crop, resized, resized.size(), 0, 0, Imgproc.INTER_CUBIC); Imgproc.resize(img_crop, resized, resized.size(), 0, 0, Imgproc.INTER_CUBIC);
if (debug) { if (debug) {
Imgcodecs.imwrite(tempPath + debugMap.get("resize") + "_resize_" + j + ".png", resized); Imgcodecs.imwrite(tempPath + debugMap.get("resize") + "_resize_" + j + ".png", resized);
@ -396,10 +403,6 @@ public class ImageUtil {
final static float DEFAULT_ASPECT = 3.142857f; final static float DEFAULT_ASPECT = 3.142857f;
public static final int DEFAULT_VERIFY_MIN = 1; public static final int DEFAULT_VERIFY_MIN = 1;
public static final int DEFAULT_VERIFY_MAX = 30; public static final int DEFAULT_VERIFY_MAX = 30;
/*final static float DEFAULT_ERROR = 0.9f;
final static float DEFAULT_ASPECT = 4f;
public static final int DEFAULT_VERIFY_MIN = 1;
public static final int DEFAULT_VERIFY_MAX = 30;*/
private static boolean checkPlateSize(RotatedRect mr) { private static boolean checkPlateSize(RotatedRect mr) {
// 切图面积取值范围 // 切图面积取值范围
@ -414,9 +417,9 @@ public class ImageUtil {
int area = (int) (mr.size.height * mr.size.width); int area = (int) (mr.size.height * mr.size.width);
// 切图宽高比 // 切图宽高比
double r = mr.size.width / mr.size.height; double r = mr.size.width / mr.size.height;
if (r < 1) { /*if (r < 1) { // 注释掉不处理width 小于height的图片
r = mr.size.height / mr.size.width; r = mr.size.height / mr.size.width;
} }*/
return min <= area && area <= max && rmin <= r && r <= rmax; return min <= area && area <= max && rmin <= r && r <= rmax;
} }

@ -32,6 +32,7 @@ import com.yuxue.train.SVMTrain;
* *
* *
* *
*
* @author yuxue * @author yuxue
* @date 2020-05-28 15:11 * @date 2020-05-28 15:11
*/ */
@ -85,7 +86,6 @@ public class PlateUtil {
/*System.err.println(PalteUtil.isPlate("粤AI234K")); /*System.err.println(PalteUtil.isPlate("粤AI234K"));
System.err.println(PalteUtil.isPlate("鄂CD3098"));*/ System.err.println(PalteUtil.isPlate("鄂CD3098"));*/
System.err.println("done!!!");
} }
@ -111,12 +111,10 @@ public class PlateUtil {
* @param inMat * @param inMat
* @param dst * @param dst
*/ */
public static final int DEFAULT_WIDTH = 136;
public static final int DEFAULT_HEIGHT = 36;
public static void hasPlate(Vector<Mat> inMat, Vector<Mat> dst, Boolean debug, String tempPath) { public static void hasPlate(Vector<Mat> inMat, Vector<Mat> dst, Boolean debug, String tempPath) {
int i = 0; int i = 0;
for (Mat src : inMat) { for (Mat src : inMat) {
if(src.rows() == DEFAULT_HEIGHT && src.cols() == DEFAULT_WIDTH) { if(src.rows() == Constant.DEFAULT_HEIGHT && src.cols() == Constant.DEFAULT_WIDTH) {
Mat samples = SVMTrain.getFeature(src); Mat samples = SVMTrain.getFeature(src);
float flag = svm.predict(samples); float flag = svm.predict(samples);
if (flag == 0) { if (flag == 0) {
@ -129,6 +127,8 @@ public class PlateUtil {
} else { } else {
System.out.println("目标不符合"); System.out.println("目标不符合");
} }
} else {
System.err.println("非法图块");
} }
} }
return; return;
@ -302,7 +302,6 @@ public class PlateUtil {
Imgcodecs.imwrite(tempPath + debugMap.get("plateCrop") + "_plateCrop_" + i + ".jpg", img_crop); Imgcodecs.imwrite(tempPath + debugMap.get("plateCrop") + "_plateCrop_" + i + ".jpg", img_crop);
} }
Mat f = annT.features(img_crop, Constant.predictSize); Mat f = annT.features(img_crop, Constant.predictSize);
// 字符预测 // 字符预测

Loading…
Cancel
Save