LOFTER-网易轻博

UI设计与图像处理(强行拉关系=-=)
XYZ-bear 2017-10-04

     看到下面这些设计稿是不是觉得还可以,是不是很兴奋?呵呵有经验的设计师心中一定有一万个mmp在奔腾,你懂的,怎么可能就这样交给那群程序员?所以标注就他妈是一项体力活,费事费力。所以就想着是不是可以搞一个自动标注的工具,下面就来研究下。



                   http://www.zcool.com.cn/work/ZMTU0NzMzNDA=.html(图片出处)

    


首先我们要搞清楚几件事:

           1.目标是什么?提高设计师的工作效率

           2.要用到什么样的技术?嗯,肯定要用opencv

           3.怎么做?先实验,如果效果还可以就做成项目

    好了现在来实验以下。



    1 获取长宽

    1.1 思路:一张设计稿中的所有元素我们都可以用矩形来描述,需要标注的元素大概可以分为标准矩形和非标准矩形两大类,标准矩形自带长宽属性,而对于非标准矩形我们可以把它当作是一个求凸包的最小环绕矩形问题来解决。具体见下面这两张图:





    


1.2 提取轮廓:很幸运,opencv已经给我们提供了相关的方法来提取轮廓和求凸包最小环绕矩形,这两个方法分别是findContours 和 boundingRect,先来看一段代码 


void todo(){

       Mat src;  //图源

       Mat img;  //处理图

       Mat dst;  //输出图


       src=imread("");

       img.create(src.rows,src.cols,src.depth());

       dst=src;

       cvtColor(src, img, CV_BGR2GRAY);

       threshold(img, img, 0, 255, CV_THRESH_OTSU);//findContours需要输入二值图形


       vector<vector<Point>> contours;

       vector<Vec4i> hierarchy;

       findContours(img,contours,hierarchy,CV_RETR_TREE, CV_CHAIN_APPROX_NONE);//获取轮廓


       CvScalar color = CV_RGB(255,0,0);

       for(vector<Point> contour:contours){

              Rect rect=boundingRect(contour);  //求凸包

              DrawMark(dst,src,rect,color,0,contour);//绘画标记

       }


       imshow("",dst);


       src.release();

       img.release();

       dst.release();

       cvWaitKey (0);

}

实验图:



话不多说先来看看效果图:


光看效果的话轮廓还是找出来了,嗯,只是有点呵呵。可以看出图中画圈的部分达到了算法想要的效果而并没有达到我们想要的效果。来整理下问题:

  1. 对于一列文字,只需要知道整列的宽高

  2. 对于图标,只需要达到图标整体的尺寸,并不关心图标里面的图案尺寸

  3. 对于蓝色圈起来的横线缺并为检测出来

  

      造成第三个问题的原因是阈值函数threshold函数二值化图片后造成的,先来看一下二值化后的图片:


很明显横线已经丢失,原因是我们用的二值化方法CV_THRESH_OTSU造成的(findContours 需要输入二值图像),那么我为什么要选择用这个方法,其实很简单,我只是想让尽量少的设置参数 ,该方法可以全局自适应阈值,所以把细小的线条过滤掉了。如果用其他方法就需要手动设置阈值会很麻烦,所以我们需要用别的方式来进行图像二值化,见1.3。

    


     1.3 消除噪点:我们并不关心过小的细节,只需要能突出整体,突出重点就对了,专业术语也就是消除噪点,消除噪点的方式很多比如滤波,腐蚀膨胀等,但是根据场景我们这里要用形态学中的腐蚀膨胀操作,好处是它可以分割出独立图像元素,连接图中相邻元素,而且还可以输出二值图像,这样基本能解决上面的问题。

      现在我们将threshold操作改为腐蚀膨胀操作:


    int erosion_type;

    int erosion_elem=0;

    int erosion_size=3;

    if( erosion_elem == 0 ){ erosion_type = MORPH_RECT; }

    else if( erosion_elem == 1 ){ erosion_type = MORPH_CROSS; }

    else if( erosion_elem == 2) { erosion_type = MORPH_ELLIPSE; }


    Mat element = getStructuringElement( erosion_type,

                                       Size( 2*erosion_size + 1, 2*erosion_size+1 ),

                                       Point( erosion_size, erosion_size ) );

    morphologyEx(img, img, MORPH_GRADIENT, element);

     这里我们用高级形态学方法morphologyEx,该方法能图像进行开,闭和梯度等操作,在这里我们选择MORPH_GRADIENT进行梯度操作,而形态学梯度正好就是突出外围-轮廓,这和我们的目标是提取轮廓不谋而合。这里需要注意的是element是我们的核,那么参数erosion_size就是图像向里收缩和向外膨胀的距离,具体可参考这篇博客 

http://blog.csdn.net/xia316104/article/details/44748217。

好来看看进行梯度操作后的图像和结果图像:


仔细看,会发现以下问题

  1. 见图可发现,我们提取出来的轮廓,实际上是比真实轮廓大。

  2. 部分细节丢失,如登陆按钮的外围轮廓。

  3. 多了无效区域的轮廓细节

如何解决:

  1. 这个问题比较好办,前面我们已经知道了膨胀距离erosion_size,所以我们只需要对提取的轮廓进行缩放即可。但是不能忽视一个问题就是,图的整体大小是不会收缩的,也就是所提取到的最外层的轮廓实际上是没有收缩变化的正常大小,比较简单的解决办法就是将图整体向外拓展一定的无效区域。在图像灰度处理后加入以下代码:

       cvtColor(src, img, CV_BGR2GRAY);

       //--------------拓展图像------------

       copyMakeBorder(img,img,20,20,20,20,BORDER_CONSTANT,RGB(255,255,255));

       copyMakeBorder(dst,dst,20,20,20,20,BORDER_CONSTANT,RGB(255,255,255));

  1. 看上图腐蚀膨胀后的图像会发现,我们的特征区域和背景色色差不是很大,这样特征被弱化了,这就导致某些区域轮廓提取不成功。色差太小,那我们就手动让色差变大不久行了,见以下打码:

       morphologyEx(img, img, MORPH_GRADIENT, element);

       //将灰度值大于10的像素改为255

       for( size_t i = 0; i < img.rows; i++)

       {

              uchar* data = img.ptr<uchar>(i);

              for(size_t j = 0; j < img.cols*img.channels(); j++)

              {

                     if(data[j]>10)

                           data[j]=255;

                     else

                           data[j]=0;

              }

       }

  1. 对于无效区域,只能手动过滤了,过滤方式只能是过滤掉较小的轮廓,然后人为排除无效区域,让其不参与运算就行。

增强特征后的图:



结果图:

      OK效果还将就,总结下就提取轮廓求长宽这个过程整体需要用户调节的就是erosion_size这个参数,这个参数取决于设计稿的大小,和设计稿中的最小元素大小。下面是其他图的效果。


还需要解决的问题。。。。

  1. 计算圆角曲率。

  2. 获取区域颜色。

完整源码和项目见我的GITHUB,未完待续

推荐文章
评论(1)
联系我们|招贤纳士|移动客户端|风格模板|官方博客
网易公司版权所有 ©1997-2019 浙公网安备 33010802010186号浙ICP备16011220号-11增值电信业务经营许可证:浙B2-20160599自营经营者信息
分享到
转载我的主页