mirror of
https://github.com/opencv/opencv_contrib.git
synced 2025-10-24 03:03:35 +08:00
ximgproc: fix weightedMedianFilter() hang
- eliminated "float th = 1e-5f" magic value (replaced to explicit checks) - eliminate manual memory allocation - avoid out of range access (i == alls)
This commit is contained in:
@@ -55,51 +55,64 @@ using namespace cv::ximgproc;
|
||||
void from32FTo32S(Mat &img, Mat &outImg, int nI, float *mapping)
|
||||
{
|
||||
int rows = img.rows, cols = img.cols;
|
||||
int alls = rows * cols;
|
||||
size_t alls = (size_t)rows * cols;
|
||||
|
||||
CV_Assert(img.isContinuous());
|
||||
float *imgPtr = img.ptr<float>();
|
||||
typedef pair<float,int> pairFI;
|
||||
pairFI *data = (pairFI *)malloc(alls*sizeof(pairFI));
|
||||
std::vector<pairFI> data(alls);
|
||||
|
||||
// Sort all pixels of the image by ascending order of pixel value
|
||||
for(int i=0;i<alls;i++){
|
||||
data[i].second = i;
|
||||
data[i].first = imgPtr[i];
|
||||
for (size_t i = 0; i < alls; i++)
|
||||
{
|
||||
pairFI& d = data[i];
|
||||
d.second = i;
|
||||
d.first = imgPtr[i];
|
||||
}
|
||||
sort(data,data+alls);
|
||||
|
||||
struct PixelValueOrder {
|
||||
static bool compare(const pairFI &a, const pairFI &b) {
|
||||
return a.first < b.first;
|
||||
}
|
||||
};
|
||||
sort(data.begin(), data.end(), PixelValueOrder::compare);
|
||||
|
||||
// Find lower bound and upper bound of the pixel values
|
||||
double maxVal,minVal;
|
||||
minMaxLoc(img,&minVal,&maxVal);
|
||||
float maxRange = (float)(maxVal - minVal);
|
||||
float th = 1e-5f;
|
||||
double maxVal = data[alls - 1].first, minVal = data[0].first;
|
||||
|
||||
const float maxRange = (float)(maxVal - minVal);
|
||||
|
||||
float l = 0, r = maxRange*2.0f/nI;
|
||||
// Perform binary search on error bound
|
||||
while(r-l > th)
|
||||
while (r > l)
|
||||
{
|
||||
float m = (r+l)*0.5f;
|
||||
float m = (r + l) * 0.5f;
|
||||
if (m == r || m == l)
|
||||
break; // bailout on numeric accuracy limit
|
||||
bool suc = true;
|
||||
float base = (float)minVal;
|
||||
int cnt=0;
|
||||
for(int i=0;i<alls;i++)
|
||||
int cnt = 0;
|
||||
for (size_t i = 0; i < alls; i++)
|
||||
{
|
||||
if(data[i].first>base+m)
|
||||
if (data[i].first > base + m)
|
||||
{
|
||||
cnt++;
|
||||
base = data[i].first;
|
||||
if(cnt==nI)
|
||||
if (cnt == nI)
|
||||
{
|
||||
suc = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(suc)r=m;
|
||||
else l=m;
|
||||
if (suc)
|
||||
r = m;
|
||||
else
|
||||
l = m;
|
||||
}
|
||||
|
||||
Mat retImg(img.size(),CV_32SC1);
|
||||
CV_Assert(retImg.isContinuous());
|
||||
int *retImgPtr = retImg.ptr<int>();
|
||||
|
||||
// In the sorted list, divide pixel values into clusters according to the minimum error bound
|
||||
@@ -108,23 +121,22 @@ void from32FTo32S(Mat &img, Mat &outImg, int nI, float *mapping)
|
||||
float base = (float)minVal;
|
||||
int baseI = 0;
|
||||
int cnt = 0;
|
||||
for(int i=0;i<=alls;i++)
|
||||
for (size_t i = 0; i < alls; i++)
|
||||
{
|
||||
if(i==alls || data[i].first>base+r)
|
||||
if (data[i].first > base + r)
|
||||
{
|
||||
mapping[cnt] = data[(baseI+i-1)>>1].first; //median
|
||||
if(i==alls)break;
|
||||
cnt++;
|
||||
base = data[i].first;
|
||||
baseI = i;
|
||||
}
|
||||
retImgPtr[data[i].second] = cnt;
|
||||
}
|
||||
|
||||
free(data);
|
||||
// tail: i == alls
|
||||
mapping[cnt] = data[(baseI+alls-1)>>1].first; // median
|
||||
|
||||
//end of the function
|
||||
outImg = retImg;
|
||||
swap(outImg, retImg);
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
@@ -134,6 +146,8 @@ void from32FTo32S(Mat &img, Mat &outImg, int nI, float *mapping)
|
||||
void from32STo32F(Mat &img, Mat &outImg, float *mapping)
|
||||
{
|
||||
Mat retImg(img.size(),CV_32F);
|
||||
CV_Assert(img.isContinuous());
|
||||
CV_Assert(retImg.isContinuous());
|
||||
int rows = img.rows, cols = img.cols, alls = rows*cols;
|
||||
float *retImgPtr = retImg.ptr<float>();
|
||||
int *imgPtr = img.ptr<int>();
|
||||
|
Reference in New Issue
Block a user