【问题标题】:Compare Images in Database比较数据库中的图像
【发布时间】:2012-07-02 15:55:59
【问题描述】:

我从图像中获取 25 个样本,获取它们的平均 rgb 值并将它们保存在 5x5 颜色数组中。这些是我的“签名”。签名中的值如下:

Color signature[5][5];

-21233 -1 -323211 ... ...
-123 -12323 ...  
...

我可以从签名的索引中获得红色、蓝色和绿色值。我使用这些值来比较两个图像的签名并获得“差异”值。

signature[1][1].getBlue() = 123, Color[1][1].getRed() = 200 ..

for (int x = 0; x < 5; x++) {   
        for (int y = 0;y < 5; y++) {
            int r1 = signature[x][y].getRed();
            int g1 = signature[x][y].getGreen();
            int b1 = signature[x][y].getBlue();
            int r2 = signature2[x][y].getRed();
            int g2 = signature2[x][y].getGreen();
            int b2 = signature2[x][y].getBlue();
            double tempDiff =  Math.sqrt((r1 - r2) * (r1 - r2) 
                                       + (g1 - g2) * (g1 - g2) 
                                       + (b1 - b2) * (b1 - b2));
            difference += tempDiff;
        }
 }

我还获得了图像的第二个签名,显示了边缘发现版本的签名。比较两张图像,我将正常特征差异与边缘特征差异相乘,得到最终的差异值。

在比较两张图片时,一切都很好。但是,我得到了很多图像,所以我将我的签名保存在数据库中,如下所示:

Table images:
-COLUMN name-       -COLUMN signature-             -COLUMN edge signature-
myimg.jpg  |-12312 -132 -2 ... (25 of them) |-123 -1 -1234 -6921 .. (25 of them)|

我只是将签名索引与它们之间的空格连接起来并保存为字符串。

这是我的问题:我需要找到一张图片的相似之处。如果我从数据库中选择所有图像,事情会变得非常缓慢并且我的内存不足。我可以从数据库中选择 1000 张图像,比较并获取下 1000 张,但这甚至更慢。

我需要一种方法来比较查询中的图像签名,我已准备好更改我的表的列,甚至准备尝试具有 100 列包含签名的所有 RGB 值的疯狂表。我需要减少或散列签名。您可以建议任何方法/方法、链接或库吗?任何帮助将不胜感激。

如果需要,我在 NetBeans 上使用 Java,与 MySQL 一起工作。

【问题讨论】:

  • “这是我的问题” 那段中的任何内容,或以下内容,都是一个问题。
  • 根据你的要求添加了一个带问号的句子。

标签: java database image


【解决方案1】:

您可以使用 SQL 来执行此操作。

如果您想查找所有重复项,可以使用类似这样的内容(替换正确的字段名称)

SELECT i.[name] FROM images i 
  INNER JOIN 
     (SELECT signature, edge_signature 
          FROM images
           GROUP BY signature, edge_signature
            HAVING COUNT(*) > 1 ) dups
   on i.signature = dups.signature and i.edge_signature = dups.edge_signature;

如果要查找特定图像的副本,请创建签名并将其放入此 SQL 中

SELECT i.[name]
  FROM images
    WHERE signature = '$yourCalculatedSignaturehere'
    and edge_signature = '$yourCalculatedEdgeSignaturehere';

这两个查询都可能返回多行(如果没有重复,则返回 0 行)。

您也许可以使用signature, edge_signature, [name] 上的索引来加快这些查询的速度 (此索引可能会使您的表使用的磁盘空间增加一倍,但它应该会显着提高查询性能。

【讨论】:

  • 我想找到相似之处,而不是重复。
【解决方案2】:

散列很可能不起作用,因为您正在搜索相似而不是相同的图像。即使您将相似的图像映射到同一个键,它也不会起作用,因为“相似”关系不是基于您对比较函数的定义的传递(A 类似于 B,B 类似于 C,但 C 可能不类似于 A )。

我唯一能想到的就是按照你说的存储在 25 * 3 列中。您可以编写 SQL 语句以仅选择可能通过距离测试的图像(如果差异已经大于阈值,则将其过滤掉)。如果数据库中的图像不太相似,则此方法应该可以正常工作。但是,如果数据库中的图像彼此非常相似,则这种方法很糟糕。

【讨论】:

  • 感谢您的回答。我需要分别比较红色、绿色和蓝色值,所以我需要 25 种颜色 x 3(r,g,b) x 2 (color,edge) = 150 列。这就是我现在正在实施的。顺便说一句,图像彼此并不接近。是否有任何建议不会放弃太多相似性成功并减少我的列数?
  • 对不起。我没有图形处理方面的经验,因此无法帮助您。
  • 该方法运行速度足够快,有 150 列,查询和代码变得非常丑陋,但它成功了。所以没有必要减少列数。再次感谢!
【解决方案3】:

看到我们需要 150 列后,想到了两种方法:

  1. 根据逻辑减少列数。
  2. 使用感知散列(散列,其中接近的散列值表示接近的散列前值)

然而,在一个丑陋而混乱的实现之后,代码运行得很好。我所做的只是使用 SQL 查询在问题中进行计算,并从数据库中获取最相似的 50 张图片。得到结果后,我稍微整理了一下代码,运行良好且快速。

因此,我们认为没有真正需要实施上述方法,因为它们会降低发现相似性的成功率,而且我们不需要更快。我们得到了最好的 50 个结果,因此内存复杂性也不是问题。

对于所有在项目的“Java 部分”(或任何其他“代码”部分)中存在速度或内存问题的人,我强烈建议将尽可能多的工作转移到“数据库部分”并获取内容完成查询。

【讨论】:

    猜你喜欢
    • 2013-02-22
    • 2012-07-14
    • 2013-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多