为什么积分图像包含额外的行和列零?

时间:2015-05-12 15:32:18

标签: matlab opencv image-processing javacv gaussian

我正在学习如何使用opencv和Java API来使用积分图像,我创建了一个测试,在使用积分图像之前和使用之后显示灰度图像。灰度图像是10 x 10,当我将其转换为积分图像时 我发现11 x 11有额外的零行和额外的零列,如下面的输出所示。

请让我知道为什么积分图像包含额外的零行和列?

代码

    public static void main(String[] args) {
    MatFactory matFactory = new MatFactory();
    FilePathUtils.addInputPath(path_Obj);
    Mat bgrMat = matFactory.newMat(FilePathUtils.getInputFileFullPathList().get(0));
    Mat gsImg = SysUtils.rgbToGrayScaleMat(bgrMat);

    Log.D(TAG, "MainClas", "gsImg.dump(): " + gsImg.dump());
    Mat integralMat = new Mat();
    Imgproc.integral(gsImg, integralMat, CvType.CV_32F);

    Log.D(TAG, "MainClas", "sumMat.dump(): " + integralMat.dump());
}

输出

    1: Debug: MainClass -> MainClas: gsImg.dump(): [2, 1, 7, 5, 1, 11, 2, 7, 9, 11;
        1, 2, 0, 0, 3, 20, 17, 5, 7, 8;
        4, 8, 0, 2, 6, 30, 31, 5, 2, 2;
        39, 43, 47, 44, 38, 62, 60, 37, 37, 39;
        27, 29, 52, 52, 47, 75, 67, 59, 58, 63;
        25, 21, 49, 51, 51, 78, 64, 66, 76, 80;
        40, 36, 50, 46, 41, 56, 42, 45, 47, 49;
        13, 17, 20, 15, 9, 20, 15, 19, 12, 11;
        17, 13, 8, 5, 4, 7, 13, 20, 17, 17;
        2, 4, 7, 9, 8, 6, 6, 7, 7, 8]
    2: Debug: MainClass -> MainClas: sumMat.dump(): [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
        0, 2, 3, 10, 15, 16, 27, 29, 36, 45, 56;
        0, 3, 6, 13, 18, 22, 53, 72, 84, 100, 119;
        0, 7, 18, 25, 32, 42, 103, 153, 170, 188, 209;
        0, 46, 100, 154, 205, 253, 376, 486, 540, 595, 655;
        0, 73, 156, 262, 365, 460, 658, 835, 948, 1061, 1184;
        0, 98, 202, 357, 511, 657, 933, 1174, 1353, 1542, 1745;
        0, 138, 278, 483, 683, 870, 1202, 1485, 1709, 1945, 2197;
        0, 151, 308, 533, 748, 944, 1296, 1594, 1837, 2085, 2348;
        0, 168, 338, 571, 791, 991, 1350, 1661, 1924, 2189, 2469;
        0, 170, 344, 584, 813, 1021, 1386, 1703, 1973, 2245, 2533]

2 个答案:

答案 0 :(得分:4)

这是预期的行为。请注意,OpenCV中的整合图像sum(X,Y)被定义为(see documentation here)原始图像中像素的总和,其索引为LESS THAN,sum_(x < X, y < Y),不小于或等于积分图像。因此,例如sum(0,0)将是零像素的总和,定义为0.这也是生成的和图像比原始图像多一行和多列的原因。

这样做的原因是它可以更容易地计算图像块上的总和等,并在它们包括顶部和/或左边界时以统一的方式处理它们。

答案 1 :(得分:2)

有两个原因。

第一个是纯数学的。假设您有一行3个数字(像素)。它产生多少可能的累积总和?答案是4.你可以得到0个第一个像素,1个像素,2个像素或所有3个像素的总和。不同总和的数量是4:(0,1,2,3)。 4恰好是3 + 1。等效的宽度为10的图像将为每行产生11个总和,而10x10的大小将产生11x11的总和。

第二个原因是编程简单。积分图像用于计算图像中任何可能的矩形的总和,仅有4个动作(2个角的总和减去其他2个角)。角之间的距离恰好等于您想要求和的矩形的大小。例如,如果矩形的宽度为5像素,则可以访问索引im[i][j]im[i][j+5]处的积分图像。但是,如果您的矩形覆盖整个图像的宽度或高度,这可能会产生一个落在数组之外的索引。这就是为什么积分图像的存储大小比图像大1x1

注意:可以将整数图像存储在与图像大小相同的数组中。但是对数组的访问速度要慢得多,因为需要测试索引是否超出范围。必须检测在索引[-1]处访问积分图像并产生0的和,并且在索引&gt;处访问。 width将自动返回整个宽度的总和。

OpenCV 主要由于速度原因实现了较大的积分图像。矩形之和的计算仅需要4 +或 - 操作和4指针参考。只要请求的矩形在图像中具有合法坐标

,就不需要测试指针落在图像内部

有一些架构允许访问数组越界(非法索引)。例如GPU着色器。在这些架构上,积分图像可以以不同的方式实现(NxN的大小,而不是N + 1xN + 1,甚至是金字塔的总和)

您可以手动从openCV中的整体图像中删除多余的列吗?

我强烈建议不要这样做! openCV具有内置代码,可以以特定方式访问整合图像。如果删除第一列,可能会导致不可预测的计算。

此外 - 正如我所解释的那样,这个额外的行和列将运行时间增加了x10倍(因为加速和减法由CPU执行得比if()条件快得多)

请注意,积分图像是原始图像的完全不同的表示。它不仅具有不同的尺寸(N + 1)x(N + 1),而且具有不同的深度。您的原始图像可以是灰度(每像素存储一个字节),而积分图像通常需要每像素4个字节(因为许多像素的总和需要更大的数字)。因此,无论如何积分图像将比原始图像多大约4倍的内存。由于不同的BPP(每像素位数),您无法在原始图像中显示积分图像,因此为什么会受到不同宽度和高度的困扰