Android OpenCV应用篇三:提取图片中的文字

本文介绍了如何利用OpenCV在Android上提取图片中的文字,包括阈值化、腐蚀、滤波降噪、连通区域检测和文字截取等步骤。通过种子填充法进行连通区域检测,计算边框并提取文字。尽管存在一些局限性,但结合其他技术如TensorFlow,可以实现更智能的文字识别应用。
摘要由CSDN通过智能技术生成

上篇我们大致了解了如何运用OpenCV在Android上进行图片但简单处理

Android OpenCV应用篇二:图片处理

接下来我们就运用之前的一些相关技术来搞点事情:
如何从一张图片中将文字提取出来?


前言

在开始之前,我们先来看一个字

可以看到,这个字体是上中下结构,相应的,我们的汉字还有左中右结构等等,我们如何在识别的过程中,不会吧这些特殊结构的字体识别成多个?

这里我们就用到了我们前一篇中的技术:**腐蚀**

看一下高字的腐蚀效果:
可以看出,完全融为一体,这为我们后面准确的提取文字区域提供了基础。

当然,我们传统的都是认为白纸黑字,但实际上并不一定都是这一,所以在此之前我们需要进行排除环境影响,如何处理?

这里也是用到我们上一篇但知识:

  • 降噪
  • 阈值化

开始我们的文字提取

OK前面大致介绍了一下基本操作,我们下面总结一下,然后开始实现
步骤:

  • 阈值化
  • 腐蚀
  • 降噪
  • 文字区域检测
  • 文字提取
第一步:阈值化&腐蚀

由于字体大小,或其他一些字体间的间距、行宽等影响,不同的字体图片可能需要用到等腐蚀效果不同,这里我们只进行原理上的处理,我选了一张比较适中等图片进行操作演示。

    /**
     * 阈值化,并腐蚀
     * @param src
     */
    private void erode(Mat src) {
   
        // 阈值化
        Imgproc.threshold(src, src, 100, 255, Imgproc.THRESH_BINARY);
//        Imgproc.adaptiveThreshold(opMat,opMat,255.0,Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C,Imgproc.THRESH_BINARY,3,0.0);

        Mat erodeKernel = Imgproc.getStructuringElement(Imgproc.MORPH_ELLIPSE, new Size(5, 5));
        Imgproc.erode(src, src, erodeKernel);
    }

第一步处理效果:

可以看出,完全转换成了白纸黑字,标题上等红色背景框完全除去掉了。但可以看出有明显的噪声,比如字左下角有一个点等。

第二步 滤波降噪

这里我们采用最为简单的中值滤波进行降噪

    /**
     * 采用中值滤波进行降噪
     *
     * @param src
     */
    private void medianBlur(Mat src) {
   
        Imgproc.medianBlur(src, src, 7);
    }

处理后的效果:

与上一步骤相比可以看出,噪声明显减少。
第三步 区域检测

区域检测,这里我们采用检测连通区域再根据联通区域计算边框的方式进行检测,当然,还有其他的一些检测方法,比如轮廓检测法、边缘检测等方法。

  • 连通区域检测
  • Rect边框计算
连通区域检测

首先进行连通区域检测,这里我们采用种子填充法进行连通区域检测,比较常用的还有两遍扫描法

种子填充法
详情请查阅 百度百科

下面开始进行种子填充算法,为了方便展示填充效果,我将每个连通区域都进行了重新赋值,这样就可以得到一个不同颜色值的联通区域展示图。具体代码如下:

    /**
     * 种子填充法进行联通区域检测
     */
    private Mat seedFill(Mat binImg, Mat src) {
   
        // 用来记录连通区域都数据图
        Mat lableImg = new Mat();
        // 这个是用来展示连通区域都效果图。
        Mat showMat = new Mat(binImg.size(), CvType.CV_8UC3);
        // 不需要记录额外都数据,一个通道就够了。
        binImg.convertTo(lableImg, CvType.CV_32SC1);

        int rows = lableImg.rows();
        int cols = lableImg.cols();

        double lable = 0;

        for (int r = 0; r < rows; r++) {
   
            for (int c = 0; c < cols; c++) {
   
                // 获取种子像素点
                double[] data = lableImg.get(r, c);
                if (data == null || data.length < 1) {
   
                    continue;
                }
                if (data[0] == 255) {
   
                	// 不是我们要都种子像素,继续
                    // 展示图背景设置为白色
                    showMat.put(r, c, 255, 255, 255);
                    continue;
                }
                if (data[0] != 0) {
   
                    // 已经标记过了,继续
                    continue;
                }

                // 走到这里说明找到了新的种子像素点,新的填充开始
                lable++;
                // 随机生成一个颜色,用来填充展示图
                double[] color = {
   Math.random() * 255, Math.random() * 255, Math.random() * 255};

                // 开始种子填充
                LinkedList<Point> neighborPixels = new LinkedList<>();
                neighborPixels.push(new Point(r, c));
                
                while (!neighborPixels.isEmpty()) {
   
                    Point curPx = neighborPixels.pop();
                    int row = (int) curPx.x;
                    int col = (int) curPx.y;
                    lableImg.put(row, col, lable);
                    showMat.put(row, col, color);

                    // 左边
                    double[] left = lableImg.get(row, col - 1);
      
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值