在Android上玩转Opencv 系列: 7.基础知识 各种常见图像滤波用法

355 阅读6分钟

在 Android 版本的 OpenCV 中,图像滤波(Image Filtering)是图像处理的常见任务之一。滤波操作通常用于去噪、平滑、锐化图像等。OpenCV 提供了多种图像滤波方法,包括 平滑滤波模糊滤波边缘检测锐化等。

下面我将详细介绍 Android OpenCV 中几种常见的滤波方法以及它们的使用方式。

1. 均值滤波(Average Filtering)

均值滤波是最简单的图像滤波方法。它通过对邻域像素取平均值来实现图像平滑,去除噪声。其效果通常是模糊图像。

用法:

import org.opencv.core.Mat;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

public class MeanFilter {
    public void applyMeanFilter() {
        // 读取图像
        Mat image = Imgcodecs.imread("path/to/image.jpg");

        // 创建一个输出图像矩阵
        Mat outputImage = new Mat();

        // 应用均值滤波
        // 参数:源图像、输出图像、窗口大小(例如3x3)
        Imgproc.blur(image, outputImage, new org.opencv.core.Size(3, 3));

        // 保存滤波后的图像
        Imgcodecs.imwrite("path/to/output_image.jpg", outputImage);
    }
}

Imgproc.blur() :用于执行均值滤波。

参数

• image:输入图像。

• outputImage:输出图像。

• new org.opencv.core.Size(3, 3):窗口的大小,表示滤波器应用于图像时每次考虑 3x3 像素区域。

2. 高斯滤波(Gaussian Blur)

高斯滤波使用高斯函数加权邻域像素,可以较好地去除高斯噪声,并保留边缘信息。相比于均值滤波,它能够更平滑地处理图像。

用法:

import org.opencv.core.Mat;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

public class GaussianFilter {
    public void applyGaussianFilter() {
        // 读取图像
        Mat image = Imgcodecs.imread("path/to/image.jpg");

        // 创建一个输出图像矩阵
        Mat outputImage = new Mat();

        // 应用高斯滤波
        // 参数:源图像、输出图像、窗口大小、标准差
        Imgproc.GaussianBlur(image, outputImage, new org.opencv.core.Size(5, 5), 0);

        // 保存滤波后的图像
        Imgcodecs.imwrite("path/to/output_image.jpg", outputImage);
    }
}

Imgproc.GaussianBlur() :执行高斯滤波。

参数

• new org.opencv.core.Size(5, 5):高斯滤波器的大小。

• 0:标准差,如果为 0,OpenCV 会自动计算标准差。

3. 中值滤波(Median Filtering)

中值滤波是一种非线性滤波方法,它通过取邻域像素的中值来代替当前像素的值。它特别有效于去除椒盐噪声。

用法:

import org.opencv.core.Mat;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

public class MedianFilter {
    public void applyMedianFilter() {
        // 读取图像
        Mat image = Imgcodecs.imread("path/to/image.jpg");

        // 创建一个输出图像矩阵
        Mat outputImage = new Mat();

        // 应用中值滤波
        // 参数:源图像、输出图像、窗口大小(必须是奇数)
        Imgproc.medianBlur(image, outputImage, 5);

        // 保存滤波后的图像
        Imgcodecs.imwrite("path/to/output_image.jpg", outputImage);
    }
}

Imgproc.medianBlur() :执行中值滤波。

参数

• 5:窗口大小,必须是奇数。

4. 边缘检测(Edge Detection)

边缘检测是图像处理中重要的操作,常用的边缘检测算法是 Sobel 算子和 Canny 算子。

Sobel 边缘检测

Sobel 算子用于计算图像的梯度,通常用于检测图像的边缘。

import org.opencv.core.Mat;
import org.opencv.core.CvType;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

public class SobelEdgeDetection {
    public void applySobel() {


    Mat source=ImgHelper.bitmapToMatWithAlpha(bitmap);
    Mat gray = new Mat();
    Imgproc.cvtColor(source, gray, Imgproc.COLOR_BGR2GRAY);

    Mat gradX = new Mat();
    Mat gradY = new Mat();
    Mat absGradX = new Mat();
    Mat absGradY = new Mat();
    Mat edge = new Mat();
    // 计算 X 和 Y 方向梯度
    Imgproc.Sobel(gray, gradX, CvType.CV_16S, 1, 0, 3);
    Imgproc.Sobel(gray, gradY, CvType.CV_16S, 0, 1, 3);
    // 转换为无符号 8 位图像
    Core.convertScaleAbs(gradX, absGradX);
    Core.convertScaleAbs(gradY, absGradY);
    // 合并梯度
    Core.addWeighted(absGradX, 0.5, absGradY, 0.5, 0, edge);
    // 显示到 ImageView
    Bitmap bitmap4 = ImgHelper.getBitmapFromMat(edge,null);
    ((ImageView)findViewById(R.id.imageView4)).setImageBitmap(bitmap4);

    }
}

Imgproc.Sobel() :Sobel 边缘检测算子。

参数

• 1, 1:分别是 x 和 y 方向的导数阶数。

• 3:Sobel 算子的大小。

Canny 边缘检测

Canny 算子是另一种常用的边缘检测方法,它通过对图像进行高斯滤波、计算梯度、非最大抑制等步骤来检测边缘。

import org.opencv.core.Mat;
import org.opencv.core.CvType;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

public class CannyEdgeDetection {
    public void applyCanny() {
        // 读取图像并转换为灰度图像
        Mat image = Imgcodecs.imread("path/to/image.jpg", Imgcodecs.IMREAD_GRAYSCALE);

        // 创建一个输出图像矩阵
        Mat outputImage = new Mat();

        // 应用 Canny 边缘检测
        // 参数:源图像、输出图像、低阈值、高阈值
        Imgproc.Canny(image, outputImage, 50, 150);

        // 保存边缘检测后的图像
        Imgcodecs.imwrite("path/to/output_image.jpg", outputImage);
    }
}

Imgproc.Canny() :Canny 边缘检测算法。

参数

• 50 和 150:低阈值和高阈值,用于检测边缘。

5. 锐化滤波(Sharpening)

锐化滤波通常用于增强图像的细节。锐化滤波通过对图像应用一个增强边缘的卷积核来实现。

import org.opencv.core.Mat;
import org.opencv.core.CvType;
import org.opencv.core.MatOfFloat;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

public class SharpeningFilter {
    public void applySharpening() {
        // 读取图像
        Mat image = Imgcodecs.imread("path/to/image.jpg");

        // 创建一个输出图像矩阵
        Mat outputImage = new Mat();

        // 创建一个锐化滤波器(卷积核)
        Mat kernel = new Mat(3, 3, CvType.CV_32F);
        kernel.put(0, 0, 0, -1, 0, -1, 5, -1, 0, -1, 0);

        // 应用锐化滤波
        Imgproc.filter2D(image, outputImage, image.depth(), kernel);

        // 保存锐化后的图像
        Imgcodecs.imwrite("path/to/output_image.jpg", outputImage);
    }
}

Imgproc.filter2D() :执行卷积操作。

卷积核:通过卷积核来增强图像边缘。

6. 图像拉普拉斯滤波(Laplacian Filter)

拉普拉斯滤波器是一种用于图像锐化和边缘检测的滤波器。它基于图像的二阶导数,用于检测图像中的边缘和轮廓。

用法:

import org.opencv.core.Mat;
import org.opencv.core.CvType;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

public class LaplacianFilter {
    public void applyLaplacianFilter() {
        // 读取图像
        Mat image = Imgcodecs.imread("path/to/image.jpg", Imgcodecs.IMREAD_GRAYSCALE);

        // 创建一个输出图像矩阵
        Mat outputImage = new Mat();

        // 应用拉普拉斯滤波
        // 参数:源图像、输出图像、深度(通常为CV_16S)、孔径大小(例如3x3)
        Imgproc.Laplacian(image, outputImage, CvType.CV_16S, 3);

        // 将图像转回正常的显示格式
        Mat absOutput = new Mat();
        Core.convertScaleAbs(outputImage, absOutput);

        // 保存拉普拉斯滤波后的图像
        Imgcodecs.imwrite("path/to/output_image.jpg", absOutput);
    }
}

Imgproc.Laplacian() :应用拉普拉斯滤波器。

参数

• CvType.CV_16S:指定输出图像的类型为 16 位深度。

• 3:表示使用 3x3 的卷积核。

使用拉普拉斯滤波器的结果通常是边缘的高亮显示,特别适合进行边缘检测或者增强图像的细节。

7. 自定义卷积核滤波(Custom Filter)

除了 OpenCV 提供的标准滤波方法,你还可以自定义卷积核(滤波器),来实现特定的图像处理效果。自定义滤波器可以通过 Imgproc.filter2D() 函数应用。

用法:

import org.opencv.core.Mat;
import org.opencv.core.CvType;
import org.opencv.core.MatOfFloat;
import org.opencv.core.Size;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.core.Mat;

public class CustomFilter {
    public void applyCustomFilter() {
        // 读取图像
        Mat image = Imgcodecs.imread("path/to/image.jpg");

        // 创建一个输出图像矩阵
        Mat outputImage = new Mat();

        // 自定义卷积核(3x3)
        float[] kernelArray = {
            0f, -1f, 0f,
            -1f, 5f, -1f,
            0f, -1f, 0f
        };
        Mat kernel = new Mat(3, 3, CvType.CV_32F);
        kernel.put(0, 0, kernelArray);

        // 应用自定义卷积核
        Imgproc.filter2D(image, outputImage, image.depth(), kernel);

        // 保存应用自定义卷积核后的图像
        Imgcodecs.imwrite("path/to/output_image.jpg", outputImage);
    }
}

Imgproc.filter2D() :应用自定义卷积核滤波。

kernel.put() :将自定义卷积核数组放入 Mat 对象中。

kernelArray:一个示例的锐化滤波卷积核(增强边缘)。

8. 双边滤波(Bilateral Filter)

双边滤波是一种同时考虑空间距离和像素强度差异的滤波方法,它可以在去噪的同时保留边缘信息。适合于图像去噪和图像平滑,尤其是在图像处理时需要同时保持边缘清晰的情况下。

用法:

import org.opencv.core.Mat;
import org.opencv.core.Size;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

public class BilateralFilter {
    public void applyBilateralFilter() {
        // 读取图像
        Mat image = Imgcodecs.imread("path/to/image.jpg");

        // 创建一个输出图像矩阵
        Mat outputImage = new Mat();

        // 应用双边滤波
        // 参数:源图像、输出图像、直径、色彩空间的标准差、坐标空间的标准差
        Imgproc.bilateralFilter(image, outputImage, 15, 80, 80);

        // 保存双边滤波后的图像
        Imgcodecs.imwrite("path/to/output_image.jpg", outputImage);
    }
}

Imgproc.bilateralFilter() :应用双边滤波。

参数

• 15:滤波器的直径。

• 80, 80:色彩空间和坐标空间的标准差。

双边滤波通常用于去除图像中的噪声而不模糊图像的边缘。

lvbo.gif

总结:

在 Android OpenCV 中,常见的图像滤波方法有:

  1. 均值滤波:Imgproc.blur()

  2. 高斯滤波:Imgproc.GaussianBlur()

  3. 中值滤波:Imgproc.medianBlur()

  4. 边缘检测

• Sobel 边缘检测:Imgproc.Sobel()

• Canny 边缘检测:Imgproc.Canny()

  1. 锐化滤波:Imgproc.filter2D()(通过自定义卷积核)

  2. 拉普拉斯滤波:Imgproc.Laplacian()

  3. 双边滤波:Imgproc.bilateralFilter()

  4. 自定义卷积核:Imgproc.filter2D()(适用于自定义滤波器)

通过这些滤波操作,你可以对图像进行各种处理,比如去噪、锐化、平滑、边缘检测等。你可以根据需求选择合适的滤波方法,组合使用不同的滤波器来处理图像。