算法:如何使用矩形突出显示图像差异?

时间:2016-08-10 10:11:04

标签: algorithm image-compression

我需要比较两个图像并创建差异的矩形。我可以建立一个像这样的差异矩阵:

0  0  0  0  0  0  0  0 
0  0  0  0  0  1  1  1 
0  0  0  1  0  0  0  0 
0  0  0  0  0  0  0  0 
0  0  0  0  1  0  0  0 
0  0  0  0  0  1  0  0 
0  0  0  0  1  1  1  0 
0  0  0  0  1  1  0  0

其中1是差异像素。我需要找到为图像差异区域创建矩形的方法。在我的例子中,我有三个方面需要强调。

# # #
# 1 #
# # #

#  #  #  # 
#  1  1  1 
#  #  #  #

#  #  #  #  #
#  1  0  0  # 
#  0  1  0  # 
#  1  1  1  # 
#  1  1  0  #

所以我正在寻找一种方便的方法来做到这一点。

3 个答案:

答案 0 :(得分:2)

我假设问题如下。给定0/1矩阵,用不相交的矩形覆盖包含1的区域(即矩形必须不相交)。特别是,不允许使用非矩形形状---例如L形多米诺骨牌。

这是一个算法的想法:

  • 从索引(0,0)处的原点开始,然后展开,直到展开的区域包含1个单个矩形,您无法通过移动到任意方向的相邻单元格来放大。
  • 将该矩形添加到集合中,然后删除已处理的区域;
  • 递归剩余的细胞。

运行时间应与细胞数呈线性关系;但是,根据输出类型是否有其他规格,您可能需要更改第一步。

我非常喜欢这个问题。请注意,问题实例可能存在许多不同的解决方案。一种自然的变化是要求一个由尽可能少的矩形组成的封面(即最小的封面);在这种情况下,也可能存在许多不同的解决方案。 (从复杂性理论的角度来看,问题的计数版看起来很有趣。)

答案 1 :(得分:1)

下面是一些用于查找矩形的JS演示代码,每次在下一个剩余的非空单元格中开始,并以递归方式探索所有路径。细胞在被访问时被清除。

这非常接近'填充'工具正在MS Paint等中进行。更准确地说,这是flood fill algorithm,正如j-random-hacker在评论中所提到的那样。

此代码将找到矩形的内部边界。如果你想要外边界,它需要稍微更新。



var W = 8, H = 8;
var matrix = [
//  0  1  2  3  4  5  6  7
  [ 0, 0, 0, 0, 0, 0, 0, 0 ], // 0
  [ 0, 0, 0, 0, 0, 1, 1, 1 ], // 1
  [ 0, 0, 0, 1, 0, 0, 0, 0 ], // 2
  [ 0, 0, 0, 0, 0, 0, 0, 0 ], // 3
  [ 0, 0, 0, 0, 1, 0, 0, 0 ], // 4
  [ 0, 0, 0, 0, 0, 1, 0, 0 ], // 5
  [ 0, 0, 0, 0, 1, 1, 1, 0 ], // 6
  [ 0, 0, 0, 0, 1, 1, 0, 0 ]  // 7
];
var dir = [
  [ -1, -1 ], [ 0, -1 ], [ 1, -1 ], [ 1, 0 ], [ 1, 1 ], [ 0, 1 ], [ -1, 1 ], [ -1, 0 ]
];

var x, y, rect;

for(y = 0; y < H; y++) {
  for(x = 0; x < W; x++) {
    if(diffAt(x, y)) {
      rect = { x0:x, y0:y, x1:x, y1:y };
      recurse(x, y, rect);
      console.log(
        'Found rectangle: ' +
        '(' + rect.x0 + ',' + rect.y0 + ') -> ' +
        '(' + rect.x1 + ',' + rect.y1 + ')'
      );
    }
  }
}

function recurse(x, y, rect) {
  rect.x0 = Math.min(rect.x0, x);
  rect.y0 = Math.min(rect.y0, y);
  rect.x1 = Math.max(rect.x1, x);
  rect.y1 = Math.max(rect.y1, y);
  matrix[y][x] = 0;

  for(var d = 0; d < 8; d++) {
    if(diffAt(x + dir[d][0], y + dir[d][1])) {
      recurse(x + dir[d][0], y + dir[d][1], rect);
    }
  }
}

function diffAt(x, y) {
  return x < 0 || x >= W || y < 0 || y >= H ? 0 : matrix[y][x];
}
&#13;
&#13;
&#13;

答案 2 :(得分:1)

您可以执行两步算法:首先,在图像中找到8-connected components,然后计算每个组件的边界框。

这种方法可能导致重叠的矩形(想象两个附近的“L”形),您可以通过合并重叠的矩形或将每个矩形中的非连通分量清零来解决(这样您就可以将所有矩形并适当地重建差异图像。

如果选择第二个选项,可以按如下方式在Matlab中获取矩形:

%# each element of the struct array rectangles contains a field
%# .Image, which is the rectangle, and 
%# .BoundingBox, which is the coordinates of the rectangle.    
rectangles = regionprops(differenceImage,'Image','BoundingBox');