精华内容
下载资源
问答
  • 积分图像

    2019-11-13 18:16:26
    积分图像 积分图像(integral image):图像中每个像素的值为位于该像素上方和左侧的所有像素值之和(in an integral image, every pixel is the summation of the pixels above and to the left of it)。(参考...

    积分图像

    积分图像(integral image):图像中每个像素的值为位于该像素上方和左侧的所有像素值之和(in an integral image, every pixel is the summation of the pixels above and to the left of it)。(参考Viola-Jones算法[1])

    在这里插入图片描述
    原图像中任意子区域中所有像素之和(summations over image subregions)可通过积分图像中四个像素的线性组合快速计算,其计算时间复杂度为O(1)\mathcal{O} (1),即与子区域大小无关。

    在这里插入图片描述
    例如,所选区域的像素之和为:462220+10=1446 – 22 – 20 + 10 = 14

    
    #!/usr/bin/env python
    # -*- encoding: utf-8 -*-
    """
    @file    :   integral_image.py
    @time    :   2019/11/13 17:42:44
    @author  :   XiaoY
    @version :   1.0
    @contact :   zhaoyin214@qq.com
    @license :   (c)copyright XiaoY
    @desc    :   integral image
    """
    
    __author__ = "XiaoY"
    
    
    # %%
    import numpy as np
    
    
    # %%
    DIM_X = 1
    DIM_Y = 0
    
    # %%
    def integral_image(image):
        """
        integral image
    
        arguments:
            image (2-dim or 3-dim array), rgb or gray scale input image
    
        return:
            integral
        """
    
        integral = np.cumsum(a=image, axis=DIM_X)
        integral = np.cumsum(a=integral, axis=DIM_Y)
    
        return integral
    
    
    # %%
    if __name__ == "__main__":
    
        image = np.random.randn(2, 2, 3)
        integral = integral_image(image)
    
        print("image: \n{}".format(image))
        print("integral: \n{}".format(integral))
    
        image = np.random.randn(5, 5)
        integral = integral_image(image)
    
        print("image: \n{}".format(image))
        print("integral: \n{}".format(integral))
    
    
    
    image:
    [[[ 0.96211598  0.67461992  0.0240872 ]
    [-0.92722726  0.31323452  0.23111007]]
    
    [[ 1.00804243  0.75129953 -0.59352847]
    [ 0.04817242 -1.04234147 -1.2935993 ]]]
    integral:
    [[[ 0.96211598  0.67461992  0.0240872 ]
    [ 0.03488872  0.98785444  0.25519727]]
    
    [[ 1.97015841  1.42591945 -0.56944127]
    [ 1.09110358  0.6968125  -1.6319305 ]]]
    image:
    [[ 1.4895371  -0.69930071 -0.02170534 -0.9398842   1.4064624 ]
    [ 0.49817712 -0.67654781 -0.19518726  0.78819665 -0.03121156]
    [-0.072189   -1.70718612  0.03034845  0.73531173 -0.49907469]
    [-0.02120605  0.55489884  2.23081881 -1.55657404 -0.10094432]
    [ 0.16923765 -1.50586851  1.28346946  0.76119275  0.14296287]]
    integral:
    [[ 1.4895371   0.79023639  0.76853104 -0.17135316  1.23510924]
    [ 1.98771422  0.61186569  0.39497309  0.24328553  1.61853638]
    [ 1.91552521 -1.16750943 -1.35405359 -0.77042941  0.10574674]
    [ 1.89431916 -0.63381664  1.41045801  0.43750814  1.21273997]
    [ 2.06355682 -1.9704475   1.35729661  1.1455395   2.0637342 ]]
    

    参考文献

    [1] Viola, P., and M. J. Jones. “Rapid Object Detection using a Boosted Cascade of Simple Features”. Proceedings of the 2001 IEEE Computer Society Conference on Computer Vision and Pattern Recognition. 2001. Vol. 1, pp. 511–518

    展开全文
  • 积分图像算法

    千次阅读 2017-11-29 11:21:55
    13行代码实现最快速最高效的积分图像算法。  研究图像到一定程度的人,应该都对积分图像有所了解,大家在百度或者google中都可以搜索到大量的相关博客,我这里不做多介绍。用积分图也确实能解决很多实际的问题,...
    
    

    13行代码实现最快速最高效的积分图像算法。

      研究图像到一定程度的人,应该都对积分图像有所了解,大家在百度或者google中都可以搜索到大量的相关博客,我这里不做多介绍。用积分图也确实能解决很多实际的问题,比如我博客中的基于局部均方差相关信息的图像去噪及其在实时磨皮美容算法中的应用 一文我就在网上看到很多人用累计积分图和乘积积分图来实现了。不过我浏览了很多人的博客,觉得很多人哪怕是图像方面的似乎还比较牛的人都对这个积分图的理解还不到位或者说理解有误,这里有必要借助我微弱的力量再次校正下。

           首先一个普遍的问题就是:积分图像的大小。你可以看到,90%自己写的积分图的作者都是把积分图像定位为W * H,但是不知道他们有没有注意到OpenCV里积分图的相关文档,我这里贴出OpenCV的官方文档:

      C++: void integral(InputArray image, OutputArray sum, int sdepth=-1

    Parameters:
    • image – Source image as W X H  , 8-bit or floating-point (32f or 64f).
    • sum – Integral image as (W + 1) X (H + 1) , 32-bit integer or floating-point (32f or 64f).
    • sdepth – Desired depth of the integral and the tilted integral images, CV_32SCV_32F, or CV_64F.

     

     

     

           注意到sum这一项的大小了吗, (W + 1) X (H + 1)而非W X H,为什么呢,我们知道,某个点的积分图反应的是原图中此位置左上角所有像素之和,这里是的累加和是不包括这个点像素本身的,那么这样,对于原图的第一行和第一列的所有像素,其对应位置的积分图就应该是0, 这样考虑到所有的像素,为了能容纳最后一列和最后一行的情况,最终的积分图就应该是 (W + 1) X (H + 1)大小。

            如果你还是希望定义成W X H大小,那么就必须每次判断你访问的积分图的位置,作为写程序来说,这样做对程序的性能和代码的简洁性都是不好的,并且你稍微不注意就会把代码写错。

           第二,就是积分图的计算的优化,很多博客也都描述了他们的优化方式,虽然他们都是描述的同一个算法,比如百度上比较靠前的博文: 【图像处理】快速计算积分图  中就用下述前两幅图描述了他的优化过程:

         --------->  ------->  

                     (1)  最原始方案             (2)网络上的优化方案            (3)我的优化方案

            不错,这样做已经很不错了,但是有一个问题就是我们需要多一个大小为W的内存来更新保存每一列相应的累计和,但是我们如果换成行方向呢,如上面的(3)所示,则只需要一个变量来累计行方向上的值,而我们知道单个变量CPU可能会把他放置到寄存器中或者我们可以强制把他声明为register变量的,而列方向上的内存数据就无法做到这一点了。

           另外,我们申请了积分图后,是没有必要先给他来一个清零操作的,因为后续我们会对每一个位置的值都填充0的。

           好,下面我们贴出了优化后的代码:

    复制代码
     1 void GetGrayIntegralImage(unsigned char *Src, int *Integral, int Width, int Height, int Stride)
     2 {
     3     memset(Integral, 0, (Width + 1) * sizeof(int));                    //    第一行都为0
     4     for (int Y = 0; Y < Height; Y++)
     5     {
     6         unsigned char *LinePS = Src + Y * Stride;
     7         int *LinePL = Integral + Y * (Width + 1) + 1;                  //    上一行位置            
     8         int *LinePD = Integral + (Y + 1) * (Width + 1) + 1;            //    当前位置,注意每行的第一列的值都为0
     9         LinePD[-1] = 0;                                                //    第一列的值为0
    10         for (int X = 0, Sum = 0; X < Width; X++)
    11         {
    12             Sum += LinePS[X];                                        //    行方向累加
    13             LinePD[X] = LinePL[X] + Sum;                            //    更新积分图
    14         }
    15     }
    16 }
    复制代码 

           代码很简单,但是集成了很多细节信息,只有有心人才能理解。

           在PC上,也许还是可以考虑到SSE优化,要使用SSE,就必须对Sum这个做改造,又要用一个W长度的int型内存记录,然后对 LinePD[X] = LinePL[X] + Sum; 用SSE优化,一次性处理4个数据据的加法,但是这么做SSE的提速和前面sum那句的处理的耗时那个更厉害,我没有去验证了。

           那么上面方法(2)的进一步的语法优化的代码如下(比原作者那个应该效率会好很多的)

    复制代码
     1 void GetGrayIntegralImage(unsigned char *Src, int *Integral, int Width, int Height, int Stride)
     2 {
     3     int *ColSum = (int *)calloc(Width, sizeof(int));        //    用的calloc函数哦,自动内存清0
     4     memset(Integral, 0, (Width + 1) * sizeof(int));
     5     for (int Y = 0; Y < Height; Y++)
     6     {
     7         unsigned char *LinePS = Src + Y * Stride;
     8         int *LinePL = Integral + Y * (Width + 1) + 1;
     9         int *LinePD = Integral + (Y + 1) * (Width + 1) + 1;
    10         LinePD[-1] = 0;
    11         for (int X = 0; X < Width; X++)
    12         {
    13             ColSum[X] += LinePS[X];
    14             LinePD[X] = LinePD[X - 1] + ColSum[X];
    15         }
    16     }
    17     free(ColSum);
    18 }
    复制代码

       可以看到,在最内层的循环里多了几个内存变量的访问,朋友们可以自己测试,我的优化方案在这一块的耗时只有方案(2)的一半左右,而且代码更简洁。

           当我们需要访问中心点为(x, y),半径为r的范围内的矩形像素内的累积值,相应的坐标计算就应该为:

              Integral(x - r, y - r) + Integral(x + r + 1, y + r + 1) - Integral(x - r, y + r + 1) - Integral(x + r + 1, y - r)

         注意上式计算中的加1,这主要是因为积分图是计算左上角像素的累计值这个特性决定的。

           那么下面我贴出用积分图实现0(1)的均值模糊的部分代码:

    复制代码
    void BoxBlur(unsigned char *Src, unsigned char *Dest, int Width, int Height, int Stride, int Radius)
    {
        int *Integral = (int *)malloc((Width + 1) * (Height + 1) * sizeof(int));
        GetGrayIntegralImage(Src, Integral, Width, Height, Stride);
        //#pragma omp parallel for
        for (int Y = 0; Y < Height; Y++)
        {
            int Y1 = max(Y - Radius, 0);
            int Y2 = min(Y + Radius + 1, Height - 1);
            /*int Y1 = Y - Radius;
            int Y2 = Y + Radius + 1;
            if (Y1 < 0) Y1 = 0;
            if (Y2 > Height) Y2 = Height;*/
            int *LineP1 = Integral + Y1 * (Width + 1);
            int *LineP2 = Integral + Y2 * (Width + 1);
            unsigned char *LinePD = Dest + Y * Stride;
            for (int X = 0; X < Width; X++)
            {
                int X1 = max(X - Radius, 0);
                int X2 = min(X + Radius + 1, Width);
                //    int X1 = X - Radius;
                //    if (X1 < 0) X1 = 0;
                //    int X2 = X + Radius + 1;
                //    if (X2 >= Width) X2 = Width - 1;
                int Sum = LineP2[X2] - LineP1[X2] - LineP2[X1] + LineP1[X1];
                int PixelCount = (X2 - X1) * (Y2 - Y1);
                LinePD[X] = (Sum + (PixelCount >> 1)) / PixelCount;
            }
        }
        free(Integral);
    }
    复制代码

       代码也很简洁明了,注意下我注释掉的几个部分。

       第一:

        //#pragma omp parallel for

      由于进行的积分图的操作,每个像素点的周边半径为r区域内的像素之和的计算就是前后无关的了,因此像素和像素之间的计算就是独立的了,这样就可以并行执行,这里用了OpenMP作为简易并行实现的一个例子而已。

           第二:我原来编程习惯怎是不怎么喜欢用max和min这样的函数,我总觉得用if这种判断效率应该会比max或者min高,而实际上却是max厉害一些,我看了下反汇编,max和min充分利用了条件按传送指令比如cmovg,cmovl,而一般的if语句很大程度上会调用jmp指令的(当然和常数比较一般编译也会用条件传送替代的,比如和0比较),jmp指令时比较耗时的。因此.......

           还有一个注意点就是积分图的最大X坐标是Width,最大Y坐标是Height, 这点和图像有所不同,正如上述代码所示。

           通过积分图技术实现的均值模糊和之前我在文章解析opencv中Box Filter的实现并提出进一步加速的方案(源码共享) 中介绍的方式(非SSE优化的代码)耗时基本差不多,内存占用也差不多,但是积分图技术有个优势,就是如果某个算法需要计算同一个图像的多个半径的模糊值,则积分图只需要计算一次,只在众多的基于多尺度模糊的算法中也是能提速的方案之一。

           上述是普通的累计积分图,我们常用的还有平方积分图,还有两幅图对应的乘积积分图,本质上和本例是没有啥,只需将 Sum += LinePS[X]; 这一句稍作修改。但是有一点,一直是我不太愿意用积分图的主要原因,就是保存积分图数据的内存区域或者数据类型问题,普通的积分图还好,就算是每个像素都为255,也只有当图像大于2800*3000左右时,才会超出int类型所能表达的范围,如果用uint类型表示,能容纳的图像大小又能提高一倍,一般来说够用了,但是如果是平方积分图,int类型在极端情况下只能处理不大于 256*256大小的图像,这样在实际中基本上是无用的,因此,可能我们就需要float类型或者int64为来表示。但是,第一,float类型会引来计算速度下降,特别是非PC的环境下。第二,int64会占用更大的内存,大约是8倍的原图像内存,同时在32位系统上也会带来速度的下降。

          对于彩色的图像,处理方式也类似,这里就不赘述了。

          本文对应的代码下载地址:http://files.cnblogs.com/files/Imageshop/IntegralImage.rar

    展开全文
  • 积分图像 来源:http://blog.sina.com.cn/s/blog_5562b0440102wgxs.html 以灰度图像为例子进行讲解,一个图像内矩形区域的积分是指该区域内所有灰度值的和,即: 所选定区域的积分为: 如图以3x6图像为例,左侧是...

    积分图像

    来源:http://blog.sina.com.cn/s/blog_5562b0440102wgxs.html

    以灰度图像为例子进行讲解,一个图像内矩形区域的积分是指该区域内所有灰度值的和,即:
    在这里插入图片描述
    所选定区域的积分为:
    在这里插入图片描述
    如图以3x6图像为例,左侧是原始图像,右侧是其积分图像,其中(2,4)位置的积分为16:
    在这里插入图片描述
    很显然,如果只是针对小区域的话,这样的加减倒也不是很复杂,如果这个区域包含成千上万的像素,那计算起来就比较复杂了。所以随着计算区域的增大,时间复杂度增长也很快。
    那有没有一种比较简单的方法,可以无论需要计算的区域有多大,它的时间复杂度都不变呢,或者变化很小。这就是积分图像最初的考虑策略,尽量减少后续的计算以达到实时的效果。
    在这里插入图片描述
    区域1 : = sum(A);
    区域2 : = sum(A + B);
    区域3 : = sum(A + C);
    区域4 : = sum(A + B + C + D);
    所以,如果需要计算D区域中的灰度和,则
    sum(D) = 区域4 - 区域2 - 区域3 + 区域1 (都是灰度值)。
    很明显,这里仅仅只需要通过查表得到 1、2、3、4点的积分图像的值即可得到。由此计算任意点积分方法可以化为:
    在这里插入图片描述
    其中integral(i,j)表示(i,j)点积分值,而image(i,j)表示的是该点图像灰度值,由此可以知道计算一个图像积分的运算量与这个图像的大小差不多。
    这其实就是积分图像最妙的地方,通过简单的预计算处理,存储整幅图像的积分图像,通过4次快速查表,便可以得到一个矩形框中的灰度和。

    积分直方图

    一个图像矩形区域内的积分直方图指该区域中所有灰度值出现的频数,如图所示:
    在这里插入图片描述
    本图是一个灰度级为[0,9]的图像,H(4,5)表示的是(0,0)到(4,5)所有像素所有灰度级出现的频数,即后面的数字[2 1 4 3 2 2 2 1 2 1]表示灰度级[0 1 2 3 4 5 6 7 8 9]在区域里出现的频数。如同积分图的计算方法,积分直方图也可以用类似的方法进行。
    在这里插入图片描述
    公式为:
    在这里插入图片描述

    疑问

    1.积分图像如何进行预处理?
    2.积分图像和积分直方图的具体应用

    展开全文
  • 积分图像(Integral Image)与积分直方图 (Integral Histogram)  (2016-04-10 17:07:12)      在图像处理中有两个常用的相关算法,这就是积分图像(Integral Image)和积分...

    积分图像(Integral Image)与积分直方图 (Integral Histogram)

      (2016-04-10 17:07:12)

       
        在图像处理中有两个常用的相关算法,这就是积分图像(Integral Image)和积分直方图(Integral Histogram),本文来讲解这两个算法的基本原理。
      在本文中主要以灰度图像来讲解。一个图像内矩形区域的积分是指这个矩形区域内所有灰度值的和,如图所示:
    积分图像(Integral <wbr>Image)与积分直方图 <wbr>(Integral <wbr>Histogram)

    所选定区域的积分为:
    积分图像(Integral <wbr>Image)与积分直方图 <wbr>(Integral <wbr>Histogram)
    如图以3x6图像为例,左侧是原始图像,右侧是其积分图像,其中(2,4)位置的积分为16:
    积分图像(Integral <wbr>Image)与积分直方图 <wbr>(Integral <wbr>Histogram)

    如果每个像素点都公式计算其积分,其运算量就太大了,为了减少计算量,专家经过推导给出了如下计算方法:如图所示:
    积分图像(Integral <wbr>Image)与积分直方图 <wbr>(Integral <wbr>Histogram)

    区域1 : = sum(A);
    区域2 : = sum(A + B);
    区域3 : = sum(A + C);
    区域4 : = sum(A + B + C + D);
    所以,如果需要计算D区域中的灰度和,则
    sum(D) = 区域4 - 区域2 - 区域3 + 区域1 (都是灰度值)。
    很明显,这里仅仅只需要通过查表得到 1、2、3、4点的积分图像的值即可得到。由此计算任意点积分方法可以化为:
    积分图像(Integral <wbr>Image)与积分直方图 <wbr>(Integral <wbr>Histogram)
    其中integral(i,j)表示(i,j)点积分值,而image(i,j)表示的是该点图像灰度值,由此可以知道计算一个图像积分的运算量与这个图像的大小差不多。
      下面再说,积分直方图(Integral Histogram)。一个图像内矩形区域的积分积分直方图是指这个矩形区域内所有灰度值的频数。普通的灰度直方图是指一个图像各灰度级出现的频数,如图所示:
    积分图像(Integral <wbr>Image)与积分直方图 <wbr>(Integral <wbr>Histogram)

    而积分直方图如图所示:
    积分图像(Integral <wbr>Image)与积分直方图 <wbr>(Integral <wbr>Histogram)
    本图是一个灰度级为[0,9]的图像,H(4,5)表示的是(0,0)到(4,5)所有像素所有灰度级出现的频数,即后面的数字[2 1 4 3 2 2 2 1 2 1]表示灰度级[0 1 2 3 4 5 6 7 8 9]在区域里出現的频数。如同积分图的计算方法,积分直方图也可以用类似的方法进行。
    积分图像(Integral <wbr>Image)与积分直方图 <wbr>(Integral <wbr>Histogram)
    公式如下:
    积分图像(Integral <wbr>Image)与积分直方图 <wbr>(Integral <wbr>Histogram)
    也就是可以如下进行:
    积分图像(Integral <wbr>Image)与积分直方图 <wbr>(Integral <wbr>Histogram)
    展开全文
  • 积分图像的计算

    2019-06-02 10:44:27
    积分图像的计算 例如: 积分图求出任意大小区域 API介绍 代码演示: #include <opencv2/opencv.hpp> #include <iostream> using namespace cv; int main(int argc, char** argv) { Mat src = ...
  • 积分图像顾名思义,就是求和,完整的意思是每一个像素点的灰度值等于在该像素点之前 所有像素点灰度值之和。 从上方图中抽取4个像素: 这4个像素点对应的在积分图像中的值为: 其关系为: 将.
  • 提出了一种在GPU上计算积分图像的方法。积分图像可通过对输入图像的行实行前缀加法后再对列实行前缀加法构建。前缀加法是指对于一个数组,求取起始位置至每一个下标位置的数组元素的和的操作。提出了分段前缀加法...
  • 本文针对二维Otsu的耗时瓶颈问题, 引人积分图像简化了二维直方图最佳阈值搜索过程的计算复杂度, 从而大大缩短算法处理时间。实验结果表明, 本文提出的算法在分割效果上与原始算法完全相同, 但计算时间远远小于后者, ...
  • 此示例演示如何使用积分图像滤波对图像应用多个大小不同的盒式滤波器。积分图像是一种有用的图像表示方法,可以快速计算局部图像的和。盒滤波器可以看作是每个像素的局部加权和。将图像读入工作区并显示它。 ...
  • matlab构建积分图像

    千次阅读 2017-12-26 21:10:54
    记录一下,代码十分简单,原理也非常容易~img=double(imread('TestImages/lena1.png')); [m,n]=size(img); I=zeros(m,n); for i=1:m for j=1:n if i==1 && j==1 %积分图像左上角 I(i,j)=img(i,j);
  • 积分图像(integral image)是一种快速计算矩形区域之和的数据结构,常利用它对算法进行加速。积分图像中处的值是原始灰度图像的左上角与当前点所围成的矩形区域内所有像素点的灰度值之和,即: 其中 为原...
  • 转载自:http://blog.sina.com.cn/s/blog_5562b0440102wgxs.html在图像处理中有两个常用的相关算法,这就是积分图像(Integral Image)和积分直方图(Integral Histogram),本文来讲解这两个算法的基本原理。...
  • 1. 积分图像 2. 盒子滤波(均值滤波) 1. 积分图像 输出结果 2. 盒子滤波(均值滤波) 输出结果: 源码 #include <ostream> #include <opencv.hpp> #include<opencv2/opencv.hpp> #...
  • OpenCV—使用积分图像统计像素

    万次阅读 2015-10-10 20:35:06
    直方图的计算方法为遍历图像的全部像素并累计每...在这种情况下使用积分图像将极大地提高统计图像子区域像素的效率。积分图像在程序中应用非常广泛。本文为学习笔记,实现书中给出的利用积分图像计算自适应阈值的例子。
  • 在图像处理中有两个常用的相关算法,这就是积分图像(Integral Image)和积分直方图(Integral Histogram),本文来讲解这两个算法的基本原理。   在本文中主要以灰度图像来讲解。一个图像内矩形区域的积分是指这个...
  • 积分图像基础上提出和应用平方积分图像,实现了一种计算速度与图像窗口大小无关的快速灰度均值和方差算法。应用该算法,结合对灰度分布标准化近似计算公式的变换,实现了图像窗口灰度分布标准化的快速计算。实验证明,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,257
精华内容 902
关键字:

积分图像