OpenCV中的saturate_cast是如何工作的?

5

无法理解,表达式Vxy和Vxy_nocast的结果

uchar init_m0[] = {10,10,30};
cv::Mat m0(3,1,CV_8UC1,init_m0,sizeof(uchar));
uchar& Vxy = m0.at<uchar>(0);
uchar& Vxy_nocast = m0.at<uchar>(1);
std::cout << m0 << std::endl;
Vxy = cv::saturate_cast<uchar>((Vxy-128)*2 + 128);
Vxy_nocast = (Vxy_nocast-128)*2 + 128;
std::cout << m0 << std::endl;

结果

[ 10;
  10;
  30]
[  0;
 148;
  30]

饱和转换保证不会发生整数溢出或下溢。通常情况下,如果您有一个无符号char类型的变量值为200,并加上56(+X),则会发生溢出,并且变量的值将为0(+X),这对许多算法来说非常非常糟糕。 - Micka
1
在这种情况下,我会说 code 是寻找答案的最佳位置。 - Dan Mašek
1个回答

8

(10-128)*2 + 128 = -108. cv::saturate_cast<uchar> 是一个饱和转换到无符号字符的操作,而无符号字符只能是 >= 0。普通的无符号字符转换(如果你没有指定任何内容,则会隐式发生),会通过重新解释位将负值包装成正值,-108在二进制的补码中为10010100,这与148相同(它也将包装大的值,例如257到1)。相反,饱和转换将把负值转换为0,以类型的最小值(以及正值将饱和于255的最大值)。

更多详情请参见饱和算术


因此,在这种情况下,saturation_cast 多了一步。它会查找 MSB,如果 MSB 为 1,则将结果设为 0。在普通转换中,它只会从 32 位截断到 8 位,并以二进制补码形式显示结果。 - infoclogged
有点类似,但它超越了无符号字符的8位,以确定它是否太大或太小。如果在支持饱和算术的硬件上运行,则这个额外步骤可能不比正常加法更昂贵。 - hcs
这个问题没有标记语言,那么 Python 绑定会发生什么呢?饱和算术是 OpenCV 矩阵操作的默认方式,例如 imgblend = 0.2*img1 + 0.8*img2 将产生预期的结果与 OpenCV 矩阵一起,但对于存储在 Python Numpy 数组中的图像,必须显式地进行饱和处理:imgblend = cv2.add(0.2*img1, 0.8*img2)以确保没有舍入导致溢出。 - mins

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