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)
|
void from32FTo32S(Mat &img, Mat &outImg, int nI, float *mapping)
|
||||||
{
|
{
|
||||||
int rows = img.rows, cols = img.cols;
|
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>();
|
float *imgPtr = img.ptr<float>();
|
||||||
typedef pair<float,int> pairFI;
|
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
|
// Sort all pixels of the image by ascending order of pixel value
|
||||||
for(int i=0;i<alls;i++){
|
for (size_t i = 0; i < alls; i++)
|
||||||
data[i].second = i;
|
{
|
||||||
data[i].first = imgPtr[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
|
// Find lower bound and upper bound of the pixel values
|
||||||
double maxVal,minVal;
|
double maxVal = data[alls - 1].first, minVal = data[0].first;
|
||||||
minMaxLoc(img,&minVal,&maxVal);
|
|
||||||
float maxRange = (float)(maxVal - minVal);
|
const float maxRange = (float)(maxVal - minVal);
|
||||||
float th = 1e-5f;
|
|
||||||
|
|
||||||
float l = 0, r = maxRange*2.0f/nI;
|
float l = 0, r = maxRange*2.0f/nI;
|
||||||
// Perform binary search on error bound
|
// 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;
|
bool suc = true;
|
||||||
float base = (float)minVal;
|
float base = (float)minVal;
|
||||||
int cnt=0;
|
int cnt = 0;
|
||||||
for(int i=0;i<alls;i++)
|
for (size_t i = 0; i < alls; i++)
|
||||||
{
|
{
|
||||||
if(data[i].first>base+m)
|
if (data[i].first > base + m)
|
||||||
{
|
{
|
||||||
cnt++;
|
cnt++;
|
||||||
base = data[i].first;
|
base = data[i].first;
|
||||||
if(cnt==nI)
|
if (cnt == nI)
|
||||||
{
|
{
|
||||||
suc = false;
|
suc = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(suc)r=m;
|
if (suc)
|
||||||
else l=m;
|
r = m;
|
||||||
|
else
|
||||||
|
l = m;
|
||||||
}
|
}
|
||||||
|
|
||||||
Mat retImg(img.size(),CV_32SC1);
|
Mat retImg(img.size(),CV_32SC1);
|
||||||
|
CV_Assert(retImg.isContinuous());
|
||||||
int *retImgPtr = retImg.ptr<int>();
|
int *retImgPtr = retImg.ptr<int>();
|
||||||
|
|
||||||
// In the sorted list, divide pixel values into clusters according to the minimum error bound
|
// 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;
|
float base = (float)minVal;
|
||||||
int baseI = 0;
|
int baseI = 0;
|
||||||
int cnt = 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
|
mapping[cnt] = data[(baseI+i-1)>>1].first; //median
|
||||||
if(i==alls)break;
|
|
||||||
cnt++;
|
cnt++;
|
||||||
base = data[i].first;
|
base = data[i].first;
|
||||||
baseI = i;
|
baseI = i;
|
||||||
}
|
}
|
||||||
retImgPtr[data[i].second] = cnt;
|
retImgPtr[data[i].second] = cnt;
|
||||||
}
|
}
|
||||||
|
// tail: i == alls
|
||||||
free(data);
|
mapping[cnt] = data[(baseI+alls-1)>>1].first; // median
|
||||||
|
|
||||||
//end of the function
|
//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)
|
void from32STo32F(Mat &img, Mat &outImg, float *mapping)
|
||||||
{
|
{
|
||||||
Mat retImg(img.size(),CV_32F);
|
Mat retImg(img.size(),CV_32F);
|
||||||
|
CV_Assert(img.isContinuous());
|
||||||
|
CV_Assert(retImg.isContinuous());
|
||||||
int rows = img.rows, cols = img.cols, alls = rows*cols;
|
int rows = img.rows, cols = img.cols, alls = rows*cols;
|
||||||
float *retImgPtr = retImg.ptr<float>();
|
float *retImgPtr = retImg.ptr<float>();
|
||||||
int *imgPtr = img.ptr<int>();
|
int *imgPtr = img.ptr<int>();
|
||||||
|
Reference in New Issue
Block a user