昊虹君 发表于 2023-3-8 10:19

利用图像在垂直方向上的投影找寻字符在图像中的大概位置(利用离散序列一阶差分找寻序列下降沿)

利用图像在垂直方向上的投影找寻字符在图像中的大概位置(利用离散序列一阶差分找寻序列下降沿)

图像在水平方向上的投影的定义为:每行的灰度累计值,这些值串起来构成了水平方向上的投影曲线;

图像在垂直方向上的投影的定义为:每列的灰度累计值,这些值串起来构成了垂直方向上的投影曲线。

在OpenCV中,可以使用函数reduce()快速求出图像在水平方向和垂直方向的投影,其C++原型如下:
void cv::reduce(InputArray src,
                OutputArray dst,
                int dim,
                int rtype,
                int dtype = -1 )
这个函数要求输入矩阵是二维矩阵。

参数dim表示是将矩阵减至一行还是一列。
当dim=0时,将矩阵减至一行;
当dim=1,将矩阵减至一列。

参数rtype表示在对矩阵作缩减操作的运算类型,有以下几种取值:
http://pic1.hhai.cc/pic1/2023/2023-03/001/30.png
最后一个参数 dtype取负值时,输出向量的数据类型和输入矩阵一样。

图像在水平方向上和在垂直方向上的投影是一维离散序列,我们可以通过差分运算来找寻序列的下降沿、上升沿、极大值(波峰)、极小值(波谷),详细原理见我的另一篇博文,链接如下:
https://www.hhai.cc/thread-231-1-1.html

查找离散序列下降沿、上升沿、极大值(波峰)、极小值(波谷)的用途:
常用于图像分割、字符检测及提取、文本分类等领域。
为什么有这样的作用?因为查到上面这些特殊点就相当于是找到了字符的大概位置,大家可结合下面这个代码的运行结果进行理解。

下面这个代码通过寻找“图像在垂直方向上的投影”的下降沿,从而定位出了图像中字符的大致位置。

代码中用到的图的下载链接:
链接:https://pan.baidu.com/s/1WQtLtyPBPZgM1EpPOxXoLg 提取码:44fd
//出处:昊虹AI笔记网(hhai.cc)
//用心记录计算机视觉和AI技术

//博主微信/QQ 2487872782
//QQ群 271891601
//欢迎技术交流与咨询

//OpenCV版本 OpenCV3.0

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace std;
using namespace cv;


// 计算图像垂直方向投影的下降沿,并标注在原图中
void findPeak(cv::Mat srcImage, vector<int>& resultVec)
{
        cv::Mat verMat;
        cv::Mat resMat = srcImage.clone();
        // 阈值化操作
        int thresh = 130;
        int threshType = 0;
        // 预设最大值
        const int maxVal = 255;
        // 通过预设的阈值对图像进行二值化处理
        cv::threshold( srcImage, srcImage, thresh, maxVal , threshType );

        // 计算垂直投影
        srcImage.convertTo(srcImage, CV_32FC1);
        cv::reduce(srcImage, verMat, 0, CV_REDUCE_SUM);
        //std::cout << verMat << std::endl;

        // 求序列的一阶前向差分
        float* iptr = (float*)verMat.data;
        vector<int> first_order_diff(verMat.cols-1 , 0);
        for(int i=0;i<=verMat.cols-2;++i, ++iptr) //最后一个点的一阶前向差分值不存在,所以这里的范围是“0到verMat.cols-2”
        {
                first_order_diff=*(iptr + 1) - *iptr;;
        }

        //找出序列的下降沿位置
        for(int i =0;i<=verMat.cols-3;++i)
        {
                if(first_order_diff==0&&first_order_diff<0)
                {
                        resultVec.push_back(i+1);
                }
                  
        }

    // 输出下降沿位置,并绘制在原图中
        std::cout <<"下降沿位置 ";
    for(int i = 0; i< resultVec.size(); i++)
    {
            std::cout << resultVec << " ";
      for (int ii = 0; ii < resMat.rows; ++ii)
                {
                     resMat.at<uchar>(ii,resultVec)=255;
                }
    }
    imshow("resMat", resMat);
}
int main()
{
        cv::Mat image = imread("E:/material/images/P0035-Image-projection-02.jpg",0);
        if(!image.data)
                return 0;
        imshow("Image", image);
        vector<int> resultVec;
        findPeak(image, resultVec);
        cv::waitKey(0);
        return 0;
}
运行结果如下图所示:
http://pic1.hhai.cc/pic1/2023/2023-03/001/31.png
页: [1]
查看完整版本: 利用图像在垂直方向上的投影找寻字符在图像中的大概位置(利用离散序列一阶差分找寻序列下降沿)