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 */ 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; } }