前言
基于opencv的c++接口,实现常用的图像滤波方法,包括了均值滤波、中值滤波、高斯滤波、双边滤波、高通滤波以及低通滤波。
相关的opencv接口解析
CV_EXPORTS_W void blur( InputArray src, OutputArray dst,
Size ksize, Point anchor = Point(-1,-1),
int borderType = BORDER_DEFAULT );
该函数使用内核平滑图像。
@param src 输入图像; 它可以有任意数量的通道,这些通道是独立处理的,但是深度应为 CV_8U、CV_16U、CV_16S、CV_32F 或 CV_64F。
@param dst 输出与 src 大小和类型相同的图像。
@param ksize 模糊内核大小。
@param anchor 锚点; 默认值 Point(-1,-1) 表示锚点在内核中央。
@param borderType 用于外推图像外像素的边框模式,请参阅#BorderTypes。 不支持#BORDER_WRAP。
enum BorderTypes {
BORDER_CONSTANT = 0, //!< `iiiiii|abcdefgh|iiiiiii` with some specified `i`
BORDER_REPLICATE = 1, //!< `aaaaaa|abcdefgh|hhhhhhh`
BORDER_REFLECT = 2, //!< `fedcba|abcdefgh|hgfedcb`
BORDER_WRAP = 3, //!< `cdefgh|abcdefgh|abcdefg`
BORDER_REFLECT_101 = 4, //!< `gfedcb|abcdefgh|gfedcba`
BORDER_TRANSPARENT = 5, //!< `uvwxyz|abcdefgh|ijklmno`
BORDER_REFLECT101 = BORDER_REFLECT_101, //!< same as BORDER_REFLECT_101
BORDER_DEFAULT = BORDER_REFLECT_101, //!< same as BORDER_REFLECT_101
BORDER_ISOLATED = 16 //!< do not look outside of ROI
};
CV_EXPORTS_W void GaussianBlur( InputArray src, OutputArray dst, Size ksize,
double sigmaX, double sigmaY = 0,
int borderType = BORDER_DEFAULT );
该函数将源图像与指定的高斯核进行卷积。支持就地过滤。
@param src 输入图像;图像可以有任意数量的通道,它们是独立处理的,但深度应该是 CV_8U、CV_16U、CV_16S、CV_32F 或 CV_64F。
@param dst 输出与 src 大小和类型相同的图像。
@param ksize 高斯内核大小。 ksize.width 和 ksize.height 可以不同,但它们都必须是正数和奇数。或者,它们可以是零,然后根据 sigma 计算它们。
@param sigmaX X 方向的高斯核标准差。
@param sigmaY Y 方向的高斯核标准差;如果 sigmaY 为零,则设置为等于 sigmaX,如果两个 sigma 均为零,则分别从 ksize.width 和 ksize.height 计算;为了完全控制结果,无论将来可能修改所有这些语义,建议指定所有 ksize、sigmaX 和 sigmaY。
@param borderType 像素外推方法,参见#BorderTypes。不支持#BORDER_WRAP。
CV_EXPORTS_W void medianBlur( InputArray src, OutputArray dst, int ksize );
该函数使用具有孔径的中值滤波器来平滑图像。 多通道图像的每个通道都是独立处理的。 支持就地操作。
@param src 输入 1、3 或 4 通道图像; ksize 为 3 或 5 时,图像深度应为 CV_8U、CV_16U 或 CV_32F,对于较大的光圈尺寸,只能为 CV_8U。
@param dst 与 src 大小和类型相同的目标数组。
@param ksize 孔径线性大小; 它必须是奇数且大于 1,例如:3、5、7 …
CV_EXPORTS_W void bilateralFilter( InputArray src, OutputArray dst, int d,
double sigmaColor, double sigmaSpace,
int borderType = BORDER_DEFAULT );
该函数对输入图像应用双边过滤,如 http://www.dai.ed.ac.uk/CVonline/LOCAL_COPIES/MANDUCHI1/Bilateral_Filtering.html 中所述
双边滤波器可以很好地减少不需要的噪声,同时保持边缘相当清晰。但是,与大多数过滤器相比,它非常慢。
@param src 源 8 位或浮点、1 通道或 3 通道图像。
@param dst 与 src 大小和类型相同的目标图像。
@param d 过滤期间使用的每个像素邻域的直径。如果它是非正数,则从 sigmaSpace 计算。
@param sigmaColor 在颜色空间中过滤 sigma。较大的参数值意味着像素邻域内更远的颜色(参见 sigmaSpace)将混合在一起,导致在较大的半等色区域。
@param sigmaSpace 在坐标空间中过滤 sigma。较大的参数值意味着更远的像素会相互影响,只要它们的颜色足够接近(参见 sigmaColor)。当 d>0 时,它指定邻域大小,而不考虑 sigmaSpace。否则,d 与 sigmaSpace 成正比。
@param borderType 用于外推图像外像素的边框模式,请参阅#BorderTypes
CV_EXPORTS_W void filter2D( InputArray src, OutputArray dst, int ddepth,
InputArray kernel, Point anchor = Point(-1,-1),
double delta = 0, int borderType = BORDER_DEFAULT );
该函数将任意线性滤波器应用于图像。支持就地操作。当光圈部分位于图像之外时,该函数会根据指定的边框模式对异常像素值进行插值。
@param src 输入图像。
@param dst 输出与 src 大小和通道数相同的图像。
@param ddepth 目标图像的所需深度,请参阅 @ref filter_depths “combinations”
@param kernel 卷积核(或者说是相关核),一个单通道浮点矩阵;如果要将不同的内核应用于不同的通道,请使用 split 将图像拆分为单独的颜色平面并单独处理它们。
@param anchor 内核的锚点,表示内核中过滤点的相对位置;锚点应位于内核中;默认值 (-1,-1) 表示锚点位于内核中心。
@param delta 在将过滤像素存储到 dst 之前添加到它们的可选值。
@param borderType 像素外推方法,参见#BorderTypes。不支持#BORDER_WRAP。
示例代码
filter.h
#pragma once
#include <iostream>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\core\core.hpp>
#include <opencv2\imgproc\imgproc.hpp>
using namespace std;
using namespace cv;
#define PROCESS_IMG_SUCESS 0
#define PROCESS_IMG_FAIL 1
namespace ImgEnhance
{
//滤波
class Filter
{
public:
Filter() { cout << "Filter is being created" << endl; } // 这是构造函数声明
~Filter() { cout << "Filter is being deleted" << endl; } // 这是析构函数声明
int MeanFilter(cv::Mat srcImage, cv::Mat &dstImage, int areaSize);//均值滤波
int GaussFilter(cv::Mat srcImage, cv::Mat &dstImage, int areaSize, int xValue, int yValue);//高斯滤波
int MedianFilter(cv::Mat srcImage, cv::Mat &dstImage, int areaSize);//中值滤波
int BilateralFilter(cv::Mat srcImage, cv::Mat &dstImage, int areaRadio, int limitValue, int unuseValue);//双边滤波
//高通滤波:边缘提取与增强//低通滤波:边缘平滑
int HighPassFilter(cv::Mat srcImage, cv::Mat &dstImage);//高通滤波
int LowPassFilter(cv::Mat srcImage, cv::Mat &dstImage);//低通滤波
};
}
filter.cpp
#include"filter.h"
int ImgEnhance::Filter::MeanFilter(cv::Mat srcImage, cv::Mat &dstImage, int areaSize)
{
if (srcImage.empty())
{
printf("cannot load!!\n");
return 1;
}
blur(srcImage, dstImage, Size(areaSize, areaSize), Point(-1, -1));
return 0;
}
int ImgEnhance::Filter::GaussFilter(cv::Mat srcImage, cv::Mat &dstImage, int areaSize, int xValue, int yValue)
{
if (srcImage.empty())
{
printf("cannot load!!\n");
return 1;
}
GaussianBlur(srcImage, dstImage, Size(areaSize, areaSize), xValue, yValue);
return 0;
}
int ImgEnhance::Filter::MedianFilter(cv::Mat srcImage, cv::Mat &dstImage, int areaSize)
{
if (srcImage.empty())
{
printf("cannot load!!\n");
return 1;
}
medianBlur(srcImage, dstImage, areaSize);
return 0;
}
int ImgEnhance::Filter::BilateralFilter(cv::Mat srcImage, cv::Mat &dstImage, int areaRadio, int limitValue, int unuseValue)
{
if (srcImage.empty())
{
printf("cannot load!!\n");
return 1;
}
bilateralFilter(srcImage, dstImage, areaRadio, limitValue, unuseValue);
return 0;
}
int ImgEnhance::Filter::HighPassFilter(cv::Mat srcImage, cv::Mat &dstImage)
{
if (srcImage.empty())
{
printf("cannot load!!\n");
return 1;
}
Mat highKernel;
highKernel = (Mat_<double>(3, 3) << -1, -1, -1, -1, 9, -1, -1, -1, -1);//高通滤波核
Mat grad;
filter2D(srcImage, grad, CV_16S, highKernel, Point(-1, -1));
convertScaleAbs(grad, dstImage);
return 0;
}
int ImgEnhance::Filter::LowPassFilter(cv::Mat srcImage, cv::Mat &dstImage)
{
if (srcImage.empty())
{
printf("cannot load!!\n");
return 1;
}
Mat lowKernel;
lowKernel = (Mat_<double>(3, 3) << 1.0 / 16, 2.0 / 16, 1.0 / 16, 2.0 / 16, 4.0 / 16, 2.0 / 16, 1.0 / 16, 2.0 / 16, 1.0 / 16);//低通滤波核
Mat grad;
filter2D(srcImage, grad, CV_16S, lowKernel, Point(-1, -1));
convertScaleAbs(grad, dstImage);
return 0;
}
test.cpp
#include"filter.h"
ImgEnhance::Filter ImgF;//滤波
int main()
{
// 读取源图像及判断
cv::Mat srcImage = cv::imread("flower.jpg");
if (!srcImage.data)
{
return 1;
}
/*cv::namedWindow("原始图", 0);
cv::imshow("原始图", srcImage);*/
// 转化为灰度图像
cv::Mat srcGray;
if (srcImage.channels() == 3)
{
cv::cvtColor(srcImage, srcGray, COLOR_RGB2GRAY);
}
else
{
srcGray = srcImage.clone();
}
cv::namedWindow("灰度图", 0);
cv::imshow("灰度图", srcGray);
//均值滤波
Mat meanImage;
int areaSizeMean=5;
ImgF.MeanFilter(srcGray, meanImage, areaSizeMean);
cv::namedWindow("均值滤波图", 0);
cv::imshow("均值滤波图", meanImage);
//高斯滤波
Mat gaussImage;
int areaSizeGauss = 5;
int xValue = 1;
int yValue = 1;
ImgF.GaussFilter(srcGray, gaussImage, areaSizeGauss, xValue, yValue);
cv::namedWindow("高斯滤波图", 0);
cv::imshow("高斯滤波图", gaussImage);
//中值滤波
Mat medianImage;
int areaSizeMedian = 5;
ImgF.MedianFilter(srcGray, medianImage, areaSizeMedian);
cv::namedWindow("中值滤波图", 0);
cv::imshow("中值滤波图", gaussImage);
//双边滤波
Mat bilateralImage;
int areaRadio = 1;
int limitValue = 1;
int unuseValue = 5;
ImgF.BilateralFilter(srcGray, bilateralImage, areaRadio, limitValue, unuseValue);
cv::namedWindow("双边滤波图", 0);
cv::imshow("双边滤波图", bilateralImage);
//高通滤波:边缘提取与增强//低通滤波:边缘平滑
Mat highpassImage;
ImgF.HighPassFilter(srcGray, highpassImage);//高通滤波
cv::namedWindow("高通滤波图", 0);
cv::imshow("高通滤波图", highpassImage);
//低通滤波
Mat lowpassImage;
ImgF.LowPassFilter(srcGray, lowpassImage);
cv::namedWindow("低通滤波图", 0);
cv::imshow("低通滤波图", lowpassImage);
cv::waitKey(0);
return 0;
}