抠字调研报告

2020-03-13  本文已影响0人  0200a9609930

抠字调研报告

1.需求分析

抠字的需求:把纸上的文字抠出来以透明背景的png的格式保存下来。这个png的图片有两个用处:1、保存到本地相册;2、作为水印添加到另一张图片上,这个水印png可以拉伸、拖动改变位置

需求分解

  1. 把纸上的文字保存为黑白图片
  2. 把该图片背景色改为透明

2.实现文字转墨迹图片

  1. iOS平台处理图片文字相关库OpenCVTesseract的了解

  2. OpenCV有一个imgproc模块,是用来图像处理相关,包括线性和非线性图像滤波、几何图像转换、颜色空间转换、直方图等等。确认使用OpenCV来处理该功能

  3. 利用opencv对图片进行处理,步骤大致如下

    1. 图像彩色转灰度
    2. 灰度图像设置阈值后二值化即变成完全黑白
    3. 去除多余的噪点
    

    3.1 将UIImage对象转成转成cv::Mat
    3.2 把图片放大
    3.3 转化成灰度图

    CV_EXPORTS_W void cvtColor( InputArray src,
                                OutputArray dst,
                                int code,
                                int dstCn = 0 );
    
    在opencv中,其默认的颜色制式排列是BGR而非RGB。所以对于24位颜色图像来说,前8-bit是蓝色,中间8-bit是绿色,最后8-bit是红色。
    code=COLOR_BGR2GRAY
    

    3.4 二值化转为完全黑白
    OpenCV提供了两个函数,第一个是普通的Threshold函数:

    CV_EXPORTS_W double threshold(  InputArray src, 
                                        OutputArray dst,
                                        double thresh, 
                                        double maxval, 
                                        int type );
    

    传入图像,传出图像,阈值,填充的最深颜色,填充方法(达到阈值就填充最深颜色或相反),就可以根据每个像素的灰度值与阈值进行比较来决定填充的值为0或是最深。

    定阈值的方法虽然可以对一张图像通过调整达到最优的效果,但是对于不同光照条件下拍摄出来的照片,因为整体亮度的不同,定阈值显然无法适应所有的情况。

    所以就有了第二种函数,adaptiveThreshold,除了传入上面的这些参数外,增加了三个重要的参数

    CV_EXPORTS_W void adaptiveThreshold(InputArray src, 
                                            OutputArray dst,
                                            double maxValue,
                                            int adaptiveMethod,
                                            int thresholdType,
                                            int blockSize, double C );
    

    blockSize:对某个像素周围进行采样的范围。
    adaptiveMethod:根据上面的范围求阈值的方法,有两种:

    mean平均,简单地取采样范围内的平均值作为阈值。
    gaussian高斯,以高斯函数为基础,简单地说就是近的地方权重更高、远的地方权重低,来求阈值。
    

    C:求出来的阈值减去的常量。

    3.5 去噪点

    去噪的目的是把图像中的独立的点去掉。去噪的方法是腐蚀,跟字面意思一样,就是缩小图案的范围,当图像的范围本身就很小时(噪点就是一个个这样的独立点),缩小后自然就不见了。

    可以想到,在去噪后,部分笔画也随之缩小甚至细的地方会直接消失,所以腐蚀之后要再进行一步膨胀,即把图案的边缘扩大。

    因为噪点已经消失,所以也不会因扩大而回来,但笔画依然存在,就会膨胀而得到弥补,也顺便可以补一下残缺的地方。

    原理大概就是这样,但是由于OpenCV的这两个操作针对的是图像中的亮点(白色的地方被认为是亮点),而我们的表格又是白底黑字的,实际上黑色的部分是我们想要处理的部分,所以我将这两步交换了,相当于是对黑色的地方先腐蚀后膨胀。

    代码如下

    //膨胀一次
    cv::Mat dilateelement = cv::getStructuringElement(cv::MORPH_CROSS, cv::Size(8,8));
    cv::Mat dilate1;
    dilate(binary, dilate1, dilateelement);
    
     //轻度腐蚀一次,去除噪点
     cv::Mat element3 = cv::getStructuringElement(cv::MORPH_CROSS, cv::Size(8,8));
     cv::Mat erode11;
     erode(dilate1, erode11, element3);
    

参考网站

http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/tutorials.html
http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/imgproc/erosion_dilatation/erosion_dilatation.html#morphology-1
https://www.viseator.com/2016/11/15/OpenCV%E5%A4%84%E7%90%86%E6%8B%8D%E7%85%A7%E8%A1%A8%E6%A0%BC%EF%BC%88%E4%B8%80%EF%BC%89/

3.把图片修改为透明颜色

    遍历图片的所有像素,把是白色或者接近白色的像素改成透明色。

    将像素点转成子节数组来表示---第一个表示透明度即`ARGB`这种表示方式。

4.总结

抠字功能主要用到了OpenCV Core Image,我对这两个库都是基础了解,很多功能都在网上查找的。实现该功能最困难的地方就是在照片腐蚀膨胀那,参数配置做了大量的测试,有些图片处理后噪点还是很多,有些又处理过了,需要在这中间找到一些平衡。

上一篇下一篇

猜你喜欢

热点阅读