简体   繁体   English

“断言”功能:奇怪的行为

[英]'assert' function : weird behavior

I am developping on Windows 7 in C++ with Qt Creator. 我正在使用Qt Creator在C ++的Windows 7上进行开发。 I also use the library OpenCV 我也使用库OpenCV

I came up against a strange problem with the function assert . 我用函数assert遇到了一个奇怪的问题。 I developed a function that makes a linear transformation on an image in order to get a better contrast, with the possibility to specify a zone (x1,x2,y1,y2) of the image we want to work on and also a tolerance (Tolmin and Tolmax) : the percentile of the histogram we want to ignore. 我开发了一个函数,可以对图像进行线性变换以获得更好的对比度,并可以指定我们要处理的图像区域(x1,x2,y1,y2)以及公差(Tolmin和Tolmax):我们要忽略的直方图的百分位数。

I need to make sure that : 我需要确保:

  • Image is 16bits grayscale (img.type()=CV_16U && img.channels()=1) 图片为16位灰度(img.type()= CV_16U && img.channels()= 1)
  • Zone coordinates are correct (positive, do not exceed image size ...) 区域坐标正确(正,不要超过图像大小...)
  • Tolmin,Tolmax positive and Tolmin+Tolmax != 1 (if Tolmin+Tolmax=1 there will be a division by 0) Tolmin,Tolmax正且Tolmin + Tolmax!= 1(如果Tolmin + Tolmax = 1,则除以0)

I used the function assert 我使用了函数assert

My code is the following : 我的代码如下:

void equalizeHist_16U_linear(Mat &img, float Tolmin, float Tolmax, int x1, int x2, int y1, int y2)
{
    assert(img.channels() == 1);
    assert(img.type() == CV_16U);
    assert(x1>=0 && y1>=0 && x2>=x1 && y2>=y1);
    assert(y2<img.rows && x2<img.cols);
    assert(Tolmin>0 && Tolmax>0);
    assert(Tolmin+Tolmax != 1.0);

    ## code ##
    ...

}

The five first assert works fine, but the last one assert(Tolmin+Tolmax != 1.0) does not work. 前五个assert可以正常工作,但最后一个assert(Tolmin+Tolmax != 1.0)不起作用。 Even when Tolmin+Tolmax=1 , assert does not stop the execution so the program crashes (division by 0). 即使当Tolmin+Tolmax=1 ,assert也不停止执行,因此程序崩溃(被0除)。 To be sure, I printed Tolmin+Tolmax before the assert call. 可以肯定的是,我在assert调用之前打印了Tolmin+Tolmax

void equalizeHist_16U_linear(Mat &img, float Tolmin, float Tolmax, int x1, int x2, int y1, int y2)
{
    cout << endl << "Tolmin+Tolmax = " << Tolmin+Tolmax << endl;

    assert(img.channels() == 1);
    assert(img.type() == CV_16U);
    assert(x1>=0 && y1>=0 && x2>=x1 && y2>=y1);
    assert(y2<img.rows && x2<img.cols);
    assert(Tolmin>0 && Tolmax>0);
    assert(Tolmin+Tolmax != 1.0);

    ## code ##
    ...

}

It displays "Tolmin+Tolmax=1", and this time, assert stopped the execution of the program ! 它显示“ Tolmin + Tolmax = 1”,这一次, assert停止了程序的执行!

How is it possible ? 这怎么可能 ? Why does the display of Tolmin+Tolmax makes assert work ? 为什么显示Tolmin+Tolmax可以使assert起作用?

I tried to add the following : 我试图添加以下内容:

void equalizeHist_16U_linear(Mat &img, float Tolmin, float Tolmax, int x1, int x2, int y1, int y2)
{
    float sum = Tolmin+Tolmax;

    assert(img.channels() == 1);
    assert(img.type() == CV_16U);
    assert(x1>=0 && y1>=0 && x2>=x1 && y2>=y1);
    assert(y2<img.rows && x2<img.cols);
    assert(Tolmin>0 && Tolmax>0);*/
    assert(sum != 1.0);

    ## code ##
    ...

}

But it does not work either. 但这也不起作用。

My guess is that a value is being used in your code (as Tolmin or Tolmax) which cannot be represented in a machine's number format. 我的猜测是您的代码中使用了一个值(如Tolmin或Tolmax),而该值不能以机器的数字格式表示。 What do I mean? 我什么意思 Well there are numbers that you can easily think of which a computer cannot store them exactly as they are. 好了,您可以轻松地想到哪些数字计算机无法完全按原样存储它们。 Computers have to store numbers in a finite digit binary formats and as a result some numbers will not be stored exactly as they are. 计算机必须以有限数字的二进制格式存储数字,因此某些数字将无法完全按原样存储。 Think about it this way, we can think of the number (2/3) right? 这样想,我们可以想到数字(2/3)对吗? but when we have to represent this number in a decimal format with finite digits, we have to round it like this: 0.66666667 hence we cannot exactly write this number as it is. 但是当我们必须用有限的数字以十进制格式表示此数字时,我们必须将其舍入为:0.66666667,因此我们无法准确地按原样写入此数字。 This case can accrue in a machine too for example we cannot have number 0.2 stored in a machine in binary format because its representative digits in binary is infinite, a machine will just round such numbers to the closest it can store. 这种情况也可以在机器中产生,例如,我们不能以二进制格式将数字0.2存储在机器中,因为其二进制代表数字是无限的,机器会将这些数字四舍五入到可以存储的最接近的数字。 In your case, you are comparing a converted-to-binary number to an absolute value (1.0) and logically they are not the same even if they are very close to each other. 在您的情况下,您正在将转换后的二进制数与绝对值(1.0)进行比较,从逻辑上讲,即使它们彼此非常接近,它们也不相同。 So my guess is that the sum of Tolmin and Tolmax will be something very close to 1.0 but not exactly 1.0. 所以我的猜测是Tolmin和Tolmax的总和将非常接近1.0,但不完全是1.0。 So whats the solution? 那么解决方案是什么? you should check if sum has passed an arbitrary interval to 1.0 or not. 您应该检查总和是否已超过1.0的任意间隔。 Something like this: 像这样:

assert(abs(sum - 1.0) > 0.0001)

UPDATE: I couldn't reproduce your reported behavior while printing it, both with gcc and MSC++ so all I can do is a weak guess. 更新:我无法在使用gcc和MSC ++进行打印时重现您报告的行为,因此,我只能做一个很弱的猜测。 When you build your code, compiler will revise it in an optimization phase. 生成代码时,编译器将在优化阶段对其进行修改。 You are ordering to compute Tolmin+Tolmax in two places, first in cout and second in assert, so compiler will deduce that this computation can be done once and then reuse it's result. 您要在两个位置上分别计算Tolmin+Tolmax ,首先在cout中,其次在assert中,因此编译器将推断出该计算可以执行一次,然后再使用它的结果。 As cout reforms the number you order to display, and the value is so close to 1, it will be rounded and get the exact value 1 and then the result will be reused in assert. 当cout更改您要显示的数字时,该值非常接近1,它将被四舍五入并获得确切的值1,然后结果将在assert中重用。 It can be the case or not, I cannot confirm it as I couldn't reproduce the reported behavior. 是否可以,我无法确认,因为我无法重现报告的行为。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM