为了账号安全,请及时绑定邮箱和手机立即绑定

Java基于opencv实现图像数字识别(五)—投影法分割字符

标签:
Java

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来做的)感谢



作者:奇迹迪
链接:https://www.jianshu.com/p/25ac6dac1408

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消