【问题标题】:Algorithm fast compare images \ matrix算法快速比较图像\矩阵
【发布时间】:2011-09-10 12:07:41
【问题描述】:

有一个尺寸为 10x10 像素的图像 (imA) 和更多 60 000 个尺寸为 10x10 的图像 (imN)

所有图片都是黑白的

找到将第一张图片 (imA) 与所有其他图片 (imN) 区分开来的最小点数的任务 - 抱歉我的英语不好,我添加了 img 和评论

我做的第一件事,就是用 numpy 把所有的图片都变成了一个矩阵

q=0
for file in inputImages:
    eachImage = os.path.join(generatorFolder, file)
    a[q]=numpy.asarray(Image.open(eachImage))
    q+=1

b=numpy.asarray(Image.open(templateimage))

b[y,x,color] 为其列表 [255,255,255] 着色

a[1-60000,y,x,颜色]

接下来我使用嵌套比较,深度为 3 点的非递归搜索看起来像这样:

for y1 in range(b.shape[0]):
    for x1 in range(b.shape[1]):
        for y2 in range(b.shape[0]):
            for x2 in range(b.shape[1]):
                for y3 in range(b.shape[0]):
                    for x3 in range(b.shape[1]):
                        if y1==y2==y3 and x1==x2==x3:continue

                        check=0
                        for a_el in range(a.shape[0]):
                            if numpy.array_equal(b[y1,x1],a[a_el,y1,x1]) and \
                               numpy.array_equal(b[y2,x2],a[a_el,y2,x2]) and \
                               numpy.array_equal(b[y3,x3],a[a_el,y3,x3]):
                                check=1
                                break

                        if not check:return 'its unic dots'

这段代码的问题是它非常慢。例如,我们的第一张图片与其他所有图片至少有五点不同:

得到 100! / 95! * 60 000 次比较 - 542,070,144,000,000

没错,我使用了一个稍微不同的算法,它可以让你把它变成: 40!/35!*60000 = 4.737.657.600.000 这不算太少。

有没有办法更漂亮地解决我的问题,而不是蛮力。

更新添加 img

0 行:3 个其他图像 (imN) 4x4

1 行:0 模板图像 (imA) 和 1-3 红色标记处的图像差异 (imA XOR imN)

2 line: 0 图中蓝色标出两点两点供比较,

    1 image green its difference, red its compare - difference yes - NEXT

    2 image red its compare - difference NO - Break (these two points is not enough to say that imA differs from imN(2))

3 行:与第 2 行一样,其他点

4 行:我们选择了两个点就足以说明 imA 与 imN(1-3) 不同

【问题讨论】:

  • 第二行图像:一些在imA中但不在imB中的像素被标记,而另一些则没有被标记。为什么?
  • 据我所知,这两个像素不足以区分 imA 和 im1 或 im2。这将是 (0,1) 和 (2,1),这三个组合中的任何一个都没有设置。

标签: python algorithm image


【解决方案1】:

如果我正确理解您的问题,您需要计算第一张图片上的点数,这与 所有 其他图片不同,而不管其他图片彼此之间有何不同?

如果是这种情况,除非我遗漏了什么,否则你能不能简单地执行以下操作:

boolean[10][10] DIFFS // all values set to TRUE
int[10][10] ORIGINAL  // store first pictures color values

foreach IMAGE in [IMAGES - FIRST IMAGE] {
    int[10][10] CURRENT <- IMAGE // store the current image's color values
    for (i : 0 -> 9) {
        for (j : 0 -> 9) {
            if (DIFFS[i][j]) {
                DIFFS[i][j] = ORIGINAL[i][j] != CURRENT[i][j]
            }
        }
    }
}

然后你会得到一个二维矩阵DIFFS,其中每个位置表示原始图像中的相应像素是否与所有其他图片不同。

【讨论】:

  • 如果我理解语法。然后,您的方法给出了第一张图像独有的点矩阵。但就我而言,没有。我添加了图片和评论。
【解决方案2】:

我的做法是:

  1. 将图像读入 60,000 x 100 数组,设置为 1 和 0。
  2. 按每个像素对它们求和,以计算每个像素“设置”为 1 英寸的图像数量
  3. 在参考图像中选择总和最小的像素。 (如果总和为 0,则只需该像素即可区分参考图像和所有其他像素)
  4. 现在只查看设置了该位的图像,重新计算总和并再次选择最低的。
  5. 反复重复,直到选择参考图像中的所有设置位(这意味着无法区分它或需要所有位)或直到总和等于 1,这意味着只有一个图像具有该位已设置。

在代码中,对于 1000 个 4x4 图像:

import numpy

def least_freq_set_pixel(array, must_have):
    # If it is specified that a certain pixels must be set, remove rows that don't have those pixels set
    if must_have != []:
        for i in must_have:
            array = numpy.delete(array, numpy.where(array[:,i] == 0), axis = 0)

    # Calculate the sum for each pixel
    set_in_n = numpy.sum(array, axis = 0)
    my_index = numpy.argmin(set_in_n)

    # Return the pixel number which is set in the fewest images
    return my_index, set_in_n[my_index]


# Create some test data 4x4 images
numpy.random.seed(11)
a = numpy.array([0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0])
b = numpy.random.randint(0,2,(1000,16))


must_have = []
stop = 0
while stop == 0:
    i,j = least_freq_set_pixel(b, must_have)
    print i,j
    # If the pixel is set in more than one image and not all pixels have been selected yet... find the next pixel
    if j > 1 and len(must_have) <= 16:
        must_have.append(i)
    else:
        stop = 1
        print must_have

这告诉我们,我们需要 16 个像素中的 7 个像素来将参考图像与其余像素分开,即 0、1、2、4、5、10 和 15 像素。

【讨论】:

  • 我复制了您的代码并添加了检查。 [link]codepaste.ru/7617如果我理解正确,那你的版本不行?
  • 确实不太好用。当总和为 0 时,条件检查会出现问题,这更可能发生在小测试集上。我没有时间修复它,但它说明了方法。
【解决方案3】:

10x10 = 100。两张图像之间的 100 次比较。你有 60000 张图片。我认为该算法必须是 O(100 * 60000) = O(6000000)。我不懂python,但是伪算法应该是这样的:

int minDistinguishPoints = 100; 
int currentPointsDiff;
Image imA;

foreach (Image myImg in ImageItems)
{
    currentPointsDiff = 0;
    for (int i=0; i<10; i++)
       for (int j=0; j<10; j++)
       {
           if (!imA.GetPixel(i,j).Equals(myImg.GetPixel(i,j)))
           {
               currentPointsDiff++;
           }                
       }
    if (minDistinguishPoints > currentPointsDiff)
    {
        minDistinguishPoints = currentPointsDiff;
    }
}

可能是我不明白的问题。如果是这样,请解释得更详细一些。

【讨论】:

  • 我加了一张图片和cmets,来解释一下。
  • @stukselbax: O(6000000) 很傻,因为它等于O(1)。你需要参数化输入,比如n(图像数量)、w(图像宽度)和h(图像高度)。复杂度是O(n * w * h)。像这样我们可以比较算法。
【解决方案4】:

如果我理解正确,我们可以完全重新定义您的问题。我认为您想要实现的目标是:快速识别某个给定图像是否等于预定义的 60000 个图像中的一个或都不等于这些图像。每张图片都是 10x10 黑白。

所以每个图像都可以解释为 10x10=100 位数组,并且您有 60000 个预先给定的,您想要与之进行比较。

您为什么不将 60000 张图像转换为 100 位整数,然后对它们进行排序。然后,您可以非常有效地比较任何 100 位整数并找出命中或未命中。

编辑:如果我正确理解评论,图像会大得多。只要已知的数量仍然是可管理的(60k 是,并且可能也是 600k),您就可以为这些图像生成哈希并对它们进行排序和比较。您有一些前期计算成本,但您只有一次。

【讨论】:

  • 实际上比我描述的要复杂得多。 imA 不是几百个中的一个。图像序列为 imN 100k * 100k imN。我找到了加速以下操作的最小点数。根据我的计算,它会给我大约 20 倍的加速度
  • imA 不需要几百,它可能是任何可能的。但是大到 100kx100k 的图像与您描述的完全不同。在上面抛出一个哈希算法。
猜你喜欢
  • 2010-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-31
相关资源
最近更新 更多