OpenCV cvtColor CV_BGR2HSV CV_32FC3 饱和度范围

OpenCV cvtColor CV_BGR2HSV CV_32FC3 Saturation Range

我正在尝试在 OpenCV 3.2 中为材料构建直方图,但对 HSV 范围感到困惑——它们似乎与文档不匹配,或者我处理错误。

// cv::Mat bgrPhoto contains a test image

cv::Mat3f hsvPhoto;
bgrPhoto.convertTo(hsvPhoto, CV_32FC3);
cv::cvtColor(hsvPhoto, hsvPhoto, CV_BGR2HSV, CV_32FC3);
std::vector<cv::Mat1f> hsvChannels;
cv::split(hsvPhoto, hsvChannels);

// Documentation [0.0, 1.0]: measured here Hue to 360.0, Sat to 1.0, Val to 255.0
double minHue, maxHue, minSat, maxSat, minVal, maxVal;
cv::minMaxIdx(hsvChannels[0], &minHue, &maxHue, 0, 0);
cv::minMaxIdx(hsvChannels[1], &minSat, &maxSat, 0, 0);
cv::minMaxIdx(hsvChannels[2], &minVal, &maxVal, 0, 0);

当您将图像从 8 位转换为 32 位时,您没有将值从 [0, 255] 缩放到 [0, 1]。 convertTo() 简单地转换类型;默认情况下它不会重新调整值。这会影响您的输出,因为从 docs for color conversion from BGR to HSVV 简单地设置为 max(B, G, R)(这将是最多 255 个数字)。您会注意到在 cvtColor() 的文档中它说对于 8 位和 16 位图像,它们被缩放以适应 [0, 1] 范围;但不适用于浮动图像。但是,H 通道和 S 通道仍会缩放到正确的范围,因为它们使用 V 缩放图像。

当您执行 bgrPhoto.convertTo(hsvPhoto, CV_32FC3) 时,您需要除以 255 以将值设置为 [0, 1]。如果查看 docs for convertTo(),您会注意到可以设置第三个位置参数,这是一个比例因子。正如文档所述,简单地使用 bgrPhoto.convertTo(hsvPhoto, CV_32FC3, 1.0/255.0) 将按该因子缩放每个像素值。

此外,Miki 在对 OP 的评论中的观点完全被我忽略了,但这是一个很好的收获;检查 docs for cvtColor();第四个参数是 目标通道数 的参数,而不是 dtype,所以 cv::cvtColor(hsvPhoto, hsvPhoto, CV_BGR2HSV) 就是你想要的。