【问题标题】:OpenCV cvtColor CV_BGR2HSV CV_32FC3 Saturation RangeOpenCV cvtColor CV_BGR2HSV CV_32FC3 饱和度范围
【发布时间】:2017-10-05 21:25:20
【问题描述】:

我正在尝试为 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);

【问题讨论】:

  • OpenCV 存储来自 [0 - 180] 的 H 通道值、S 和来自 [0 - 255] 的 V 值。对于float,相应地转换值。
  • H 在 [0,360],S,V 在 [0,1]。见the doc。此外,您正在尝试创建具有 21 个(CV_32FC3 评估为 21)目标通道的输出图像。只需使用cv::cvtColor(hsvPhoto, hsvPhoto, CV_BGR2HSV);。还有bgrPhoto.convertTo(hsvPhoto, CV_32F);,因为只需要指定类型而不是深度。

标签: opencv hsv


【解决方案1】:

当您将图像从 8 位转换为 32 位时,您尚未将值从 [0, 255] 缩放到 [0, 1]。 convertTo() 只是转换类型;默认情况下它不会重新调整值。这会影响您的输出,因为从 docs for color conversion from BGR to HSV 开始,V 只是设置为 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)是你想要的。

【讨论】:

  • 不妨提一下,您可以直接在 convertTo 函数中执行此操作:bgrPhoto.convertTo(hsvPhoto, CV_32F, 1.0/255.0);
  • 感谢@Miki,现在链接更多文档。
  • 谢谢亚历山大——出色的回答!
猜你喜欢
  • 2021-08-31
  • 1970-01-01
  • 2014-05-10
  • 2011-05-17
  • 2012-02-23
  • 1970-01-01
  • 1970-01-01
  • 2022-11-30
  • 2017-06-16
相关资源
最近更新 更多