积分图算法简介

原文来自https://blog.csdn.net/jia20003/article/details/52710751

图像处理之积分图算法

一:积分图来源与发展

积分图像是Crow在1984年首次提出,是为了在多尺度透视投影中提高渲染速度。随后这种技术被应用到基于NCC的快速匹配、对象检测和SURF变换中、基于统计学的快速滤波器等方面。积分图像是一种在图像中快速计算矩形区域和的方法,这种算法主要优点是一旦积分图像首先被计算出来我们可以计算图像中任意大小矩形区域的和而且是在常量时间内。这样在图像模糊、边缘提取、对象检测的时候极大降低计算量、提高计算速度。第一个应用积分图像技术的应用是在Viola-Jones的对象检测框架中出现。

二:积分图像概念

在积分图像(Integral Image - ii)上任意位置(x, y)处的ii(x, y)表示该点左上角所有像素之和,表示如下:



从给定图像I从上到下、从左到右计算得到和的积分图像公式如下:


其中(x<0 || y<0) 时ii(x,y)=0, i(x,y)=0

得到积分图像之后,图像中任意矩形区域和通过如下公式计算:



三:代码实现:

积分图像算法的Java代码实现如下:

  1. package com.gloomyfish.ii.demo;  
  2.   
  3. public class IntIntegralImage extends AbstractByteProcessor {  
  4.     // sum index tables  
  5.     private int[] sum;  
  6.     private int[] squaresum;  
  7.     // image  
  8.     private byte[] image;  
  9.     private int width;  
  10.     private int height;  
  11.   
  12.     public byte[] getImage() {  
  13.         return image;  
  14.     }  
  15.   
  16.     public void setImage(byte[] image) {  
  17.         this.image = image;  
  18.     }  
  19.       
  20.     public int getBlockSum(int x, int y, int m, int n) {  
  21.         int swx = x + n/2;  
  22.         int swy = y + m/2;  
  23.         int nex = x-n/2-1;  
  24.         int ney = y-m/2-1;  
  25.         int sum1, sum2, sum3, sum4;  
  26.         if(swx >= width) {  
  27.             swx = width - 1;  
  28.         }  
  29.         if(swy >= height) {  
  30.             swy = height - 1;  
  31.         }  
  32.         if(nex < 0) {  
  33.             nex = 0;  
  34.         }  
  35.         if(ney < 0) {  
  36.             ney = 0;  
  37.         }  
  38.         sum1 = sum[ney*width+nex];  
  39.         sum4 = sum[swy*width+swx];  
  40.         sum2 = sum[swy*width+nex];  
  41.         sum3 = sum[ney*width+swx];  
  42.         return ((sum1 + sum4) - sum2 - sum3);  
  43.     }  
  44.       
  45.     public int getBlockSquareSum(int x, int y, int m, int n) {        
  46.         int swx = x + n/2;  
  47.         int swy = y + m/2;  
  48.         int nex = x-n/2-1;  
  49.         int ney = y-m/2-1;  
  50.         int sum1, sum2, sum3, sum4;  
  51.         if(swx >= width) {  
  52.             swx = width - 1;  
  53.         }  
  54.         if(swy >= height) {  
  55.             swy = height - 1;  
  56.         }  
  57.         if(nex < 0) {  
  58.             nex = 0;  
  59.         }  
  60.         if(ney < 0) {  
  61.             ney = 0;  
  62.         }  
  63.         sum1 = squaresum[ney*width+nex];  
  64.         sum4 = squaresum[swy*width+swx];  
  65.         sum2 = squaresum[swy*width+nex];  
  66.         sum3 = squaresum[ney*width+swx];  
  67.         return ((sum1 + sum4) - sum2 - sum3);  
  68.     }  
  69.   
  70.     @Override  
  71.     public void process(int width, int height) {  
  72.         this.width = width;  
  73.         this.height = height;  
  74.         sum = new int[width*height];  
  75.         squaresum = new int[width*height];  
  76.         // rows  
  77.         int p1=0, p2=0, p3=0, p4;  
  78.         int offset = 0, uprow=0, leftcol=0;  
  79.         int s=0;  
  80.         for(int row=0; row<height; row++ ) {  
  81.             offset = row*width;  
  82.             uprow = row-1;  
  83.             for(int col=0; col<width; col++) {  
  84.                 leftcol=col-1;  
  85.                 p1=image[offset]&0xff;// p(x, y)  
  86.                 p2=(leftcol<0) ? 0:sum[offset-1]; // p(x-1, y)  
  87.                 p3=(uprow<0) ? 0:sum[offset-width]; // p(x, y-1);  
  88.                 p4=(uprow<0||leftcol<0) ? 0:sum[offset-width-1]; // p(x-1, y-1);  
  89.                 s = sum[offset]= p1+p2+p3-p4;  
  90.                 squaresum[offset]=s*s;  
  91.                 // System.out.print(“\t[“ + offset+”]=” + s);  
  92.                 offset++;  
  93.             }  
  94.             // System.out.println();  
  95.         }  
  96.     }  
  97.       
  98.     public static void main(String[] args) {  
  99.         byte[] data = new byte[]{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};  
  100.         IntIntegralImage ii = new IntIntegralImage();  
  101.         ii.setImage(data);  
  102.         ii.process(73);  
  103.           
  104.         int sum = ii.getBlockSum(3233);  
  105.         System.out.println(”sum = ” + sum);  
  106.     }  
  107. }  
package com.gloomyfish.ii.demo;

public class IntIntegralImage extends AbstractByteProcessor {
    // sum index tables
    private int[] sum;
    private int[] squaresum;
    // image
    private byte[] image;
    private int width;
    private int height;

    public byte[] getImage() {
        return image;
    }

    public void setImage(byte[] image) {
        this.image = image;
    }

    public int getBlockSum(int x, int y, int m, int n) {
        int swx = x + n/2;
        int swy = y + m/2;
        int nex = x-n/2-1;
        int ney = y-m/2-1;
        int sum1, sum2, sum3, sum4;
        if(swx >= width) {
            swx = width - 1;
        }
        if(swy >= height) {
            swy = height - 1;
        }
        if(nex < 0) {
            nex = 0;
        }
        if(ney < 0) {
            ney = 0;
        }
        sum1 = sum[ney*width+nex];
        sum4 = sum[swy*width+swx];
        sum2 = sum[swy*width+nex];
        sum3 = sum[ney*width+swx];
        return ((sum1 + sum4) - sum2 - sum3);
    }

    public int getBlockSquareSum(int x, int y, int m, int n) {      
        int swx = x + n/2;
        int swy = y + m/2;
        int nex = x-n/2-1;
        int ney = y-m/2-1;
        int sum1, sum2, sum3, sum4;
        if(swx >= width) {
            swx = width - 1;
        }
        if(swy >= height) {
            swy = height - 1;
        }
        if(nex < 0) {
            nex = 0;
        }
        if(ney < 0) {
            ney = 0;
        }
        sum1 = squaresum[ney*width+nex];
        sum4 = squaresum[swy*width+swx];
        sum2 = squaresum[swy*width+nex];
        sum3 = squaresum[ney*width+swx];
        return ((sum1 + sum4) - sum2 - sum3);
    }

    @Override
    public void process(int width, int height) {
        this.width = width;
        this.height = height;
        sum = new int[width*height];
        squaresum = new int[width*height];
        // rows
        int p1=0, p2=0, p3=0, p4;
        int offset = 0, uprow=0, leftcol=0;
        int s=0;
        for(int row=0; row<height; row++ ) {
            offset = row*width;
            uprow = row-1;
            for(int col=0; col<width; col++) {
                leftcol=col-1;
                p1=image[offset]&0xff;// p(x, y)
                p2=(leftcol<0) ? 0:sum[offset-1]; // p(x-1, y)
                p3=(uprow<0) ? 0:sum[offset-width]; // p(x, y-1);
                p4=(uprow<0||leftcol<0) ? 0:sum[offset-width-1]; // p(x-1, y-1);
                s = sum[offset]= p1+p2+p3-p4;
                squaresum[offset]=s*s;
                // System.out.print("\t[" + offset+"]=" + s);
                offset++;
            }
            // System.out.println();
        }
    }

    public static void main(String[] args) {
        byte[] data = new byte[]{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
        IntIntegralImage ii = new IntIntegralImage();
        ii.setImage(data);
        ii.process(7, 3);

        int sum = ii.getBlockSum(3, 2, 3, 3);
        System.out.println("sum = " + sum);
    }
}

后续应用相关博文会陆续出炉!
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用C语言实现积分实现ACE算法的代码: ```c #include <stdio.h> #include <stdlib.h> #include <opencv2/opencv.hpp> using namespace cv; void integral_image(Mat &img, Mat &integral) { int h = img.rows; int w = img.cols; integral.create(h+1, w+1, CV_32S); integral.setTo(0); for(int i=1; i<=h; i++) { for(int j=1; j<=w; j++) { integral.at<int>(i, j) = img.at<uchar>(i-1, j-1) + integral.at<int>(i-1, j) + integral.at<int>(i, j-1) - integral.at<int>(i-1, j-1); } } } void local_mean_and_variance(Mat &integral, int w_size, Mat &local_mean, Mat &local_variance) { int h = integral.rows - 1; int w = integral.cols - 1; int half_w_size = w_size / 2; local_mean.create(h, w, CV_32F); local_variance.create(h, w, CV_32F); for(int i=0; i<h; i++) { for(int j=0; j<w; j++) { int top = i - half_w_size; int left = j - half_w_size; int bottom = i + half_w_size; int right = j + half_w_size; top = top < 0 ? 0 : top; left = left < 0 ? 0 : left; bottom = bottom >= h ? h-1 : bottom; right = right >= w ? w-1 : right; int area = (bottom - top + 1) * (right - left + 1); int sum = integral.at<int>(bottom+1, right+1) + integral.at<int>(top, left) - integral.at<int>(bottom+1, left) - integral.at<int>(top, right+1); float mean = (float)sum / area; local_mean.at<float>(i, j) = mean; int sum2 = integral.at<int>(bottom+1, right+1) + integral.at<int>(top, left) - integral.at<int>(bottom+1, left) - integral.at<int>(top, right+1); float variance = (float)sum2 / area - mean * mean; local_variance.at<float>(i, j) = variance; } } } void contrast_score(Mat &local_mean, Mat &local_variance, float k, float alpha, Mat &contrast) { contrast.create(local_mean.rows, local_mean.cols, CV_32F); for(int i=0; i<local_mean.rows; i++) { for(int j=0; j<local_mean.cols; j++) { float mean = local_mean.at<float>(i, j); float variance = local_variance.at<float>(i, j); float score = k * fabs(mean) / sqrt(variance + alpha * alpha); contrast.at<float>(i, j) = score; } } } void contrast_enhancement(Mat &img, Mat &contrast, Mat &img_enhanced) { img.convertTo(img_enhanced, CV_32F); float *pImg = img_enhanced.ptr<float>(0); float *pContrast = contrast.ptr<float>(0); int size = img_enhanced.rows * img_enhanced.cols; for(int i=0; i<size; i++) { pImg[i] = pImg[i] + pContrast[i] * (pImg[i] - mean(pImg, size)); pImg[i] = pImg[i] < 0 ? 0 : pImg[i]; pImg[i] = pImg[i] > 255 ? 255 : pImg[i]; } img_enhanced.convertTo(img_enhanced, CV_8U); } int main(int argc, char **argv) { if(argc < 2) { printf("Usage: %s image_path\n", argv[0]); return -1; } Mat img = imread(argv[1], IMREAD_GRAYSCALE); if(img.empty()) { printf("Failed to load image: %s\n", argv[1]); return -1; } Mat integral, local_mean, local_variance, contrast, img_enhanced; integral_image(img, integral); local_mean_and_variance(integral, 21, local_mean, local_variance); contrast_score(local_mean, local_variance, 0.4, 1.0, contrast); contrast_enhancement(img, contrast, img_enhanced); imshow("original", img); imshow("enhanced", img_enhanced); waitKey(0); destroyAllWindows(); return 0; } ``` 其中,img_path 是待处理的像路径,w_size 是局部均值和局部方差计算时的窗口大小,k 和 alpha 是对比度得分计算时的参数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值