使用k-means为聚类准备数据(每行一个样本)?

时间:2012-11-16 18:45:57

标签: opencv cluster-analysis k-means sift

我正在尝试使用kmeans功能对关键点进行聚类(使用SIFT检测到),但我无法为使用它做好准备。

使用以下代码将关键点保存到xml / yml文件中:

int _tmain(int argc, _TCHAR* argv[])
{
Mat img;

img = imread("c:\\box.png", 0);

SiftFeatureDetector detector;
vector<KeyPoint> keypoints;
detector.detect(img, keypoints);



FileStorage fs("keypoint1.xml", FileStorage::WRITE);
write(fs, "keypoints1", keypoints);
fs.release();

xml保存由空格分隔的关键点,yml使用逗号分隔关键点。

%YAML:1.0
keypoints1: [ 6.1368021965026855e+000, 5.2649226188659668e+000,
    4.0740542411804199e+000, 2.7943280029296875e+002, 0., 9109760, -1,
    6.1368021965026855e+000, 5.2649226188659668e+000,
    4.0740542411804199e+000, 3.4678604125976562e+002, 0., 9109760, -1,
    1.5903041076660156e+002, 2.4698186874389648e+001,
    4.1325736045837402e+000, 9.7977493286132813e+001, 0., 10158336, -1,
    1.6808378601074219e+002, 2.5029441833496094e+001,
    4.2399377822875977e+000, 9.7380126953125000e+001, 0., 11993344, -1,
    1.9952423095703125e+002, 4.4663669586181641e+001,
    5.0049328804016113e+000, 5.7439949035644531e+001, 0., 7275008, -1,
    3.0947158813476563e+002, 4.6865818023681641e+001,......................

kmeans函数要求输入为每个样本一行。有人可以解释一下,我的意思是上面的文件可以用作单行吗?它会使用FileStorage读取方法获得kmeans的资格吗?

我想添加和读取文件的原因是假设我有100个图像的关键点需要聚类。我想将所有这些文件附加到一个巨大的文件和群集中。

谢谢

3 个答案:

答案 0 :(得分:2)

汤姆是对的。通常使用SIFT,您可以使用每个图像多个关键点。这就是关键点检测背后的整个想法,即您尝试在后续步骤中仅处理图像的“有趣”部分。

因此,对于群集图像,常规SIFT功能将无法正常工作。它们适用于全景构建以及您希望在多个图像中找到相同关键点的内容。

但是,您可以“滥用”SIFT关键点;这可能就是你想要重现的东西。如果你阅读相关文章肯定会有所帮助,而不仅仅是从编码的角度试图弄清楚它。

这里可以找到一个简单的介绍:   http://image-net.org/download-features

注意他们如何使用常规网格从每个图像中采样相同数量的关键点。然而,他们仍然没有将它们组合成一个巨大的阵列 - 这对于相似性搜索不起作用。相反,他们会进行一种降维。

他们在所有图像的所有个别关键点上运行k-means,以获得1000个“常用”关键点,称为视觉词 。然后,他们将每个关键点转换为最佳匹配的视觉词,这样就可以获得图像的文本式表示。除了关键点没有人类可读的名称,你可以想象将图像表示为“天空天空天空毛皮毛皮森林天空毛皮天空毛皮水森林水水森林”的图像与海狸游泳的图像湖。

在这些词汇表示中,您可以再次运行群集或相似性搜索。 K-means不能很好地工作,因为向量是稀疏的。欧几里德距离对于稀疏数据不起作用,并且不幸的是,k-means被设计用于欧几里德距离。此外,手段不再稀疏,这使他们变得异常。最有可能的是,由此产生的方法将与实例相比更加相似,从而使整个分区变得荒谬。

答案 1 :(得分:1)

筛选点的数量因图像而异,因此也没有固定长度的矢量。此外,您将它们连接起来创建一个大向量的顺序意味着排序很重要。 SIFT特征是点的(不是向量)

您需要更复杂的指标来定义相似性。欧几里德或其他基于矢量的指标不起作用。 OpenCV的K-means需要向量输入,因此它不起作用。

答案 2 :(得分:0)

SIFT特征是一回事,每个特征的值构建矢量。从SIFT关键点提取SIFT描述符时,您将在4x4区域中以8个可能的方向提取渐变的大小。因此,每个关键点都有一个矢量,具有128个特征,或者如果需要,可以有128个维度。它与表示欧几里得空间中的一个点相同,但不是有三个维度,而是128个。有一个常规SIFT描述符的变体表现更好。密集的SIFT。它不是根据高斯差异来计算关键点,而是在图像顶部放置一个矩形网格来提取描述符。在google中查找vl_feat。