【问题标题】:Get data ready(one sample per row) for clustering using k-means?准备好数据(每行一个样本)以使用 k-means 进行聚类?
【发布时间】:2012-11-05 12:43:48
【问题描述】:

我正在尝试使用 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保存keypoints用空格隔开,yml用逗号隔开keypoints。

%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 个关键点需要聚类的图像。我想将所有这些文件附加到一个巨大的文件中并将其聚集在一起。

谢谢

【问题讨论】:

    标签: opencv cluster-analysis k-means sift


    【解决方案1】:

    筛选点的数量因图像而异,因此也没有固定长度的向量可以投影。此外,您连接它们以创建 1 个大向量的顺序意味着顺序很重要。 SIFT 特征是集合点(不是向量)

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

    【讨论】:

    • 我从您的回答中了解到,每张图像都有不同数量的检测到的关键点,关键点的顺序很重要,不能将其连接成一个大向量。我不为此烦恼。我只想将每个图像的关键点向量保存在一行中,并将第二个图像的关键点保存在下一行中;因为这是 kmeans 所需的格式。
    • SIFT 特征是一组点而不是向量是什么意思?
    • 我从没这么说过。如果我这样做了,那一定是一个错字。因为我知道 SIFT 关键点存储在向量中
    • 我现在明白了,我对他在说什么感到困惑
    【解决方案2】:

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

    因此,对于图像聚类,常规 SIFT 功能不会很好地工作。它们适用于全景构建等,您希望在多张图像中找到相同的关键点。

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

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

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

    他们对所有图像的所有单个关键点运行k-means,以获得1000个“共同”关键点,称为视觉词 .然后他们将每个关键点翻译成最匹配的视觉词,从而获得图像的类似文本的表示。除了关键点没有人类可读的名称之外,您可以想象将图像表示为类似于“天空天空天空天空毛皮毛皮森林天空毛皮天空毛皮水森林水水水森林”的图像,其中有一只海狸游泳一个湖。

    在这些 词袋 表示上,您可以再次运行聚类或相似性搜索。 K-means 不能很好地工作,因为向量是稀疏的。欧几里得距离不适用于稀疏数据,不幸的是,k-means 是为欧几里得距离设计的。另外,手段不再稀疏,这使它们变得异常。最有可能的是,得到的均值彼此之间比与实例更相似,从而使整个分区变得荒谬。

    【讨论】:

    • 感谢您的详细回复。我一定会考虑你的建议。
    【解决方案3】:

    SIFT 特征是一回事,每个特征的值构成向量。当您从 SIFT 关键点提取 SIFT 描述符时,您正在提取 4x4 区域中 8 个可能方向的梯度幅度。因此,对于每个关键点,您都有一个具有 128 个特征的向量,或者如果需要,还有 128 个维度。这与表示欧几里得空间中的一个点相同,但不是三个维度,而是 128。常规 SIFT 描述符的一个变体表现更好。密集筛选。它不是从高斯差中计算关键点,而是在图像顶部放置一个矩形网格来提取描述符。在谷歌中寻找 vl_feat。

    【讨论】:

      猜你喜欢
      • 2015-06-22
      • 2016-07-28
      • 2015-01-16
      • 2012-03-24
      • 2017-11-01
      • 2018-08-10
      • 2018-06-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多