Java基於opencv實現圖像數字識別(五)—投影法分割字符


Java基於opencv實現圖像數字識別(五)—投影法分割字符

水平投影法

1、水平投影法就是先用一個數組統計出圖像每行黑色像素點的個數(二值化的圖像);

2、選出一個最優的閥值,根據比這個閥值大或小,用一個數組記錄相應Y軸的坐標;

3、因為是水平切割我們只需要Y軸的切割點即可,寬度默認圖像的寬,高度可以用相鄰的切割點相減得到;

4、優化切割點,把切割點靠近的都清除掉

5、設置感應區的區域,切割圖片

垂直投影法和水平投影法類似,對比思考一下

因為我做的是表格的切割,你如果想實現驗證碼的切割,或者其他的類比這個,我想也是很容易實現的

我們先看一下,效果,還是很不錯的
投影法分割字符

水平切割代碼

// 圖像切割,水平投影法切割
public List<Mat> cutImgX() {
	int i, j;
	int nWidth = getWidth(), nHeight = getHeight();
	int[] xNum = new int[nHeight], cNum;
	int average = 0;// 記錄像素的平均值
	// 統計出每行黑色像素點的個數
	for (i = 0; i < nHeight; i++) {
		for (j = 0; j < nWidth; j++) {
			if (getPixel(i, j) == BLACK) {
				xNum[i]++;
			}

		}
	}

	// 經過測試這樣得到的平均值最優
	cNum = Arrays.copyOf(xNum, xNum.length);
	Arrays.sort(cNum);
	for (i = 31 * nHeight / 32; i < nHeight; i++) {
		average += cNum[i];
	}
	average /= (nHeight / 32);

	// 把需要切割的y點都存到cutY中
	List<Integer> cutY = new ArrayList<Integer>();
	for (i = 0; i < nHeight; i++) {
		if (xNum[i] > average) {
			cutY.add(i);
		}
	}

	// 優化cutY把
	if (cutY.size() != 0) {

		int temp = cutY.get(cutY.size() - 1);
		// 因為線條有粗細,優化cutY
		for (i = cutY.size() - 2; i >= 0; i--) {
			int k = temp - cutY.get(i);
			if (k <= 8) {
				cutY.remove(i);
			} else {
				temp = cutY.get(i);

			}

		}
	}

	// 把切割的圖片都保存到YMat中
	List<Mat> YMat = new ArrayList<Mat>();
	for (i = 1; i < cutY.size(); i++) {
		// 設置感興趣的區域
		int startY = cutY.get(i - 1);
		int height = cutY.get(i) - startY;
		Mat temp = new Mat(mat, new Rect(0, startY, nWidth, height));
		Mat t = new Mat();
		temp.copyTo(t);
		YMat.add(t);
	}

	return YMat;
}

垂直投影法

// 圖像切割,垂直投影法切割
public List<Mat> cutImgY() {

	int i, j;
	int nWidth = getWidth(), nHeight = getHeight();
	int[] xNum = new int[nWidth], cNum;
	int average = 0;// 記錄像素的平均值
	// 統計出每列黑色像素點的個數
	for (i = 0; i < nWidth; i++) {
		for (j = 0; j < nHeight; j++) {
			if (getPixel(j, i) == BLACK) {
				xNum[i]++;
			}

		}
	}

	// 經過測試這樣得到的平均值最優 , 平均值的選取很重要
	cNum = Arrays.copyOf(xNum, xNum.length);
	Arrays.sort(cNum);
	for (i = 31 * nWidth / 32; i < nWidth; i++) {
		average += cNum[i];
	}
	average /= (nWidth / 28);

	// 把需要切割的x點都存到cutY中,
	List<Integer> cutX = new ArrayList<Integer>();
	for (i = 0; i < nWidth; i += 2) {
		if (xNum[i] >= average) {
			cutX.add(i);
		}
	}

	if (cutX.size() != 0) {

		int temp = cutX.get(cutX.size() - 1);
		// 因為線條有粗細,優化cutY
		for (i = cutX.size() - 2; i >= 0; i--) {
			int k = temp - cutX.get(i);
			if (k <= 10) {
				cutX.remove(i);
			} else {
				temp = cutX.get(i);

			}

		}
	}

	// 把切割的圖片都保存到YMat中
	List<Mat> XMat = new ArrayList<Mat>();
	for (i = 1; i < cutX.size(); i++) {
		// 設置感興趣的區域
		int startX = cutX.get(i - 1);
		int width = cutX.get(i) - startX;
		Mat temp = new Mat(mat, new Rect(startX, 0, width, nHeight));
		Mat t = new Mat();
		temp.copyTo(t);
		XMat.add(t);
	}

	return XMat;
}

注:本文章參考了很多博客,感謝;主要是跟着一個博客來實現的https://blog.csdn.net/ysc6688/article/category/2913009(也是基於opencv來做的)感謝


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM