在网站colorizer.org上,他们的HSV范围为H = 0-360,S = 0-100,V = 0-100。我们也知道OpenCV中的HSV范围是H = 0-180,S = 0-255,V = 0-255。
我想为任何阴影(我们认为的)蓝色选择一个范围,所以我看了colorizer.org,看到蓝色Hue的范围大致从170到270.所以我将这个Hue范围缩放到OpenCV除以2,得到85-135。
现在,我从网站预览中获取了以下彩色[H=216, S=96, V=67]
的屏幕截图
然后我在手机上运行应用程序并从笔记本电脑屏幕捕获以下相机框架。 据我所知,HSV频道的值会在某种程度上与网站上的不同,因为当我拍摄相机框架时,房间里还有其他条件,如额外的光线(HSV中的V),等等。
然后我将此Mat
转换为Imgproc.cvtColor(rgbaFrame, hsvImage, Imgproc.COLOR_RGB2HSV_FULL);
的HSV颜色空间,从而产生了以下图像。
然后我调用了inRange
函数:
Core.inRange(hsvImage, new Scalar(85, 50, 40), new Scalar(135, 255, 255), maskedImage);
导致以下maskedImage。
问题是,当我为蓝色包含所有可能的色相范围时,为什么不检测蓝色?
重要事项:除第一张原始图片外,所有图片均使用Highgui.imwrite
函数存储在SD卡中,以便我可以将它们移动到我的计算机上,以便在Stackoverflow上传。您必须注意到第一张原始屏幕截图中的蓝色在第二张图像中转换为红色。原因是由相机捕获的帧(即由移动电话相机捕获的第一屏幕截图的照片/帧)是RGBA图像。但OpenCV默认情况下会将所有图像转换为BRG,因为它会将它们保存到某些内容的SD卡中。所以请确保原始图像是RGBA,并且它仅在OpenCV内部转换为BGR以保存到SD卡中。这就是为什么红色显得很蓝。
答案 0 :(得分:2)
使用此代码对我有用(C ++):
cv::Mat input = cv::imread("../inputData/HSV_RGB.jpg");
//assuming your image to be in RGB format after loading:
cv::Mat hsv;
cv::cvtColor(input,hsv,CV_RGB2HSV);
// hue range:
cv::Mat mask;
inRange(hsv, cv::Scalar(85, 50, 40), cv::Scalar(135, 255, 255), mask);
cv::imshow("blue mask", mask);
我使用了这个输入图像(以BGR格式保存和加载,虽然它实际上是RGB图像,这就是为什么我们必须使用RGB2HSV而不是BGR2HSV):
导致这个面具:
与您的代码的不同之处在于我使用的是CV_RGB2HSV
而不是CV_RGB2HSV_FULL
。标记CV_RGB2HSV_FULL
使用整个字节来存储色调值,因此范围0 .. 360 degrees
将缩放为0 .. 255
,而不是0 .. 180
CV_RGB2HSV
我可以通过使用这部分代码验证这一点:
// use _FULL flag:
cv::cvtColor(input,hsv,CV_RGB2HSV_FULL);
// but scale the hue values accordingly:
double hueScale = 2.0/1.41176470588;
cv::Mat mask;
// scale hue values:
inRange(hsv, cv::Scalar(hueScale*85, 50, 40), cv::Scalar(hueScale*135, 255, 255), mask);
给出这个结果:
对于想要使用“正确”图像进行测试的任何人:
这是转换为BGR的输入:如果要直接使用它,则必须将转换从RGB2HSV切换到BGR2HSV。但我认为最好还是显示输入的BGR版本......