OpenCV中的双三次插值(imresize)会产生负值

4
我注意到在使用双三次插值法(downsampling)缩小openCV中的矩阵时,即使原始矩阵全为正值,仍然会得到负值。
我附上以下代码作为示例:
// Declaration of variables
cv::Mat M, MLinear, MCubic;
double minVal, maxVal;
cv::Point minLoc, maxLoc;
// Create random values in M matrix
M = cv::Mat::ones(1000, 1000, CV_64F);
cv::randu(M, cv::Scalar(0), cv::Scalar(1));
minMaxLoc(M, &minVal, &maxVal, &minLoc, &maxLoc);
// Printout smallest value in M
std::cout << "smallest value in M = "<< minVal << std::endl;

// Resize M to quarter area with bicubic interpolation and store in MCubic
cv::resize(M, MCubic, cv::Size(0, 0), 0.5, 0.5, cv::INTER_CUBIC);
// Printout smallest value in MCubic
minMaxLoc(MCubic, &minVal, &maxVal, &minLoc, &maxLoc);
std::cout << "smallest value in MCubic = " << minVal << std::endl;

// Resize M to quarter area with linear interpolation and store in MLinear
cv::resize(M, MLinear, cv::Size(0, 0), 0.5, 0.5, cv::INTER_LINEAR);
// Printout smallest value in MLinear
minMaxLoc(MLinear, &minVal, &maxVal, &minLoc, &maxLoc);
std::cout << "smallest value in MLinear = " << minVal << std::endl;

我不明白为什么会发生这种情况。我注意到,如果我在[0,100]之间选择随机值,则调整大小后的最小值通常为~-24,而范围为[0,1]的最小值为-0.24,如上面的代码所示。
作为比较,在Matlab中不会发生这种情况(我知道这里有一种轻微的加权方案差异,如此处所示:imresize comparison - Matlab/openCV)。
这是一个简短的Matlab代码片段,保存了任何1000个随机缩小矩阵中的最小值(每个矩阵的原始尺寸为1000x1000):
currentMinVal = 1e6;
for k=1:1000        
    x = rand(1000);
    x = imresize(x,0.5);
    minVal = min(currentMinVal,min(x(:)));
end
1个回答

3

如您在此答案中所见,双三次插值核不是非负的,因此,在某些情况下,负系数可能会占主导地位并产生负输出。

您还应该注意Matlab默认使用'Antialiasing',这会对结果产生影响:

I = zeros(9);I(5,5)=1; 
imresize(I,[5 5],'bicubic') %// with antialiasing
ans =
     0         0         0         0         0
     0    0.0000   -0.0000   -0.0000         0
     0   -0.0000    0.3055    0.0000         0
     0   -0.0000    0.0000    0.0000         0
     0         0         0         0         0

imresize(I,[5 5],'bicubic','Antialiasing',false) %// without antialiasing
ans =
     0         0         0         0         0
     0    0.0003   -0.0160    0.0003         0
     0   -0.0160    1.0000   -0.0160         0
     0    0.0003   -0.0160    0.0003         0
     0         0         0         0         0

那似乎是合理的。我猜这归结于Matlab和openCV中使用的随机数生成器 - 因为在Matlab中它从未变成负数,而在openCV中它总是产生负值。你同意这个假设(RNG)吗? - CV_User
1
@CV_User,OpenCv和Matlab使用的内核也有所不同。 - Shai
如果在Matlab中内核是非负的,而在openCV中不是非负的,那么这将是一个有效的解释。然而,它似乎在两种情况下都不是非负的,但是在Matlab中我没有得到负结果,而在openCV中却有。这可能与主题无关,但我尝试编辑imgwarp.cpp中的系数并保存它,但我想它需要更多的操作才能保持编辑。如何重新构建openCV以使此编辑生效?谢谢Shai! - CV_User
1
@CV_User,请查看我的编辑,关于“抗锯齿”选项。 - Shai
在我发布问题之前,我看到Matlab在其他相关答案中使用了抗锯齿技术,但没有想到检查一下Matlab在不使用该选项时是否会产生负值。糟糕...感谢您指出这一点!我想唯一的解决方法就是重新构建openCV,但我不知道该如何操作。看来是时候要进行一些搜索了... - CV_User
@CV_User,构建OpenCV非常有趣。祝好运,保持坚强! - Shai

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接