主要问题是(cx > 0.5) 的类型是CV_8U 而不是CV_32F。
看看下面的代码示例:
//Initialize 3x3 matrix for example
cv::Mat cx = (cv::Mat_<float>(3, 3) << 5.0f, 0, 0, 0, 5.0f, 0, 0, 0, 5.0f);
//The type of "logical matrix" result of (cx > 0.5f) is UINT8 (255 where true).
cv::Mat cx_above05 = (cx > 0.5f);
为方便起见,我使用 Image Watch 和 Visual Studio 2017。
这是cv::Mat cx_above05 = (cx > 0.5f)的结果:
如您所见,类型为UINT8,值为255,其中cx>0.5 和0 不是。
您可以使用convertTo 将类型转换为CV_32F 并除以255:
cx_above05.convertTo(cx_above05 , CV_32F, 1.0/255.0); //Convert type to float (1.0f where true).
结果:
如您所见,类型为FLOAT32,255 的值转到1.0f
完整的代码示例:
cv::Mat cx = (cv::Mat_<float>(3, 3) << 5.0f, 0, 0, 0, 5.0f, 0, 0, 0, 5.0f); //Initialize 3x3 matrix for example
cv::Mat cx_above05 = (cx > 0.5f); //The type of "logical matrix" result of (cx > 0.5f) is UINT8 (255 where true).
cx_above05.convertTo(cx_above05 , CV_32F, 1.0/255.0); //Convert type to float (1.0f where true).
cv::Mat c0 = cx_above05.mul((cx - 0.5f) * 2.0f);
结果:
我们可以使用 OpenCV pow documentation 中描述的技巧,而不是乘以掩码:
cv::Mat cx = (cv::Mat_<float>(3, 3) << 5.0f, 0, 0, 0, 5.0f, 0, 0, 0, 5.0f); //Initialize 3x3 matrix for example
cv::Mat mask = (cx <= 0.5f); //The type of "logical matrix" result of (cx <= 0.5f) is UINT8 (255 where true).
cv::Mat c0 = (cx - 0.5f) * 2.0f;
cv::subtract(c0, c0, c0, mask);
我找到了一个更优雅的解决方案here(使用setTo):
cv::Mat c0 = (cx - 0.5f) * 2.0f;
c0.setTo(0, cx <= 0.5f);
单线解决方案:
表达式((cx - 0.5f) * 2.0f)的类型是cv::MatExpr,我们可以将其转换为cv::Mat:
cv::Mat c0 = ((cv::Mat)((cx - 0.5f) * 2.0f)).setTo(0, cx <= 0.5f);