You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
240 lines
6.6 KiB
240 lines
6.6 KiB
package com.yuxue.easypr.core;
|
|
|
|
import static com.yuxue.easypr.core.CoreFunc.getPlateType;
|
|
import static org.bytedeco.javacpp.opencv_imgproc.CV_RGB2GRAY;
|
|
import static org.bytedeco.javacpp.opencv_imgproc.CV_THRESH_BINARY;
|
|
import static org.bytedeco.javacpp.opencv_imgproc.CV_THRESH_BINARY_INV;
|
|
import static org.bytedeco.javacpp.opencv_imgproc.CV_THRESH_OTSU;
|
|
import static org.bytedeco.javacpp.opencv_imgproc.cvtColor;
|
|
import static org.bytedeco.javacpp.opencv_imgproc.findContours;
|
|
import static org.bytedeco.javacpp.opencv_imgproc.resize;
|
|
import static org.bytedeco.javacpp.opencv_imgproc.threshold;
|
|
import static org.bytedeco.javacpp.opencv_imgproc.warpAffine;
|
|
|
|
import java.util.Vector;
|
|
|
|
import org.bytedeco.javacpp.opencv_core;
|
|
import org.bytedeco.javacpp.opencv_core.Mat;
|
|
import org.bytedeco.javacpp.opencv_core.MatVector;
|
|
import org.bytedeco.javacpp.opencv_core.Range;
|
|
import org.bytedeco.javacpp.opencv_core.Rect;
|
|
import org.bytedeco.javacpp.opencv_core.Scalar;
|
|
import org.bytedeco.javacpp.opencv_core.Size;
|
|
import org.bytedeco.javacpp.opencv_imgcodecs;
|
|
|
|
import com.yuxue.enumtype.PlateColor;
|
|
import com.yuxue.util.Convert;
|
|
|
|
import java.io.File;
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.List;
|
|
|
|
import org.opencv.core.Core;
|
|
import org.opencv.imgcodecs.Imgcodecs;
|
|
|
|
|
|
/**
|
|
* 字符分割
|
|
* @author yuxue
|
|
* @date 2020-04-28 09:45
|
|
*/
|
|
public class CharsSegment {
|
|
|
|
// preprocessChar所用常量
|
|
final static int CHAR_SIZE = 20;
|
|
final static int HORIZONTAL = 1;
|
|
final static int VERTICAL = 0;
|
|
|
|
final static int DEFAULT_LIUDING_SIZE = 7;
|
|
final static int DEFAULT_MAT_WIDTH = 136;
|
|
|
|
final static int DEFAULT_COLORTHRESHOLD = 150;
|
|
final static float DEFAULT_BLUEPERCEMT = 0.3f;
|
|
final static float DEFAULT_WHITEPERCEMT = 0.1f;
|
|
private static final String BLACK = null;
|
|
private float bluePercent = DEFAULT_BLUEPERCEMT;
|
|
private float whitePercent = DEFAULT_WHITEPERCEMT;
|
|
|
|
private boolean isDebug = true;
|
|
private int liuDingSize;
|
|
private int colorThreshold;
|
|
|
|
|
|
/**
|
|
* 字符分割
|
|
*
|
|
* @param input
|
|
* @param resultVec
|
|
* @return <ul>
|
|
* <li>more than zero: the number of chars;
|
|
* <li>-3: null;
|
|
* </ul>
|
|
*/
|
|
public List<Mat> charsSegment(final Mat input, Vector<Mat> resultVec, String tempPath) {
|
|
if (input.data().isNull()) {
|
|
return null;
|
|
}
|
|
|
|
// 判断车牌颜色以此确认threshold方法
|
|
Mat img_threshold = new Mat();
|
|
|
|
Mat input_grey = new Mat();
|
|
cvtColor(input, input_grey, CV_RGB2GRAY);//转为灰度图
|
|
|
|
int w = input.cols();
|
|
int h = input.rows();
|
|
Mat tmpMat = new Mat(input, new Rect((int) (w * 0.1), (int) (h * 0.1), (int) (w * 0.8), (int) (h * 0.8)));
|
|
|
|
PlateColor color= getPlateType(tmpMat, true);
|
|
switch (color) {
|
|
case BLUE:
|
|
threshold(input_grey, img_threshold, 10, 255, CV_THRESH_OTSU + CV_THRESH_BINARY);
|
|
break;
|
|
|
|
case YELLOW:
|
|
threshold(input_grey, img_threshold, 10, 255, CV_THRESH_OTSU + CV_THRESH_BINARY_INV);
|
|
break;
|
|
|
|
case GREEN:
|
|
threshold(input_grey, img_threshold, 10, 255, CV_THRESH_OTSU + CV_THRESH_BINARY_INV);
|
|
break;
|
|
|
|
default:
|
|
return null;
|
|
}
|
|
|
|
if (this.isDebug) {
|
|
opencv_imgcodecs.imwrite(tempPath + "debug_char_threshold.jpg", img_threshold);
|
|
}
|
|
|
|
// 去除车牌上方的柳钉以及下方的横线等干扰 //会导致虚拟机崩溃
|
|
// clearLiuDing(img_threshold);
|
|
/*if (this.isDebug) {
|
|
String str = tempPath + "debug_char_clearLiuDing.jpg";
|
|
opencv_imgcodecs.imwrite(str, img_threshold);
|
|
}*/
|
|
|
|
|
|
|
|
//垂直投影法
|
|
int i, j;
|
|
int ncols = img_threshold.cols(), nrows = img_threshold.rows();
|
|
int[] xNum = new int[ncols], cNum;
|
|
int average = 0;
|
|
// 统计出每列黑色像素点的个数
|
|
for (i = 0; i < ncols; i++) {
|
|
for (j = 0; j < nrows; j++) {
|
|
if (getPixel(j, i) == BLACK) {
|
|
xNum[i]++;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
cNum = Arrays.copyOf(xNum, xNum.length);
|
|
Arrays.sort(cNum);
|
|
for (i = 31 * ncols / 32; i < ncols; i++) {
|
|
average += cNum[i];
|
|
}
|
|
average /= (ncols / 28);
|
|
|
|
// 把需要切割的x点都存到list中,
|
|
List<Integer> list = new ArrayList<Integer>();
|
|
for (i = 0; i < ncols; i += 2) {
|
|
if (xNum[i] >= average) {
|
|
list.add(i);
|
|
}
|
|
}
|
|
|
|
//优化切割点
|
|
if (list.size() != 0) {
|
|
//获取list集合的最后一个元素
|
|
int temp = list.get(list.size() - 1);
|
|
for (i = list.size() - 2; i >= 0; i--) {
|
|
int k = temp - list.get(i);
|
|
if (k <= 8) {
|
|
list.remove(i);
|
|
} else {
|
|
temp = list.get(i);
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
// 把切割的图片都保存到XMat中
|
|
List<Mat> XMat = new ArrayList<Mat>();
|
|
for (i = 1; i < list.size(); i++) {
|
|
// 设置分割图块的区域
|
|
int startX = list.get(i - 1);
|
|
int width = list.get(i) - startX;
|
|
Mat mat = null;
|
|
Mat temp = new Mat(mat, Rect(startX, 0, width, nrows));
|
|
Mat auxRoi = new Mat();
|
|
temp.copyTo(auxRoi);
|
|
XMat.add(auxRoi);
|
|
}
|
|
|
|
return XMat;
|
|
}
|
|
|
|
|
|
private Range Rect(int startX, int i, int width, int nrows) {
|
|
// TODO Auto-generated method stub
|
|
return null;
|
|
}
|
|
|
|
|
|
private String getPixel(int j, int i) {
|
|
// TODO Auto-generated method stub
|
|
return null;
|
|
}
|
|
|
|
|
|
|
|
|
|
private List<Mat> img_threshold() {
|
|
// TODO Auto-generated method stub
|
|
return null;
|
|
}
|
|
|
|
|
|
public void setLiuDingSize(int param) {
|
|
this.liuDingSize = param;
|
|
}
|
|
|
|
public void setColorThreshold(int param) {
|
|
this.colorThreshold = param;
|
|
}
|
|
|
|
public void setBluePercent(float param) {
|
|
this.bluePercent = param;
|
|
}
|
|
|
|
public final float getBluePercent() {
|
|
return this.bluePercent;
|
|
}
|
|
|
|
public void setWhitePercent(float param) {
|
|
this.whitePercent = param;
|
|
}
|
|
|
|
public final float getWhitePercent() {
|
|
return this.whitePercent;
|
|
}
|
|
|
|
public boolean getDebug() {
|
|
return this.isDebug;
|
|
}
|
|
|
|
public void setDebug(boolean isDebug) {
|
|
this.isDebug = isDebug;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|