OpenCV学习笔记(三)之投影峰谷查找

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/spw_1201/article/details/53510798

投影峰谷查找:

图像的投影特征是分析图像中目标灰度变化规律的重要技术之一,一般是通过计算图像的X或Y轴的投影曲线,来分析其波峰波谷分布特征以实现目标分析,该技术常用于图像分割、字符检测及提取及文本分类等情况。对于投影曲线而言,波峰/波谷通常存在于曲线的极值点出,即图像变化为零的点。从离散曲线特征来看,波峰点是图像的局部最大值点,波谷点是图像的局部最小值点。波峰波谷的计算不能简单通过投影点前后大小直接求得,在实际应用中,通常采用差分遍历向量法来实现波峰波谷的查找。

对于图像f(x,y),对其行或者列进行叠加累计求和得到一维向量S,一维向量中的每个数代表第几行或者第几列的灰度累计值。计算其投影曲线S的波峰/波谷的步骤如下:

(1)计算差分向量,对投影曲线向量S计算一阶差分向量D=S(i+1)-S(i)。

(2)判定向量符号。对上一步得到的差分向量D进行符号判定,得到D(s)=sign(D)。即遍历向量D。若D(i)>0,则通过符号函数D(s)值为1;若D(i)<0,则符号函数D(s)值为-1;其他的情况D(s)值为0。

(3)遍历差分方程。对上一步得到的向量D(s)逆序遍历,根据向量元素的变化规律重新更新向量D(s)。具体判定规则为:D(s)=0且D(s)(i+1)>=0,则D(s)=1;若D(s)=0且D(s)(i+1)<0,则D(s)=-1。

(4)差分遍历判定峰谷。若D(s)(i+1)-D(s)(i)=-2,则i+1为投影向量S的一个波峰位置点,对应的波峰值为S(i+1);若D(s)(i+1)-D(s)(i)= 2,则i+1为投影向量S的一个波谷位置点,对应的波峰值为S(i+1)。

#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include <stdio.h>
#include <vector>
using namespace cv;
using namespace std;
void findPeak(Mat srcImage, vector<int>& resultVec)
{
	Mat verMat;
	Mat resMat = srcImage.clone();//克隆矩阵,分配独立空间
	//阈值化操作
	int thresh = 130;
	int threshType = 0;
	//预设最大值
	const int maxVal = 255;
	//固定阈值化操作
	threshold(srcImage, srcImage, thresh, maxVal, threshType);
	srcImage.convertTo(srcImage, CV_32FC1);
	//计算垂直投影
	reduce(srcImage, verMat, 0, CV_REDUCE_SUM);//合并成列,计算所有向量的总和,转化成矩阵
	cout << verMat << endl;
	//遍历求差分符号函数
	float* iptr = ((float*)verMat.data) + 1;
	//生成一列向量tempVec
	vector<int> tempVec(verMat.cols - 1, 0);
	//对差分向量进行符号判定,
	for (int i = 0; i < verMat.cols - 1; ++i, ++iptr)
	{
		if (*(iptr + 1) - *iptr>0)
			tempVec[i] = 1;
		else if (*(iptr + 1) - *iptr < 0)
			tempVec[i] = -1;
		else
			tempVec[i] = 0;
	}
	//对符号函数进行遍历
	for (int i = tempVec.size() - 1; i >= 0; i--)
	{
		if (tempVec[i] == 0 && i == tempVec.size() - 1)
		{
			tempVec[i] = 1;
		}
		else if (tempVec[i] == 0)
		{
			if (tempVec[i + 1] >= 0)
				tempVec[i] = 1;
			else
				tempVec[i] = -1;
		}
	}
	//波峰判断输出
	for (vector<int>::size_type i = 0; i != tempVec.size() - 1; i++)
	{
		if (tempVec[i + 1] - tempVec[i] == -2)
			//认为i+1为投影向量S的一个波峰位置点,把点加入到resultVec中
			resultVec.push_back(i + 1);
	}
	//输出波峰位置
	for (int i = 0; i < resultVec.size(); i++)
	{
		cout << resultVec[i] << '\t';
		//波峰位置为255
		for (int ii = 0; ii < resMat.rows; ++ii)
		{
			resMat.at<uchar>(ii, resultVec[i]) = 255;
		}
	}
	imshow("resMat", resMat);
}
int main()
{
	Mat srcImage = imread("d:\\1.jpg",0);
	if (!srcImage.data)
		return -1;
	imshow("Image", srcImage);
	vector<int> resultVec;
	findPeak(srcImage, resultVec);
	waitKey(0);
	return 0;

}


没有更多推荐了,返回首页

私密
私密原因:
请选择设置私密原因
  • 广告
  • 抄袭
  • 版权
  • 政治
  • 色情
  • 无意义
  • 其他
其他原因:
120
出错啦
系统繁忙,请稍后再试