我正在使用c ++但是python中的答案也很好。
我需要将已知的BGR颜色转换为HSV才能使用cv :: inRange方法,该方法允许您提取图像的某个部分。我已经有了能够很好地估算出我需要的BGR颜色的代码,所以我想我应该可以猜测它的范围。
所以我对这个链接进行了评价:Convert a single color with cvtColor这似乎可以用于将BGR转换为HSV,但我仍然会得到一些奇怪的输出,我稍后会解释。
无论如何,这是我的代码:
//store BGR values and convert BGR to HSV
cv::Mat3f hairColor(cv::Vec3f(averageBlue, averageGreen, averageRed));
cv::Mat3f finalHSV;
cv::cvtColor(hairColor, finalHSV, CV_BGR2HSV);
//change values to be valid with the cv::inRange function (find this part odd)
finalHSV.ptr<float>(0)[0] /= 2;
finalHSV.ptr<float>(0)[1] *= 255;
//store hsv values as integers
int averageHue = finalHSV.ptr<float>(0)[0];
int averageSat = finalHSV.ptr<float>(0)[1];
int averageValue = finalHSV.ptr<float>(0)[2];
//try to appromimate ranges. I'm trying to mess wtih these values but can't calibrate it whatsoever
int hueMin = averageHue - 20; int hueMax = averageHue + 100;
int saturationMin = averageSat - 20; int saturationMax = averageSat + 20;
int valueMin = averageValue - 50; int valueMax = averageValue + 50;
//bw is the output array for my mask.
cv::inRange(hsv, cv::Scalar(hueMin, saturationMin, valueMin), cv::Scalar(hueMax, saturationMax, valueMax), bw);
所以这是一个简单的例子:我的代码确定了我想要的近似BGR颜色值[126,105,98]。最初转换为HSV给出了[225,0.22,126]这似乎与opencv如何存储hsv(如我认为的色调是0-179)一样奇怪,所以我做了2次转换得到[112,56,126]我认为应该是正确的吗?
无论如何,当我尝试修改我的inRange函数中的值时,我无法真正得到任何好的提取,我倾向于只是得到一个黑屏(我测试我的掩码工作,它确实问题应该在代码提供)。
有没有更好的方法来完成这项任务?
答案 0 :(得分:0)
您的第二次转换是正确的(如果您截断为int
而不是舍入)。
您可以随时对OpenCV docs for cvtColor中给出的值进行实际计算。
这是用Python编写的确切公式链接。对不起,它不是C ++,但是我尽可能地写了它,所以对于任何其他语言的人来说都是可以接受的:
b, g, r = 126, 105, 98
b = b/255
g = g/255
r = r/255
v = max([b, g, r])
if v is 0:
s = 0
else:
s = (v-min([b, g, r]))/v
if v is r:
h = 60*(g-b)/(v-min([b,g,r]))
elif v is g:
h = 120 + 60*(b-r)/(v-min([b,g,r]))
elif v is b:
h = 240 + 60*(r-g)/(v-min([b,g,r]))
if h < 0:
h = h + 360
v = np.round(255*v).astype(int)
s = np.round(255*s).astype(int)
h = np.round(h/2).astype(int)
print(h,s,v)
113 57 126
您可以使用几种不同的方法来获得色彩过滤的良好自动值。我喜欢的一种方法是选择一个你想要的颜色区域,找到这些颜色值的标准偏差和平均值。这样,您可以轻松地将inRange()
函数的下限和上限分别设置为mean-stddev
和mean+stddev
。或者你可以减少限制并将你的标准偏差乘以某个标量,你可以选择更多或更少挑选的方向。例如,lowerb = mean - 3*stddev
和upperb = mean + 1.5*stddev
。
当您说有多个ROI且中间有您关心的对象时,这可能非常有用。您可以使用边框像素的平均值和标准偏差分别过滤掉每个ROI边框中的颜色!