计划
我的项目能够捕获目标窗口的位图并将其转换为IplImage,然后在cvNamedWindow中显示该图像,进行进一步处理.
为了测试,我将图像加载到MSPaint中,如下所示:
然后允许用户点击并将鼠标拖动到图像内的任何数量的像素上以创建向量< cv :: Scalar_< BYTE>>包含这些RGB颜色值.
然后,在ColorRGBToHLS()的帮助下,然后通过hue从左到右对此数组进行排序,如下所示:
// PixelColor is just a cv::Scalar_
bool comparePixelColors( PixelColor& pc1, PixelColor& pc2 ) {
WORD h1 = 0, h2 = 0;
WORD s1 = 0, s2 = 0;
WORD l1 = 0, l2 = 0;
ColorRGBToHLS(RGB(pc1.val[2], pc1.val[1], pc1.val[0]), &h1, &l1, &s1);
ColorRGBToHLS(RGB(pc2.val[2], pc2.val[1], pc2.val[0]), &h2, &l2, &s2);
return ( h1 < h2 );
}
//..(elsewhere in code)
std::sort(m_colorRange.begin(), m_colorRange.end(), comparePixelColors);
…然后在新的cvNamedWindow中显示,它看起来像:
问题
现在,这里的想法是创建一个二进制阈值图像(或“掩码”),其中所选颜色范围变为白色,源图像的其余部分变为黑色…类似于“按颜色选择”工具的方式在GIMP中运行,或者“魔术棒”工具在Photoshop中运行…除了不限于特定的轮廓选择,我们实际上是在整个图像上运行.
我已经阅读了cvInRangeS,听起来这正是我所需要的.
然而,无论出于何种原因,阈值图像总是最终变成黑色……
VOID ShowThreshedImage(const IplImage* src, const PixelColor& min, const PixelColor& max)
{
IplImage* imgHSV = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 3);
cvCvtColor(src, imgHSV, CV_RGB2HLS);
cvNamedWindow("T1");
cvShowImage("T1", imgHSV); //
IplImage* imgThreshed = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
cvInRangeS(imgHSV, min, max, imgThreshed);
cvNamedWindow("T2");
cvShowImage("T2", imgThreshed); //
}
这就是“T1”窗口看起来像(我认为是正确的?):
请记住,因为颜色范围向量存储为RGB(并且OpenCV内部将此顺序反转为BGR),我已将最小值/最大值转换为HLS,然后将它们传递给ShowThreshedImage(),如下所示:
CvScalar rgbPixelToHSV(const PixelColor& pixelColor)
{
WORD h = 0, s = 0, l = 0;
ColorRGBToHLS(RGB(pixelColor.val[2], pixelColor.val[1], pixelColor.val[0]), &h, &l, &s);
return PixelColor(h, s, l);
}
//...(elsewhere in code)
if(m_colorRange.size() > 0)
m_minHSV = rgbPixelToHSV(m_colorRange[0]);
if(m_colorRange.size() > 1)
m_maxHSV = rgbPixelToHSV(m_colorRange[m_colorRange.size() - 1]);
ShowThreshedImage(m_imgSrc, m_minHSV, m_maxHSV);
…但即使没有这种转换,只是简单地传递RGB值,结果仍然是一个完全黑色的图像.我甚至尝试手动插入某些最小/最大值,我得到的最好结果是几个像素(尽管是不正确的).
问题:
我在这做错了什么?
有什么东西我不了解cvInRangeS方法?
我是否需要逐步浏览每种颜色,以便正确地将所选范围限制在源图像之外?
有没有其他方法来实现这一目标?
感谢您的时间.
更新:
我发现cvInRangeS期望min的所有值都低于max的值.但是,当选择一系列颜色时,似乎不能保证会出现这种情况,通常会导致黑色阈值图像.
并且交换值以强制执行此规则可能会在新范围内导致不需要的颜色(在某些情况下,这可能包括所有颜色而不仅仅是所需的颜色).
所以我想这里真正的问题是:
“你如何分割RGB颜色数组,并使用它们来阈值图像?”