我试图用openCV在c++中重新实现matlab imregionalmax()
,我在网站上进行了搜索,并在这里找到了一些有趣的答案使用openCV在灰度图像中找到局部最大值,到目前为止最好的一个属于Doga Siyli,但有2个"奇怪"的函数。一个是:SANITYCHECK(squareSize,3,1)
,另一个是:maxUsedValInHistogramData(dst,false);
。(这里的"奇怪"是指我不认为这两个是OpenCV的功能)
我用assert(squareSize >= 3);
代替了SANITYCHECK(squaresize,3,1)
,用minmaxLoc
代替了maxUsedValInHistogramData(dst,false);
,但程序没有工作,特别是第二个,因为minmaxLoc
返回全局值,而Doga的意图是找到局部值。
那么我如何使代码工作呢?
我是c++和OpenCV的新手,我还在学习,任何帮助都会非常感激。
下面是他的代码(他确实解释得很清楚)
void localMaxima(cv::Mat src, cv::Mat &dst, int squareSize)
{
if (squareSize == 0)
{
dst = src.clone();
return;
}
Mat m0;
dst = src.clone();
Point maxLoc(0, 0);
//1.Be sure to have at least 3x3 for at least looking at 1 pixel close neighbours
// Also the window must be <odd>x<odd>
SANITYCHECK(squareSize, 3, 1);
int sqrCenter = (squareSize - 1) / 2;
//2.Create the localWindow mask to get things done faster
// When we find a local maxima we will multiply the subwindow with this MASK
// So that we will not search for those 0 values again and again
Mat localWindowMask = Mat::zeros(Size(squareSize, squareSize), CV_8U);//boolean
localWindowMask.at<unsigned char>(sqrCenter, sqrCenter) = 1;
//3.Find the threshold value to threshold the image
//this function here returns the peak of histogram of picture
//the picture is a thresholded picture it will have a lot of zero values in it
//so that the second boolean variable says :
// (boolean) ? "return peak even if it is at 0" : "return peak discarding 0"
int thrshld = maxUsedValInHistogramData(dst, false);
threshold(dst, m0, thrshld, 1, THRESH_BINARY);
//4.Now delete all thresholded values from picture
dst = dst.mul(m0);
//put the src in the middle of the big array
for (int row = sqrCenter; row<dst.size().height - sqrCenter; row++)
for (int col = sqrCenter; col<dst.size().width - sqrCenter; col++)
{
//1.if the value is zero it can not be a local maxima
if (dst.at<unsigned char>(row, col) == 0)
continue;
//2.the value at (row,col) is not 0 so it can be a local maxima point
m0 = dst.colRange(col - sqrCenter, col + sqrCenter + 1).rowRange(row - sqrCenter, row + sqrCenter + 1);
minMaxLoc(m0, NULL, NULL, NULL, &maxLoc);
//if the maximum location of this subWindow is at center
//it means we found the local maxima
//so we should delete the surrounding values which lies in the subWindow area
//hence we will not try to find if a point is at localMaxima when already found a neighbour was
if ((maxLoc.x == sqrCenter) && (maxLoc.y == sqrCenter))
{
m0 = m0.mul(localWindowMask);
//we can skip the values that we already made 0 by the above function
col += sqrCenter;
}
}
}
使用maxUsedValInHistogramData
函数通过定义阈值thrshld
来提高计算时间,然后使用cv::threshold
将thrshld
下的dst图像的所有像素设置为零。
根据解释,阈值由直方图max定义。这种方法是有效的,因为图像的很大一部分(设置为零)会被跳过:
if (dst.at<unsigned char>(row, col) == 0)
continue;
然而,这也意味着thrshld
下的局部最大值没有被检测到
您可以删除这三行,函数应该正常工作,但速度较慢:
int thrshld = maxUsedValInHistogramData(dst, false);
threshold(dst, m0, thrshld, 1, THRESH_BINARY);
dst = dst.mul(m0);
或编写一个函数来检测输入图像的直方图最大值