meanFilter积分图

定义

积分图中p(i, j) 的值是原图中I(0, 0)到I(i, j)组成的矩阵的像素的和。用积分图可用于快速实现计算Harr特征、二值化、均值滤波等算法。

积分图实现均值滤波的速度很快,且和size的大小无关。

计算积分图

公式是res(i, j) = res(i - 1, j ) + res(i, j - 1) - res(i - 1, j - 1) + I(i, j) 。
积分图的结果比原结果多一行一列值为0的像素。

void Im_integral(cv::Mat& src, cv::Mat& dst) {
    int row = src.rows;
    int col = src.cols;
    dst = cv::Mat::zeros(row + 1, col + 1, CV_32F);
    for (int i = 1; i < dst.rows; ++i) {
        for (int j = 1; j < dst.cols; ++j) {
            float top_left = dst.ptr(i - 1)[j - 1];
            float top_right = dst.ptr(i - 1)[j];
            float buttom_left = dst.ptr(i)[j - 1];
            int buttom_right = src.ptr(i - 1)[j - 1];
            dst.ptr(i)[j] = buttom_right + buttom_left + top_right - top_left;
        }
    }
}

均值滤波

难点就是积分图的扩展边界的尺寸的处理。

void meanFilter(cv::Mat &src, cv::Mat &dst, int size) {
    if (size % 2 == 0) size++;
    int radius = size / 2;
    cv::Mat srcNew;
    cv::copyMakeBorder(src, srcNew, radius, radius, radius, radius, cv::BORDER_REFLECT);

    cv::Mat inte;
    Im_integral(srcNew, inte);

    dst = cv::Mat::zeros(src.size(), src.type());

    float mean = 0;
    for (int i = radius + 1; i < src.rows + radius + 1; ++i) { 
        for (int j = radius + 1; j < src.cols + radius + 1; ++j) {
            float top_left = inte.ptr(i - radius - 1)[j - radius - 1];
            float top_right = inte.ptr(i - radius - 1)[j + radius];
            float buttom_left = inte.ptr(i + radius)[j - radius - 1];
            float buttom_right = inte.ptr(i + radius)[j + radius];
            mean = (buttom_right - top_right - buttom_left + top_left) / pow(size, 2);
            if (mean < 0)
                mean = 0;
            else if (mean > 255)
                mean = 255;
            dst.at(i - radius - 1, j - radius - 1) = static_cast (mean);
        }
    }
}

你可能感兴趣的:(meanFilter积分图)