6.8方框滤波

基本概念

方框滤波(Box Filter)是一种基本的图像处理技术,用于对图像进行平滑处理模糊效果。它通过在图像上应用一个固定大小的方框核(通常是矩形),计算该区域内像素值的平均值来替换中心像素的值。这种方式简单且计算效率高,但在处理边界时需要特别注意。

方框滤波(Box Filter)是一种简单的线性滤波器,它可以用于平滑图像或降低噪声。方框滤波器使用一个均匀加权的矩形核来对图像进行卷积,从而实现图像的平滑处理。在OpenCV中,方框滤波可以使用 boxFilter 函数来实现。

函数原型
在OpenCV中,方框滤波可以通过boxFilter函数实现。函数原型如下:

void boxFilter(InputArray src, OutputArray dst, int ddepth, Size ksize, 
               Point anchor=Point(-1,-1), bool normalize=true, 
               int borderType=BORDER_DEFAULT);
参数说明
src: 输入图像,可以是单通道或多通道图像。
dst: 输出图像,将具有与输入图像相同的尺寸,但深度取决于ddepth参数。
ddepth: 输出图像的深度。常见的选择有:
    -1: 输出图像深度与输入图像相同。
    CV_8U: 8位无符号整数。
    CV_16S: 16位有符号整数。
    CV_32F: 32位浮点数。
    CV_64F: 64位浮点数。
ksize: 方框核的大小,指定为一个Size对象,例如Size(3, 3)。
anchor: 核的锚点位置,默认为Point(-1,-1),表示锚点在核的中心。
normalize: 是否归一化。如果设置为true(默认值),则输出的每个像素将是核内所有像素值的平均值;如果设置为false,则输出的每个像素将是核内所有像素值的总和。
borderType: 边界处理类型。常见的边界处理方式有:
    BORDER_CONSTANT: 使用常数值填充边界外区域。
    BORDER_REPLICATE: 复制边界像素。
    BORDER_REFLECT: 镜像反射边界。
    BORDER_WRAP: 边界环绕(类似于纹理坐标)。
    BORDER_REFLECT_101 或 BORDER_DEFAULT: 默认的边界反射方式。

使用示例1

下面是一个详细的示例,展示如何使用boxFilter函数来进行图像平滑处理。

步骤一:包含必要的头文件
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;

步骤二:加载图像
int main(int argc, char** argv)
{
    Mat src = imread("path_to_your_image.jpg", IMREAD_COLOR);
    if (src.empty())
    {
        cout << "Error: Image cannot be loaded!" << endl;
        return -1;
    }

步骤三:定义输出图像
    Mat dst;

步骤四:应用方框滤波
    // 设置方框核的大小
    Size ksize(5, 5);  // 5x5的核

    // 应用方框滤波
    boxFilter(src, dst, -1, ksize, Point(-1,-1), true);
在这里,-1表示输出图像的深度与输入图像相同。true表示启用归一化,即输出的每个像素值将是核内所有像素值的平均值。

步骤五:显示结果
    namedWindow("Original Image", WINDOW_AUTOSIZE);
    imshow("Original Image", src);

    namedWindow("Blurred Image", WINDOW_AUTOSIZE);
    imshow("Blurred Image", dst);

    waitKey(0);
    return 0;
}


注意事项
归一化: 如果normalize参数设置为true,则输出图像中的每个像素值将是核内所有像素值的平均值。如果设置为false,则输出图像中的每个像素值将是核内所有像素值的总和。在某些情况下,不归一化的结果可能会导致像素值溢出。
边界处理: 方框滤波在处理图像边界时可能会出现问题,特别是当核的大小超过边界时。选择适当的边界处理方式可以帮助解决这些问题。
性能: 方框滤波是一种简单快速的滤波方法,但由于它在每个像素上都执行了累加操作,因此在处理大尺寸核时可能会消耗较多资源。对于大型核,可以考虑使用积分图(integral image)来加速计算。


通过上述步骤,你可以使用OpenCV的boxFilter函数来对图像进行平滑处理或实现模糊效果。

#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;

int main(int argc, char** argv)
{
	Mat src = imread("880.jpeg", IMREAD_COLOR);
	if (src.empty())
	{
		cout << "Error: Image cannot be loaded!" << endl;
		return -1;
	}


	Mat dst;

	// 设置方框核的大小
	Size ksize(5, 5);  // 5x5的核

	// 应用方框滤波
	boxFilter(src, dst, -1, ksize, Point(-1, -1), true);

	namedWindow("Original Image", WINDOW_NORMAL);
	imshow("Original Image", src);

	namedWindow("Blurred Image", WINDOW_NORMAL);
	imshow("Blurred Image", dst);

	waitKey(0);
	return 0;
}


注意事项
归一化: 如果normalize参数设置为true,则输出图像中的每个像素值将是核内所有像素值的平均值。如果设置为false,则输出图像中的每个像素值将是核内所有像素值的总和。在某些情况下,不归一化的结果可能会导致像素值溢出。
边界处理: 方框滤波在处理图像边界时可能会出现问题,特别是当核的大小超过边界时。选择适当的边界处理方式可以帮助解决这些问题。
性能: 方框滤波是一种简单快速的滤波方法,但由于它在每个像素上都执行了累加操作,因此在处理大尺寸核时可能会消耗较多资源。对于大型核,可以考虑使用积分图(integral image)来加速计算。


通过上述步骤,你可以使用OpenCV的boxFilter函数来对图像进行平滑处理或实现模糊效果。

运行结果1

示例代码2

示例代码下面是一个使用OpenCV C++实现方框滤波的示例代码:

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

void applyBoxFilter(const Mat &src, Mat &dst, Size ksize, bool normalize) 
{
	boxFilter(src, dst, -1, ksize, Point(-1, -1), normalize);
}

int main(int argc, char** argv) 
{
	/*if (argc != 2) {
		cout << "Usage: ./BoxFilter <Image Path>" << endl;
		return -1;
	}*/

	// 加载图像
	Mat img = imread("559.jpg", IMREAD_GRAYSCALE);
	if (!img.data) 
	{
		cout << "Error opening image" << endl;
		return -1;
	}

	// 定义核大小
	Size ksize(5, 5);  // 核大小

	// 初始化输出矩阵
	Mat filtered;

	// 应用方框滤波
	applyBoxFilter(img, filtered, ksize, true);

	// 显示结果
	namedWindow("Original Image", WINDOW_NORMAL);
	imshow("Original Image", img);
	namedWindow("Filtered Image", WINDOW_NORMAL);
	imshow("Filtered Image", filtered);

	waitKey(0);
	destroyAllWindows();

	return 0;
}


代码解释
1. 加载图像:使用 imread 函数加载图像。
2. 定义核大小:设置方框滤波器的核大小。
3. 初始化输出矩阵:创建一个新的矩阵来存储滤波后的图像。
4. 应用方框滤波:使用 boxFilter 函数应用方框滤波。
5. 显示结果:使用 imshow 函数显示原始图像和滤波后的图像。

运行结果2

方框滤波的应用

方框滤波器常用于以下场景:

•图像平滑:通过平均相邻像素值来减少图像中的噪声。

•均值滤波:当 normalize 参数为 true 时,方框滤波器相当于均值滤波器。

•非归一化的方框滤波:当 normalize 参数为 false 时,可以用于特殊的图像处理任务,例如累积求和。

非归一化的方框滤波示例

非归一化的方框滤波不将权重归一化,这意味着每个像素的权重保持不变。这在某些特殊情况下是有用的,例如累积求和(Integral Images)。

#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;


void applyNonNormalizedBoxFilter(const Mat &src, Mat &dst, Size ksize)
{
	boxFilter(src, dst, -1, ksize, Point(-1, -1), false);
}

int main(int argc, char** argv)
{
	//if (argc != 2)
	//{
	//	cout << "Usage: ./NonNormalizedBoxFilter <Image Path>" << endl;
	//	return -1;
	//}

	// 加载图像
	Mat img = imread("559.jpg", IMREAD_GRAYSCALE);
	if (!img.data)
	{
		cout << "Error opening image" << endl;
		return -1;
	}

	// 定义核大小
	Size ksize(5, 5);  // 核大小

	// 初始化输出矩阵
	Mat filtered;

	// 应用非归一化的方框滤波
	applyNonNormalizedBoxFilter(img, filtered, ksize);

	// 显示结果
	namedWindow("Original Image", WINDOW_NORMAL);
	imshow("Original Image", img);
	namedWindow("Non-Normalized Filtered Image", WINDOW_NORMAL);
	imshow("Non-Normalized Filtered Image", filtered);

	waitKey(0);
	destroyAllWindows();

	return 0;
}

运行结果3

性能优化

方框滤波器的计算可以通过积分图像(Integral Images)来加速。积分图像是一种预先计算的数据结构,可以高效地计算任意矩形区域的和。OpenCV提供了 integral 函数来计算积分图像。

积分图像示例

积分图像可以用来高效地实现方框滤波。

#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;

void applyBoxFilterUsingIntegral(const Mat &src, Mat &dst, Size ksize) 
{
    Mat integralImg;
    integral(src, integralImg);

    int radius = ksize.width / 2;
    for (int y = radius; y < src.rows - radius; ++y) 
    {
        for (int x = radius; x < src.cols - radius; ++x) 
        {
            int top_left = integralImg.at<int>(y - radius, x - radius);
            int top_right = integralImg.at<int>(y - radius, x + radius);
            int bottom_left = integralImg.at<int>(y + radius, x - radius);
            int bottom_right = integralImg.at<int>(y + radius, x + radius);

            int sum = bottom_right + top_left - top_right - bottom_left;
            dst.at<uchar>(y, x) = static_cast<uchar>(sum / (ksize.width * ksize.height));
        }
    }
}

int main(int argc, char** argv) 
{
    if (argc != 2) 
    {
        cout << "Usage: ./BoxFilterUsingIntegral <Image Path>" << endl;
        return -1;
    }

    // 加载图像
    Mat img = imread(argv[1], IMREAD_GRAYSCALE);
    if (!img.data)
    {
        cout << "Error opening image" << endl;
        return -1;
    }

    // 定义核大小
    Size ksize(5, 5);  // 核大小

    // 初始化输出矩阵
    Mat filtered = Mat::zeros(img.size(), img.type());

    // 应用方框滤波
    applyBoxFilterUsingIntegral(img, filtered, ksize);

    // 显示结果
    imshow("Original Image", img);
    imshow("Filtered Image Using Integral", filtered);

    waitKey(0);
    destroyAllWindows();

    return 0;
}

运行结果4

总结

通过这些示例,你应该能够理解如何在OpenCV中使用C++实现方框滤波。方框滤波器是一个简单但有效的工具,可用于图像平滑和噪声减少。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值