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
* - more than zero: the number of chars;
*
- -3: null;
*
*/
public List charsSegment(final Mat input, Vector 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 list = new ArrayList();
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 XMat = new ArrayList();
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 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;
}
}