C语言 二维矩阵极值查找(仿python的peak_local_max函数)

350 阅读2分钟

函数功能:

  • 返回一个二维矩阵中查找到的极值坐标列表

参数说明

  • data:二维数组
  • row:二维数组宽
  • col:二维数组长
  • min_distance:最小步长(影响极值检测的临近距离)

用到的功能函数:

  • getIndexOfArr:用于返回能对应二维数组索引位置的一维索引数值
  • findPosByIndex:查找指定范围内是否有已检测的点
  • getPeakPoses:获取锚点(以锚点为中心,步长为半径区域检索极值)

代码:

typedef struct {

float value;
int x;
int y;
int maxLen;

}peakPos;

peakPos* myPeak_local_max_noLen(float* data, int row, int col, int min_distance) {

//!!data的宽高必须和row与col完全一致,不得出现data[10][10],row=3,col=2的情况
int err = 0;
peakPos* peaks = NULL;
int peakIndex = 0;
peakPos maxPoint = { 0 };
int moveLen = min_distance * 2 + 1;
int findIndex = 0;
int arrStyle[2] = { col, row };
int posIndex[2] = { 0 };
float curValue = 0.0f;
peakPos Anchor[500] = { 0 };

if (data == NULL)
	return NULL;

int maxLen = 0;

err = getPeakPoses(20, 20, min_distance, Anchor, &maxLen);
peaks = (peakPos*)malloc(sizeof(peakPos) * maxLen);

for (int i = 0; i < maxLen; i++) {//遍历各锚点区
	for (int j = Anchor[i].x - min_distance; j <= Anchor[i].x + min_distance; j++) {
		for (int k = Anchor[i].y - min_distance; k <= Anchor[i].y + min_distance; k++) {
			if (j > col || k > row)
				continue;
			posIndex[0] = j;	posIndex[1] = k;
			curValue = data[getIndexOfArr(arrStyle, 2, posIndex)];
			if (j == Anchor[i].x - min_distance && k == Anchor[i].y - min_distance) {//
				maxPoint.value = curValue;
				maxPoint.x = j;
				maxPoint.y = k;
				continue;
			}
			if (curValue > maxPoint.value) {
				maxPoint.value = curValue;
				maxPoint.x = j;
				maxPoint.y = k;
			}
		}
	}
	if (maxPoint.value == 0)
		continue;
	findIndex = findPosByIndex(peaks, peakIndex, maxPoint.x, maxPoint.y, min_distance);
	if (findIndex >= 0) {
		if (peaks[findIndex].value < maxPoint.value) {
			peaks[peakIndex++] = maxPoint;
		}
	}
	else {
		peaks[peakIndex++] = maxPoint;
	}

	maxPoint.value = 0;
	maxPoint.x = 0;
	maxPoint.y = 0;
}
peaks[0].maxLen = peakIndex;
return peaks;

}

int getIndexOfArr(int* inArrStyle, int nD, int* PosIndex) {

int index = 0;

if (inArrStyle == NULL || PosIndex == NULL)
	return -1;
if (nD <= 0 || nD > 4)
	return -2;

if (nD == 1) {
	return PosIndex[0];
}
else if (nD == 2) {
	index = PosIndex[0] * inArrStyle[1] + PosIndex[1];
}
else if (nD == 3) {
	index = PosIndex[2] + PosIndex[1] * inArrStyle[2] + PosIndex[0] * inArrStyle[1] * inArrStyle[2];//2*4*3 + 2*3 + 2
}
else if (nD == 4) {
	index = PosIndex[3] + PosIndex[0] * inArrStyle[1] * inArrStyle[2] * inArrStyle[3] + PosIndex[1] * inArrStyle[2] * inArrStyle[3] + PosIndex[2] * inArrStyle[3];//2 + 5*5*4*3+4*4*3+3*3
}
else {
	//
	for (int i = 0;; i++) {

	}
}

return index;

} int findPosByIndex(peakPos* inArr, int len, int x, int y, int min_distance) {

int i = 0;
for (i = 0; i < len; i++) {
	if (myAbs_int(inArr[i].x - x) <= min_distance && myAbs_int(inArr[i].y - y) <= min_distance) {
		return i;
	}
}
return -1;

} int getPeakPoses(int row, int col, int min_distance, peakPos* outArr, int* outLen) {

int index = 0;
int moveLen = min_distance * 2 + 1;
if (outArr == NULL || outLen == NULL)
	return -1;
for (int i = min_distance + 1; i <= col; i += moveLen) {
	for (int j = min_distance + 1; j <= row; j += moveLen) {
		outArr[index].x = i;
		outArr[index].y = j;
		//printf("[%d,%d]\n",i,j);
		index++;
	}
}
*outLen = index;
return 0;

}