opencv实现 Matlab 寻找峰值函数 findpeaks

findpeaks 寻找峰值函数

[pks,locs] = findpeaks(coutss,'minpeakdistance',30,'minpeakheight',mean_value-5);


opencv实现findpeaks(coutss,'minpeakdistance',30,'minpeakheight',mean_value-5); 


 

/*
输入参数:
Matdata: 输入的数据矩阵
minpeakdistance:设定两峰值间的最小间隔数
minpeakheight  :设定峰值的最小高度
输出函数:
mapPeaks_max        :按照key  值(灰度级0-255)排序的
Vector_map_Peaks_max:按照value值(各灰度级的像素值)排序的
备注:此函数只完成了波峰的提取,波谷自行完成
- zhang
*/
void findPeaks(const Mat Matdata, int minpeakdistance, int minpeakheight, std::map <int, double> &mapPeaks_max, vector<pair<int, double>>&Vector_map_Peaks_max)
{
	int row = Matdata.rows - 1;
	int col = Matdata.cols;
	vector<int> sign;
	vector<double> markdata;
	vector<double> markdata1;
	//minMaxLoc寻找矩阵(一维数组当作向量,用Mat定义) 中最小值和最大值的位置. 
	//类型转换注意:data为unchar* 
	double* pMatdata = (double*)Matdata.data;
	for (int i = 1; i < col; i++)
	{
		/*相邻值做差:
		*小于0,赋-1
		*大于0,赋1
		*等于0,赋0
		*/
		markdata1.push_back(*(pMatdata + i-1));
		int diff = *(pMatdata + i) - *(pMatdata + i-1);
		if (diff > 0)
		{
			sign.push_back(1);
		}
		else if (diff < 0)
		{
			sign.push_back(-1);
		}
		else
		{
			sign.push_back(0);
		}
	}
	//再对sign相邻位做差  
	//保存极大值和极小值的位置  
	vector<int> indMax;
	vector<int> indMin;
	std::map <int, double> mapPeaks_min;
	for (int j = 1; j < sign.size(); j++)
	{
		int diff = sign[j] - sign[j - 1];
		if (diff < 0)
		{
			indMax.push_back(j);
			//根据峰值最小高度进行筛选
			if ( *(pMatdata +  indMax[indMax.size() - 1]) > minpeakheight){
				mapPeaks_max.insert(pair<int, double>(j, *(pMatdata + indMax[indMax.size() - 1])));
            }
			
		}
		else if (diff>0)
		{
			indMin.push_back(j);
			mapPeaks_min.insert(pair<int, double>(j, *(pMatdata + indMin[indMin.size() - 1])));
			
		}
	}

	if (mapPeaks_max.size() >= 2){

		//找到像素值最大的对应的容器指针
		std::map<int, double>::iterator iter_high_max1_pos = std::max_element(std::begin(mapPeaks_max), std::end(mapPeaks_max), cmpDescending);
		int high_max1_pos = iter_high_max1_pos->first;//最高点的位置
		map<int, double>::iterator  iter;
		map<int, double>::iterator  temp;
		//以位置为序
		map<int, double>::iterator  iter_high_max1_pos;
		map<int, double>::iterator  iter_high_max1_pos_temp1;
		map<int, double>::iterator  iter_high_max1_pos_temp2;
		//知道峰值最高的对应容器指针
        //我们以最高峰值处进行作业搜索所以在此声明两个局部变量保存该指针
		iter_high_max1_pos_temp1= iter_high_max1_pos;
		iter_high_max1_pos_temp2 = iter_high_max1_pos;
	   
	    //rate为宽度,以iter_high_max1_pos为起点,根据minpeakdistance的距离倍数搜索
		//minpeakdistance宽度内取一个最大的峰值max_value_temp
		int rate = 1;
		double max_value_temp = 0;
		map<int, double>::iterator max_value_temp_iter;
		//每个minpeakdistance内的第一个指针防止被删除
		bool is_first_max = true;
		//挨着最大峰值的
		if (mapPeaks_max.size() >= 2){
			if (iter_high_max1_pos_temp1 != mapPeaks_max.begin()){
				
				for (iter = --iter_high_max1_pos_temp1; iter != mapPeaks_max.begin(); iter--){
					//小于minpeakdistance
					if (labs((*iter).first - high_max1_pos) < (rate)*minpeakdistance){
							temp = iter;
							iter++;
							mapPeaks_max.erase(temp);
					}
					if (rate*minpeakdistance<=labs((*iter).first - high_max1_pos) && labs((*iter).first - high_max1_pos)<=(rate+1)*minpeakdistance){
						if ((*iter).second > max_value_temp){
							max_value_temp = (*iter).second;
							if (is_first_max){
								max_value_temp_iter = iter;
								is_first_max = false;
							}
							else{
								//删除原先最大的
								mapPeaks_max.erase(max_value_temp_iter);
								temp = iter;
								iter++;
								max_value_temp_iter = temp; 
							}
						}
						else{
							is_first_max = true;
							max_value_temp = 0;
							temp = iter;
							iter++;
							mapPeaks_max.erase(temp);
						}
					}
					//大于(rate + 1)*minpeakdistance
					else if (labs((*iter).first - high_max1_pos)>(rate + 1)*minpeakdistance){
						 
							rate++;
							iter++;
					}
				}
			}
			is_first_max = true;
			if (iter_high_max1_pos_temp2 != mapPeaks_max.end() && mapPeaks_max.size()>=2){
			
				for (iter = ++iter_high_max1_pos_temp2; iter != mapPeaks_max.end(); iter++){
					//TRACE("2Vector:%d \n", debug++);
					//小于minpeakdistance
					if (labs((*iter).first - high_max1_pos) < (rate)*minpeakdistance){
						temp = iter;
						iter--;
						mapPeaks_max.erase(temp);
					}
					if (rate*minpeakdistance <= labs((*iter).first - high_max1_pos) && labs((*iter).first - high_max1_pos) <= (rate + 1)*minpeakdistance){

						if ((*iter).second > max_value_temp){
							max_value_temp = (*iter).second;
							if (is_first_max){
								max_value_temp_iter = iter;
								is_first_max = false;
							}
							else{
								//删除原先最大的
								mapPeaks_max.erase(max_value_temp_iter);
								
								temp = iter;
								iter--;
								max_value_temp_iter = temp;
							}
						}

					}
					//大于(rate + 1)*minpeakdistance
					else if (labs((*iter).first - high_max1_pos)>(rate + 1)*minpeakdistance){
						//初始化
						is_first_max = true;
						max_value_temp = 0;
						rate++;
						iter--;

					}
				}
				}
			//因为容器指针的begin()指针在上面的循环中未进行判断,所以这里单独处理
			//end()指的是最后一个元素的下一个位置所以不需要淡定进行判断
			map<int, double>::iterator max_value_temp_iter_more;
			if (mapPeaks_max.size() >= 2){
				max_value_temp_iter = mapPeaks_max.begin();
				max_value_temp_iter_more = max_value_temp_iter++;
				if (labs(max_value_temp_iter->first - max_value_temp_iter_more->first) < minpeakdistance){
					if (max_value_temp_iter->second > max_value_temp_iter_more->second){
						mapPeaks_max.erase(max_value_temp_iter_more);
					}
					else{
						mapPeaks_max.erase(max_value_temp_iter);
					}

				}
			}
		}
		Vector_map_Peaks_max.clear();
		//二维向量排序(根据函数选择以key或者value排序)
		sortMapByValue(mapPeaks_max, Vector_map_Peaks_max);
	}

}

//辅助函数
//降序
int cmpDescending (const pair<int, double>& x, const pair<int, double>&y)
{
	return  x.second<y.second;
}
//升序
int cmpAscending(const pair<int, double>& x, const pair<int, double>&y)
{
	return  x.second>y.second;
}
//完成MAP到vector 的转化并且完成排序
void sortMapByValue(map<int, double>& tMap, vector<pair<int, double>>& tVector)
{
	for (map<int, double>::iterator curr = tMap.begin(); curr != tMap.end(); curr++)
	{
		tVector.push_back(make_pair(curr->first, curr->second));
	}
	
	sort(tVector.begin(), tVector.end(), cmpAscending);
}


  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值