对于印刷体图片来说,进行水平投影和垂直投影可以很快的进行分割,本文就在OpenCV中如何进行水平投影和垂直投影通过代码进行说明。

水平投影:二维图像在y轴上的投影

垂直投影:二维图像在x轴上的投影

由于投影的图像需要进行二值化,本文采用积分二值化的方式,对图片进行处理。

具体代码如下:

 //积分二值化
 void thresholdIntegral (Mat inputMat, Mat& outputMat)
 {

     int nRows = inputMat.rows;
     int nCols = inputMat.cols;

     // create the integral image
     Mat sumMat;
     integral (inputMat, sumMat);

     ;
     double T = 0.15;

     // perform thresholding
     ;
     int x1, y1, x2, y2, count, sum;

     int* p_y1, *p_y2;
     uchar* p_inputMat, *p_outputMat;

     ; i < nRows; ++i)
     {
         y1 = i - s2;
         y2 = i + s2;

         )
         {
             y1 = ;
         }
         if (y2 >= nRows)
         {
             y2 = nRows - ;
         }

         p_y1 = sumMat.ptr<int> (y1);
         p_y2 = sumMat.ptr<int> (y2);
         p_inputMat = inputMat.ptr<uchar> (i);
         p_outputMat = outputMat.ptr<uchar> (i);

         ; j < nCols; ++j)
         {
             // set the SxS region
             x1 = j - s2;
             x2 = j + s2;

             )
             {
                 x1 = ;
             }
             if (x2 >= nCols)
             {
                 x2 = nCols - ;
             }

             count = (x2 - x1)* (y2 - y1);

             // I(x,y)=s(x2,y2)-s(x1,y2)-s(x2,y1)+s(x1,x1)
             sum = p_y2[x2] - p_y1[x2] - p_y2[x1] + p_y1[x1];

             if ((int) (p_inputMat[j] * count) < (int) (sum* (1.0 - T)))
             {
                 p_outputMat[j] = ;
             }
             else
             {
                 p_outputMat[j] = ;
             }
         }
     }
 }
 //垂直方向投影
 void picshadowx (Mat binary)
 {
     Mat paintx (binary.size(), CV_8UC1, Scalar ()); //创建一个全白图片,用作显示

     int* blackcout = new int[binary.cols];
     memset (blackcout, , binary.cols * );

     ; i < binary.rows; i++)
     {
         ; j < binary.cols; j++)
         {
             )
             {
                 blackcout[j]++; //垂直投影按列在x轴进行投影
             }
         }
     }
     ; i < binary.cols; i++)
     {
         ; j < blackcout[i]; j++)
         {
             paintx.at<uchar> (binary.rows--j, i) = ; //翻转到下面,便于观看
         }
     }
     delete blackcout;
     imshow ("paintx", paintx);

 }
 //水平方向投影并行分割
 void picshadowy (Mat binary)
 {
    //是否为白色或者黑色根据二值图像的处理得来
     Mat painty (binary.size(), CV_8UC1, Scalar ()); //初始化为全白

    //水平投影
    int* pointcount = new int[binary.rows]; //在二值图片中记录行中特征点的个数
     memset (pointcount, , binary.rows * );//注意这里需要进行初始化

     ; i < binary.rows; i++)
     {
         ; j < binary.cols; j++)
         {
             )
             {
                 pointcount[i]++; //记录每行中黑色点的个数 //水平投影按行在y轴上的投影
             }
         }
     }

     ; i < binary.rows; i++)
     {
         ; j < pointcount[i]; j++) //根据每行中黑色点的个数,进行循环
         {

             painty.at<uchar> (i, j) = ;
         }

     }

     imshow ("painty", painty);

     vector<Mat> result;
     ;
     ;
     bool inblock = false; //是否遍历到字符位置

     ; i < painty.rows; i++)
     {

         ) //进入有字符区域
         {
             inblock = true;
             startindex = i;
             cout << "startindex:" << startindex << endl;
         }
         ) //进入空白区
         {
             endindex = i;
             inblock = false;
             Mat roi = binary.rowRange (startindex, endindex+); //从而记录从开始到结束行的位置,即可进行行切分
             result.push_back (roi);
         }
     }

     ; i < result.size(); i++)
     {
         Mat tmp = result[i];
         imshow ("test"+to_string (i), tmp);
      }
     delete pointcount;

 }
 int main (int argc, char* argv[])
 {

       Mat src = cv::imread ("test.jpg");

         if (src.empty())
         {
             cerr << "Problem loading image!!!" << endl;
             ;
         }

         imshow("in",src);

         Mat gray;

         )
         {
             cv::cvtColor (src, gray, CV_BGR2GRAY);
         }
         else
         {
             gray = src;
         }

         Mat bw2 = Mat::zeros (gray.size(), CV_8UC1);
         thresholdIntegral (gray, bw2);

         cv::imshow ("binary integral", bw2);

         //picshadowx (bw2);
         picshadowy (bw2);
         waitKey ();

     ;
 }

输入图片:

二值图片:

水平投影:

垂直投影:

行切割:

OpenCV 实现图片的水平投影与垂直投影,并进行行分割的更多相关文章

  1. python 对图片做垂直投影

    Python 对图片做垂直投影 本文利用opencv对图片进行垂直投影,做出垂直投影图,大体思路:打开图片,灰度化,二值化,按列进行统计,新建一个大小和原图一样的图片,按列进行填充: cv2.cv.G ...

  2. Python + opencv 实现图片文字的分割

    实现步骤: 1.通过水平投影对图形进行水平分割,获取每一行的图像: 2.通过垂直投影对分割的每一行图像进行垂直分割,最终确定每一个字符的坐标位置,分割出每一个字符: 先简单介绍一下投影法:分别在水平和 ...

  3. 用 Python 和 OpenCV 检测图片上的条形码

      用 Python 和 OpenCV 检测图片上的的条形码 这篇博文的目的是应用计算机视觉和图像处理技术,展示一个条形码检测的基本实现.我所实现的算法本质上基于StackOverflow 上的这个问 ...

  4. CSS实现文字和图片的水平垂直居中

    关于文字和图片的水平垂直居中,在前端界绝对算是一个老生常谈的问题了,尤其是垂直居中,什么千奇百怪的解法都能想的出来.下面我就总结一些比较常用的方法: 一.文本的水平垂直居中: 1.水平居中: 是不是很 ...

  5. mysql的水平拆分和垂直拆分

    转:http://www.cnblogs.com/sns007/p/5790838.html 1,水平分割: 例:QQ的登录表.假设QQ的用户有100亿,如果只有一张表,每个用户登录的时候数据库都要从 ...

  6. MYSQL水平拆分与垂直拆分

    目前很多互联网系统都存在单表数据量过大的问题,这就降低了查询速度,影响了客户体验.为了提高查询速度,我们可以优化sql语句,优化表结构和索引,不过对那些百万级千万级的数据库表,即便是优化过后,查询速度 ...

  7. * CSS 视觉格式化(基本框、包含块、盒模型、水平格式化、垂直格式化、行布局、em框、内容区、行间距、行内框、行框)

    前言 CSS视觉格式化这个词可能比较陌生,但说起盒模型可能就恍然大悟了.实际上,盒模型只是CSS视觉格式化的一部分.视觉格式化分为块级和行内两种处理方式.理解视觉格式化,可以确定得到的效果是应该显示的 ...

  8. mysql的水平拆分和垂直拆分 (转)

    http://www.cnblogs.com/sns007/p/5790838.html 1,水平分割: 例:QQ的登录表.假设QQ的用户有100亿,如果只有一张表,每个用户登录的时候数据库都要从这1 ...

  9. mysql数据库的水平拆分与垂直拆分

    近端时间在面试,发现很多面试官或者面试都把数据的水平拆分合垂直拆分给搞混了,今天特意写了一篇博客来说说水平拆分和垂直拆分希望对程序猿们有所帮助. 数据库水平与垂直拆分: 垂直(纵向)拆分:是指按功能模 ...

随机推荐

  1. VC++6.0在win8.1系统下运行失败的解决办法

    在win8.1系统下安装了VC++6,.0编译软件之后,发现打不开.出现下面的错误: 解决办法: 安装文件目录:Microsoft Visual Studio--common--MSDev98--Bi ...

  2. iOS之ViewController的多层presentViewController的dismiss问题

    今天在Q群里有人问了个这么个问题: A,B,C,D 都是Viewcontroller.A.B.C.D使用present去切的 他是这么搞的: A -> B, B ->C, C->D, ...

  3. 用css属性画出一棵圣诞树

    对于学习前端的童鞋,css的掌握是必须的.今天就来实现用css画出一棵圣诞树. 主要练习的是css里面border的练习与掌握程度. 在body创建一个主区域<div></div&g ...

  4. 【Salvation】——登录注册存储数据&验证用户

    写在前面:登录注册功能是在纯Unity3D环境内实现的,用到UGUI绘制界面技术,数据库的部分是后面拓展加进来的,这里数据存储是指存在XML用户文件中. 注册用户名和密码 zc() 用户名和密码登录 ...

  5. Disharmony Trees

    /* 写完这篇博客有很多感慨,过去一段时间都是看完题解刷题,刷题,看会题解,没有了大一那个时候什么都不会的时候刷题的感觉,这个题做了一天半,从开始到结束都是从头开始自己构思的很有感觉,找回到当初的感觉 ...

  6. Windows下caffe的配置和调用caffe库(一)

    一.Windows下caffe的配置: 1. 下载caffe官网提供的开发包,https://github.com/microsoft/caffe 2. 将caffe-master目录下的Window ...

  7. 「Vue」起步 - vue-router路由与页面间导航

    vue-router 我们知道路由定义了一系列访问的地址规则,路由引擎根据这些规则匹配找到对应的处理页面,然后将请求转发给页进行处理.可以说所有的后端开发都是这样做的,而前端路由是不存在"请 ...

  8. 树莓派配置允许WINDOWS远程桌面 x11nvc+xrdp

    20171109 网上很多设置教程都比较老旧,于是自己整理一下顺便分享下 开启SSH后,使用PUTTY连接. 安装x11vnc sudo apt-get install x11vnc 设置密码 sud ...

  9. jQuery插件实现瀑布留布局masonry + infinitescroll 图片高度处理

    jQuery插件实现瀑布留布局masonry + infinitescroll . 使用官方的示例代码实际测试发现,当上传到服务器的时候,由于图片下载速度问题,导致图片高度不能被正确识别,从而造成层的 ...

  10. Grafana+Prometheus系统监控之钉钉报警功能

    介绍 钉钉,阿里巴巴出品,专为中国企业打造的免费智能移动办公平台,含PC版,Web版和手机版.智能办公电话,消息已读未读,DING消息任务管理,让沟通更高效:移动办公考勤,签到,审批,企业邮箱,企业网 ...