2017-03-02 56 views
0

我正在试图找到衣服中的主色。OpenCV:如何忽略来自颜色集群的背景像素

1)第一步是删除背景。我使用解决方案here做了这个。它完美地工作,并使背景变黑。

2)现在有了第一步我想找到的结果,利用该解决方案主要颜色提到here。但我得到black(背景)作为主要颜色之一。

如何忽略步骤2中的背景像素?

+0

如果您认为他们有帮助,请考虑接受最佳答案。 – m3h0w

回答

0

删除背景。这给你一个二进制图像 - 前景和背景像素。现在做一个形态学关闭来关闭前景图像中的小孔并且通常清理轮廓。最后再次替换像素以获得彩色前景图像。

+0

这并没有回答这个问题 - 他们已经获得了前景图像,他们想知道如何在聚类时忽略背景。 – ELRG

1

做一个简单的方法就是简单地将黑色作为主色去除。再抓一个比你想要的更多的群,忽略黑色。如果黑色可能是真正的主色,请用不同的背景颜色重复该操作并丢弃该颜色;比较结果。这会很慢,但很简单。

或者,您只能从前景中的像素进行采样。从你的前景提取方法,你应该有一个二进制黑白前景/背景的面具。如果您只从遮罩的白色区域进行取样,则只应考虑这些颜色。

我有一个粗略的C++实现这个,但它几乎肯定不是最有效的可能。也许这是你可以从事的开始?

Mat src; //Your source image 
Mat mask; //Your black & white foreground/background image 
Mat samples(src.rows * src.cols, 3, CV_32F); 
//Set up samples with only foreground pixels 
for (int y = 0; y < src.rows; y++) { 
    for (int x = 0; x < src.cols; x++) { 
     if (mask.at<uchar>(y, x) == 255) { 
      for (int z = 0; z < 3; z++) { 
       samples.at<float>(y + x*src.rows, z) = src.at<Vec3b>(y, x)[z]; 
      } 
     } 
    } 
} 
int clusterNo = 3; 
int attempts = 5; 
Mat labels; 
Mat centers; 
kmeans(samples, clusterNo, labels, TermCriteria(), attempts, KMEANS_RANDOM_CENTERS, centers); 

你的主色会存储在中心的行中,你可以在那里做你想要的东西。

2

根据不同的情况下,你可以发现你感兴趣的区域的边界矩形,如果颜色的像素数量比矩形边框内的黑色像素的数量要高得多,黑色不宜检测为主色。

面罩的二进制图像呼叫findContours(binaryMask)。确保你找到了你正在寻找的轮廓。如果没有,过滤它们以获得最好的应用程序。然后在轮廓上调用boundingRect(cnt)。然后使用该矩形裁剪图像并运行你的功能。如果不够,请尝试minAreaRect(cnt),但裁剪有点棘手:see this answer

如果这不起作用,我可能会选择“愚蠢”的解决方案,将面具的颜色更改为99%的颜色,不会出现在连衣裙上,然后 - 知道确切的RGB值 - 从结果中筛选出来。

下一次请记得提供一个你的案例的图像,所以答案可能会更准确。

相关问题