比较数据库中的图像

时间:2012-05-28 14:06:07

标签: java database image

我从图像中获取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)|

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

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

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

如果需要,我在NetBeans上使用Java,使用MySQL。

3 个答案:

答案 0 :(得分:0)

哈希最有可能无效,因为您正在搜索类似的,不相同的图像。即使您将相似的图像映射到相同的密钥,它也不会起作用,因为“相似”的关系不会根据您对比较函数的定义传递(类似于B,B类似于C,但C可能与A不相似) )。

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

答案 1 :(得分:0)

您可以使用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 :(得分:0)

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

  1. 根据逻辑减少列数。
  2. 使用感知哈希(哈希值,其中关闭哈希值表示关闭的前哈希值)
  3. 然而,在一个丑陋而混乱的实现之后,代码运行得很好。我正在做的只是使用SQL查询在问题中进行计算,并从数据库中获取最相似的50张图片。在我得到结果后,我稍微整理了一下代码,它工作得很好而且速度很快。

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

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