项目代码:https://download.csdn.net/download/qq_38735017/87379918
准备工作
首先,需要去OpenCV官网下载iOS的framework,下载好后拖入新建的工程中即可,由于OpenCV库是使用C++编写,所以swift无法直接使用,需要使用OC做桥接,需要使用swift的同学可以看下这篇文章Using OpenCV in an iOS app。
实验流程
根据OpenCV入门笔记(七) 文字区域的提取中提供的思路,我实现了OC版本的代码,通过测试,清晰的文字截图识别没有问题,但是在复杂的拍照场景中几乎无法识别任何内容,例如下图
![](https://i-blog.csdnimg.cn/blog_migrate/afc7405288c9072226ba75b85319722a.jpeg)
这张是相机拍摄的屏幕上的文字,有清晰的竖纹及屏幕反光,在该算法下,最终的框选区域是整个图片,无法识别文字区域,说明这个处理流程还是不完善的,我们先来看一下他的处理过程:
将图片转为灰度图
形态学变换的预处理,得到可以查找矩形的图片
查找和筛选文字区域
用绿线画出这些找到的轮廓
根据前面得到的识别结果,我们大致可以猜测问题出在了第二步,由于竖纹影响将全部文字区域连城一片,导致整图被框选。
那么在第二步中都做了哪些操作呢?
![](https://i-blog.csdnimg.cn/blog_migrate/6257e1c7cdf7f7503f374a83a4df109f.jpeg)
实际上上面的流程一共做了4步操作,二值化->膨胀->腐蚀->再膨胀,这个流程对于正常的白底文本截图的识别没有问题,一但图片中出现了噪点,噪点在第一次膨胀的之后被放大,对整个图像产生不可逆的污染,我们先来看一下二值化后的图像
![](https://i-blog.csdnimg.cn/blog_migrate/557b0e38a729003140c6e1de991b4144.jpeg)
文字还是很清晰的,但是竖纹一样明显,接着第二步膨胀,看下会怎样
![](https://i-blog.csdnimg.cn/blog_migrate/b258cb36124f7e72a1f30a831cf2c9d1.jpeg)
一片白,不用往下看了吧。
既然如此,就需要我们修改一下在第二步的处理流程了
在反转图像(由黑白变为白黑)之前,需要对图像进行降噪处理,因为OpenCV是对亮点进行操作,在黑白图像中降噪更容易处理(去除杂乱黑点),降噪使用的方法仍然是上面的膨胀和腐蚀法
//第一次二值化,转为黑白图片
cv::Mat binary; cv::adaptiveThreshold(gray,binary,255,cv::ADAPTIVE_THRESH_GAUSSIAN_C,cv::THRESH_BINARY,31,10);
//在第二次二值化之前 为了去除噪点 做了两次膨胀腐蚀
//膨胀一次
cv::Mat dilateelement = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(4,2));
cv::Mat dilate1;dilate(binary, dilate1, dilateelement);
//轻度腐蚀一次,去除噪点
cv::Mat element3 = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(4,4));
cv::Mat erode11;erode(dilate1, erode11, element3);
//第二次膨胀
cv::Mat dilateelement12 = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5,1));
cv::Mat dilate12;dilate(erode11, dilate12, dilateelement12);
//轻度腐蚀一次,去除噪点
cv::Mat element12 = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5,1));
cv::Mat erode12;erode(dilate12, erode12, element12);
看一下经过两次降噪之后的图像是怎么样的
![](https://i-blog.csdnimg.cn/blog_migrate/bff3bc560e6b432c469fd8c65da46516.jpeg)
竖纹基本上不见了,仍然还有一部分黑点,但是已经不影响后面的识别了,这里降噪只能适度,过度处理可能会使文字部分丢失。
![](https://i-blog.csdnimg.cn/blog_migrate/225ad0199a819a01b103228403b6b1ec.jpeg)
做完二值化反转之后是上面这个样子的,接下来再对图片做膨胀->腐蚀->膨胀处理
//二值化 第二次二值化将黑白图像反转 文字变亮
cv::Mat binary2;
cv::adaptiveThreshold(erode12,binary2,255,cv::ADAPTIVE_THRESH_GAUSSIAN_C,cv::THRESH_BINARY_INV,17,10);
//横向膨胀拉伸 文字连片形成亮条
cv::Mat dilateelement21 = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(60,1));
cv::Mat dilate21;
dilate(binary2, dilate21, dilateelement21);
//腐蚀一次,去掉细节,表格线等。这里去掉的是竖直的线
cv::Mat erodeelement21 = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(30,1));
cv::Mat erode21;
erode(dilate21, erode21, erodeelement21);
//再次膨胀,让轮廓明显一些
cv::Mat dilateelement22 = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5,1));
cv::Mat dilate22;
dilate(erode21, dilate22, dilateelement22);
处理的结果图如下:
![](https://i-blog.csdnimg.cn/blog_migrate/1328e00178e27ed2fe392b40e5f333a5.jpeg)
最终的框选效果
![](https://i-blog.csdnimg.cn/blog_migrate/d6e807816497ac30ea9925fab496f854.jpeg)
其他调试结果
当然调试过程中不止用了这一张图片,毕竟结果要有一定的普适性,下面是其他几种情况下的识别结果
![](https://i-blog.csdnimg.cn/blog_migrate/c771d51a1af71a57f6d82d6c023eac91.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/cb5a2d9019b1c9873cf95a512422bf06.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/56f1f329c6fffa6d29b56d3be58aa385.jpeg)