@转载请注明出处
积分图:
假设原图图幅wxh,则积分图图幅为(w+1)*(h+1)。
积分图第一行和第一列全为0,其余点为图像像素点左上角所有像素值的和。
计算方法有两种:
- 方法1.计算前一行当前列的和,加上当前行,该列前所有像素值的和。
- 方法2.左边像素点的积分和,加上上一行当前列的积分和,减去上一行左边像素的积分和,加上当前像素值。
假设要求像素点(x,y)的积分和,左边像素点为(x-1,y),上一行当前列(x,y-1),上一行左边像素(x-1,y-1)。
则ii(x,y) = ii(x-1,y) + ii(x,y-1) - ii(x-1,y-1) + f(x,y).
均值滤波
主要用于降噪。一般计算3x3或5x5区域的平均值。因而可以用积分图,计算3x3区域的和,然后求平均值。
#include <opencv2/opencv.hpp>
#include <iostream>
int* create_integra_map(unsigned char* src, int rows, int cols)
{
int r,c,size;
int* map;
unsigned char* ptr;
int* maplast;
int* mapnow;
int sum = 0;
size = sizeof(int)*(rows+1)*(cols+1);
map = (int*)malloc(size);
memset(map,0,size);
for(r = 0; r < rows; r++)
{
ptr = src + r*cols;
maplast = map + r * (cols + 1) + 1;
mapnow = map + (r + 1) * (cols + 1) + 1;
mapnow[-1] = 0;
for(c = 0, sum = 0; c < cols; c++)
{
sum += ptr[c];
mapnow[c] = maplast[c] +sum;
}
}
return map;
}
void meanBlur(unsigned char* src, int rows, int cols, unsigned char* dst)
{
unsigned char* ptr;
int r,c,sum;
int *maplast, *mapnext;
unsigned char* out;
int* maps = create_integra_map(src, rows, cols);
for(r = 1; r < rows - 1; r++)
{
ptr = src + r*cols;
maplast = maps + (r-1)*(cols+1) + 1;
mapnext = maps + (r+2)*(cols+1) + 1;
out = dst + r * cols;
for(c = 1; c < cols - 1; c++)
{
sum = mapnext[c+1] + maplast[c-2] - (mapnext[c-2] + maplast[c+1]);
out[c] = (int)(sum / 9.0f);
}
}
free(maps);
}
int main()
{
cv::Mat src = cv::imread("lena.jpg", 0);
cv::Mat dst(src.size(),src.type(),cv::Scalar::all(0));
meanBlur(src.data, src.rows, src.cols, dst.data);
cv::imshow("meanblur.jpg", dst);
cv::waitKey(0);
return 0;
}