昊虹AI笔记网

 找回密码
 立即注册
搜索
查看: 1090|回复: 0
收起左侧

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

[复制链接]

238

主题

241

帖子

931

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
931
昊虹君 发表于 2023-3-8 10:19 | 显示全部楼层 |阅读模式
利用图像在垂直方向上的投影找寻字符在图像中的大概位置(利用离散序列一阶差分找寻序列下降沿)

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

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

在OpenCV中,可以使用函数reduce()快速求出图像在水平方向和垂直方向的投影,其C++原型如下:
  1. void cv::reduce(InputArray src,
  2.                 OutputArray dst,
  3.                 int dim,
  4.                 int rtype,
  5.                 int dtype = -1 )
复制代码

这个函数要求输入矩阵是二维矩阵。

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

参数rtype表示在对矩阵作缩减操作的运算类型,有以下几种取值:

最后一个参数 dtype取负值时,输出向量的数据类型和输入矩阵一样。

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

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

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

代码中用到的图的下载链接:
链接:https://pan.baidu.com/s/1WQtLtyPBPZgM1EpPOxXoLg 提取码:44fd
[C++] 纯文本查看 复制代码
//出处:昊虹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[i]=*(iptr + 1) - *iptr;;
	}

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

    // 输出下降沿位置,并绘制在原图中
	std::cout <<"下降沿位置 ";
    for(int i = 0; i< resultVec.size(); i++)
    {
    	std::cout << resultVec[i] << " ";
        for (int ii = 0; ii < resMat.rows; ++ii)
		{
		     resMat.at<uchar>(ii,resultVec[i])=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;
}

运行结果如下图所示:

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|昊虹AI笔记网 ( 蜀ICP备2024076726 )

GMT+8, 2024-5-19 08:18 , Processed in 0.025479 second(s), 23 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表