zoukankan      html  css  js  c++  java
  • 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来做的)感谢

  • 相关阅读:
    struts2文件下载的编写步骤(文件导出)和输入流转换的方法
    spring的applicationContext.xml配置SessionFactory抛异常
    引用第三方高德地图接口---使用js脚本进行开发地图定位的步骤
    登陆时不同浏览器获取session存在的相关疑问?
    统一的异常处理和自定义的全局异常处理器的配置使用
    国际化的工具类ognl utils
    oracle中decode的用法(例子)
    PLSQL连接本机oracle 11g 64 数据库的步骤
    处理oracle 报ORA-12505 信息:listener does not currently know of SID given in connect descriptor...
    spring容器的配置和springmvc的配置
  • 原文地址:https://www.cnblogs.com/qjmnong/p/9257018.html
Copyright © 2011-2022 走看看