6:OpenCV—图像滤波

news2025/5/24 1:50:44

过滤图像和视频

图像滤波是一种邻域运算,其中输出图像中任何给定像素的值是通过对相应输入像素附近的像素值应用某种算法来确定的。该技术通常用于平滑、锐化和检测图像和视频的边缘。
让我们了解在讨论图像过滤技术、内核和卷积时使用的一些术语的含义。

内核

内核是一个具有奇数高度和奇数宽度的矩阵。它也被称为卷积矩阵、掩码或滤波器。内核根据其值分布命名。内核用于在图像过滤操作中定义像素的邻域。一些流行的内核是规范化盒过滤器,高斯内核,拉普拉斯内核,边缘检测内核等。内核可以定义不同的大小。但是大内核会导致较长的处理时间。

这是一个 3 x 3 规范化框筛选器。此内核用于均匀平滑(模糊)。

这是一个 5 x 5 规范化框筛选器。该内核也用于均匀平滑。同样,您可以创建具有任何大小的归一化框过滤器,以用于均匀平滑。

这是一个 3 x 3 高斯核,用于高斯平滑(模糊)。

这是一个 5 x 5 高斯核,用于高斯平滑(模糊)。同样,您可以创建任何大小的高斯核。核的值分布应使用 2-D 高斯函数计算。

x, y 是原点位于中心的核的坐标。(即内核中心元素处的 x = 0 和 y = 0。**σ**是高斯分布的标准差。对于较大的标准差,需要更大的核才能准确执行高斯平滑。以下 5 x 5 高斯核的标准差为 1。

卷积

卷积是对图像执行的数学运算,方法是在整个图像上滑动内核,并根据内核的值和原始图像的重叠像素值计算每个像素的新值。


C22 = (K11 x A11 + K12 x A12 + K13 x A13) + (K21 x A21 + K22 x A22 + K23 x A23) + (K31 x A31 + K32 x A32 + K33 x A33)
C23 = (K11 x A12 + K12 x A13 + K13 x A14) + (K21 x A22 + K22 x A23 + K23 x A24) + (K31 x A32 + K32 x A33 + K33 x A34)
C24 = (K11 x A13 + K12 x A14 + K13 x A15) + (K21 x A23 + K22 x A24 + K23 x A25) + (K31 x A33 + K32 x A34 + K33 x A35)

C32 = (K11 x A21 + K12 x A22 + K13 x A23) + (K21 x A31 + K22 x A32 + K23 x A33) + (K31 x A41 + K32 x A42 + K33 x A43)
C33 = (K11 x A22 + K12 x A23 + K13 x A24) + (K21 x A32 + K22 x A33 + K23 x A34) + (K31 x A42 + K32 x A43 + K33 x A44)

以同样的方式C34,可以在卷积图像中计算。但是卷积图像边界中的其他值(例如 C11、C12 等)不能以相同的方式计算,因为内核在边界处与原始图像部分重叠。因此,应计算非重叠的不存在的像素值,以确定卷积图像边界处的像素值。

均匀模糊

均匀模糊是平滑图像的最简单方法。它也被称为均匀平滑、均匀过滤和框模糊。在此技术中,每个像素值计算为内核定义的像素邻域的平均值。

均匀模糊中使用的内核称为归一化框滤波器。您可以根据需要为此内核定义任何大小。但最好定义宽度和高度为奇数大小的方形核。在下图中,我显示了 3 x 3 和 5 x 5 规范化框筛选器。

3x3 规范化框筛选器
5 x 5 标准化框筛选器

您必须选择正确大小的内核来定义每个像素的邻域。如果太大,图像的小特征可能会消失,图像看起来会模糊。如果它太小,则无法消除图像中的噪点。

使用OpenCV的图像上的均匀模糊

#include <QCoreApplication>
#include "opencv2/opencv.hpp"
#include "opencv/highgui.h"

using namespace std;
using namespace cv;

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    // 读取图像
    Mat image = imread("D:/Gerry/project/opencvproj/singleandslot/OpenCV-2/ImageAndVideoHandle/resources/lean_guitar.jpg");
    // 创建3X3和5X5的均匀滤波核并对读取图像进行均匀滤波处理
    Mat blur_3X3_img;
    Mat blur_5X5_img;
    blur(image, blur_3X3_img, Size(3, 3));
    blur(image, blur_5X5_img, Size(5, 5));

    string orignWd = "原始图像";
    string blurWd_3X3 = "3X3处理的图像";
    string blurWd_5X5 = "5X5处理的图像";

    namedWindow(orignWd);
    namedWindow(blurWd_3X3);
    namedWindow(blurWd_5X5);

    // 显示出来图像到窗口
    imshow(orignWd, image);
    imshow(blurWd_3X3, blur_3X3_img);
    imshow(blurWd_5X5, blur_5X5_img);

    waitKey(0);

    destroyAllWindows();


    return a.exec();
}
原始图像
使用 3 x 3 归一化框滤镜模糊图像
使用 5 x 5 归一化框滤镜模糊图像

代码解释


//Blur the image with 3x3 kernel
Mat image_blurred_with_3x3_kernel;
blur(image, image_blurred_with_3x3_kernel, Size(3, 3));

上述函数在原始图像上使用 3 x 3 归一化框滤镜执行均匀平滑/模糊操作,并将平滑的图像存储在 image_blurred_with_3x3_kernel Mat 对象中。原始图像中的每个通道都是独立处理的。


//Blur the image with 5x5 kernel
Mat image_blurred_with_5x5_kernel;
blur(image, image_blurred_with_5x5_kernel, Size(5, 5));

上述函数使用5 x 5归一化框滤镜对原始图像执行均匀平滑/模糊操作,并将平滑的图像存储在*image_blurred_with_5x5_kernel* Mat对象中。原始图像中的每个通道都是独立处理的。


//Define names of the window
String window_name = "The Guitar"; 
String window_name_blurred_with_3x3_kernel = "The Guitar Blurred with 3 x 3 Kernel";
String window_name_blurred_with_5x5_kernel = "The Guitar Blurred with 5 x 5 Kernel";

// Create a window with above names
namedWindow(window_name);
namedWindow(window_name_blurred_with_3x3_kernel);
namedWindow(window_name_blurred_with_5x5_kernel);

// Show our images inside the created windows.
imshow(window_name, image); 
imshow(window_name_blurred_with_3x3_kernel, image_blurred_with_3x3_kernel);
imshow(window_name_blurred_with_5x5_kernel, image_blurred_with_5x5_kernel);

上面的代码段创建窗口并在其中显示图像。

视频上的均匀模糊

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

using namespace cv;
using namespace std;

int main(int argc, char* argv[])
{
    //open the video file for reading
    VideoCapture cap("D:/Gerry/project/opencvproj/singleandslot/OpenCV-2/ImageAndVideoHandle/resources/点云应用.mp4");

    // if not success, exit program
    if (cap.isOpened() == false)
    {
        qDebug() << "打开不读取的视频文件" << endl;
        cin.get(); //wait for any key press
        return -1;
    }



    //Define names of the window
    String window_name_of_original_video = "Original Video";
    String window_name_of_video_blurred_with_5x5_kernel = "Video Blurred with 5 x 5 Kernel";

    // Create a window with above names
    namedWindow(window_name_of_original_video, WINDOW_NORMAL);
    namedWindow(window_name_of_video_blurred_with_5x5_kernel, WINDOW_NORMAL);

    while (true)
    {
        Mat frame;
        bool bSuccess = cap.read(frame); // read a new frame from video
        if (bSuccess == false)
        {
            qDebug() << "Found the end of the video" << endl;
            break;
        }

        //Blur the frame with 5x5 kernel
        Mat frame_blurred_with_5x5_kernel;
        blur(frame, frame_blurred_with_5x5_kernel, Size(5, 5));

        //show the frames in the created windows
        imshow(window_name_of_original_video, frame);
        imshow(window_name_of_video_blurred_with_5x5_kernel, frame_blurred_with_5x5_kernel);

        //wait for for 10 ms until any key is pressed.
        //If the 'Esc' key is pressed, break the while loop.
        //If the any other key is pressed, continue the loop
        //If any key is not pressed withing 10 ms, continue the loop
        if (waitKey(10) == 27)
        {
            qDebug() << "按下ESC键,停止视频处理" << endl;
            break;
        }
    }

    return 0;

}

高斯模糊

所谓模糊,可以理解成每一个像素都取周边像素的平均值。

高斯模糊/平滑是最常用的平滑技术,用于消除图像和视频中的噪点。在这种技术中,图像应该与高斯核卷积以产生平滑的图像。

您可以根据需要定义内核的大小。但是,在X和Y方向上高斯分布的标准差应仔细选择,考虑核的大小,以使核的边缘接近于零。在这里,我展示了 3 x 3 和 5 x 5 高斯核。

3 x 3 高斯核
5 x 5 高斯核

您必须选择正确大小的内核来定义每个像素的邻域。如果太大,图像的小特征可能会消失,图像看起来会模糊。如果它太小,则无法消除图像中的噪点。

3X3高斯模型过程

  1. 定义高斯函数: G(x, y) = (1 / (2 * π * σ^2)) * e^(-(x^2 + y^2) / (2 * σ^2)) 其中,x和y是偏移量,σ是高斯分布的标准差。

  2. 计算元素的值: 对于一个3x3的高斯核,中心元素位于(0, 0),即(行偏移量, 列偏移量) = (0, 0)。 将(x, y)代入高斯函数的公式中,可得到每个元素的值。

G(-1, -1) = (1 / (2 * π * σ^2)) * e^(-((-1)^2 + (-1)^2) / (2 * σ^2))

G(-1, 0) = (1 / (2 * π * σ^2)) * e^(-((-1)^2 + 0^2) / (2 * σ^2))

G(-1, 1) = (1 / (2 * π * σ^2)) * e^(-((-1)^2 + 1^2) / (2 * σ^2))

G(0, -1) = (1 / (2 * π * σ^2)) * e^(-(0^2 + (-1)^2) / (2 * σ^2))

G(0, 0) = (1 / (2 * π * σ^2)) * e^(-(0^2 + 0^2) / (2 * σ^2))

G(0, 1) = (1 / (2 * π * σ^2)) * e^(-(0^2 + 1^2) / (2 * σ^2))

G(1, -1) = (1 / (2 * π * σ^2)) * e^(-(1^2 + (-1)^2) / (2 * σ^2))

G(1, 0) = (1 / (2 * π * σ^2)) * e^(-(1^2 + 0^2) / (2 * σ^2))

G(1, 1) = (1 / (2 * π * σ^2)) * e^(-(1^2 + 1^2) / (2 * σ^2))

  1. 归一化: 将所有元素值相加并除以总和:G(-1, -1) + G(-1, 0) + G(-1, 1) + G(0, -1) + G(0, 0) + G(0, 1) + G(1, -1) + G(1, 0) + G(1, 1)

请注意,归一化是将所有元素的和调整为1,而不是单个元素的值。对于标准的高斯核,σ的值通常取1。代入σ=1进行计算,我们可以得到一个准确的3x3高斯核:

1/16 2/16 1/16

2/16 4/16 2/16

1/16 2/16 1/16

这是一个经过归一化处理的3x3高斯核,它满足所有元素之和为1。

对图像进行高斯模糊

#include <QCoreApplication>
#include "opencv2/opencv.hpp"

using namespace std;
using namespace cv;

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    // 读取图像
    Mat image = imread("D:/Gerry/project/opencvproj/singleandslot/OpenCV-2/ImageAndVideoHandle/resources/lean_guitar.jpg");
    // 创建3X3和5X5的高斯滤波核并对读取图像进行高斯滤波处理
    Mat blur_3X3_img;
    Mat blur_5X5_img;
    GaussianBlur(image, blur_3X3_img, Size(3, 3), 0);
    GaussianBlur(image, blur_5X5_img, Size(9, 9), 0);

    string orignWd = "原始图像";

    string blurWd_3X3 = "3X3处理的图像";
    string blurWd_5X5 = "5X5处理的图像";

    namedWindow(orignWd);
    namedWindow(blurWd_3X3);
    namedWindow(blurWd_5X5);

    // 显示出来图像到窗口
    imshow(orignWd, image);
    imshow(blurWd_3X3, blur_3X3_img);
    imshow(blurWd_5X5, blur_5X5_img);

    waitKey(0);

    destroyAllWindows();


    return a.exec();
}
原始图像
使用 3 x 3 高斯核模糊图像
使用 5 x 5 高斯核模糊图像
代码解释

/Blur the image with 3x3 Gaussian kernel
Mat image_blurred_with_3x3_kernel;
GaussianBlur(image, image_blurred_with_3x3_kernel, Size(3, 3), 0);

上述函数在原始图像上使用 3 x 3 高斯滤波器执行高斯模糊/平滑操作,并将平滑的图像存储在 image_blurred_with_3x3_kernel Mat 对象中。原始图像中的每个通道都是独立处理的。内核的宽度和高度应该是奇数。高斯分布的 X 方向和 Y 方向的标准偏差将根据核的大小计算。


//Blur the image with 5x5 Gaussian kernel
Mat image_blurred_with_5x5_kernel;
GaussianBlur(image, image_blurred_with_5x5_kernel, Size(5, 5), 0);

上述函数使用5 x 5高斯滤波器对原始图像执行高斯模糊/平滑操作,并将平滑的图像存储在image_blurred_with_5x5_kernel Mat对象中。原始图像中的每个通道都是独立处理的。内核的宽度和高度应该是奇数。高斯分布的 X 方向和 Y 方向的标准偏差将根据核的大小计算。


//Define names of the windows
String window_name = "Lotus";
String window_name_blurred_with_3x3_kernel = "Lotus Blurred with 3 x 3 Gaussian Kernel";
String window_name_blurred_with_5x5_kernel = "Lotus Blurred with 5 x 5 Gaussian Kernel";

// Create windows with above names
namedWindow(window_name);
namedWindow(window_name_blurred_with_3x3_kernel);
namedWindow(window_name_blurred_with_5x5_kernel);

// Show our images inside the created windows.
imshow(window_name, image);
imshow(window_name_blurred_with_3x3_kernel, image_blurred_with_3x3_kernel);
imshow(window_name_blurred_with_5x5_kernel, image_blurred_with_5x5_kernel);

上面的代码段创建窗口并在其中显示图像。

视频上的高斯模糊

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

using namespace cv;
using namespace std;

int main(int argc, char* argv[])
{
    //读取视频文件内容
    VideoCapture cap("D:/Gerry/project/opencvproj/singleandslot/OpenCV-2/ImageAndVideoHandle/resources/点云应用.mp4");

    //定义窗口名称
    String window_name_of_original_video = "原始视频";
    String window_name_of_video_blurred_with_5x5_kernel = "5X5高斯核处理的图像";

    // 根据前面的窗口标题创建窗口对象
    namedWindow(window_name_of_original_video, WINDOW_NORMAL);
    namedWindow(window_name_of_video_blurred_with_5x5_kernel, WINDOW_NORMAL);

    while (true)
    {
        Mat frame;
        // 从视频中读取一帧
        bool bSuccess = cap.read(frame);
        if (bSuccess == false)
        {
            cout << "视频已经读取完成" << endl;
            break;
        }

        //创建当前帧的5X5高斯核来平滑图像
        Mat frame_blurred_with_5x5_kernel;
        GaussianBlur(frame, frame_blurred_with_5x5_kernel, Size(5, 5), 0);

        //把当前帧平滑处理的图像显示到对应的窗口上
        imshow(window_name_of_original_video, frame);
        imshow(window_name_of_video_blurred_with_5x5_kernel, frame_blurred_with_5x5_kernel);

        // 等待10秒按下ESC键退出程序
        if (waitKey(10) == 27)
        {
            cout << "按下ESC键,停止视频直播" << endl;
            break;
        }
    }

    return 0;

}

反转图像

反转图像就像拍摄图像的负片。





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

using namespace cv;
using namespace std;

int main()
{
    //定义原图像
    Mat color;
    //定义灰度图像,灰度图像反转后的图像
    Mat gray, grayDst;
    // 定义图像的高度和宽度
    int height, width;
    int i, j;

    //载入图片
    color = imread("D:/Gerry/project/opencvproj/singleandslot/OpenCV-2/ImageAndVideoHandle/resources/Car.jpg");
    if (color.empty())
    {
        qDebug() << "读取错误" << endl;
        return -1;
    }

    //获取图像信息
    height = color.rows;

    //列项要乘通道数
    width = color.cols * color.channels();

    qDebug()  << "彩色图片宽:" << color.cols << ", 高:" << color.rows << ",通道数:" << color.channels() << endl;
    qDebug()  << "实际宽:" << width << endl << endl << endl;

    // 定义窗口名称
    string originColor = "原彩色原图";
    string reverseColor = "反转彩色图像";

    //创建窗口
    namedWindow(originColor, WINDOW_AUTOSIZE);
    namedWindow(reverseColor, WINDOW_AUTOSIZE);

    //显示原图
    imshow(originColor, color);

    //彩色图像反转
    //算法:反转后的像素a = 255 - a
    for (i = 0; i < height; i++)
    {
        for (j = 0; j < width; j++)
        {
            color.at<uchar>(i, j) = 255 - color.at<uchar>(i, j);   //对每一个像素反转
        }
    }

    //保存反色后的图片
    cv::imwrite("outputColor.jpg", color);
    //显示反相图片
    imshow(reverseColor, color);

    //---------------------灰度图像反转------------------
    //灰度化,由原图获得灰度图像
    cvtColor(color, gray, COLOR_BGR2GRAY);
    //保存灰度图片
    cv::imwrite("gray.jpg", gray);
    // 获取灰度图的高
    height = gray.rows;
    //列项乘通道数
    // 获取灰度图的宽度
    width = gray.cols * gray.channels();

    qDebug()  << "灰度图片宽:" << gray.cols << ", 高:" << gray.rows << ",通道数:" << gray.channels() << endl;
    qDebug()  << "实际宽:" << width << endl << endl << endl;

    string grayTitle = "原灰度窗口";
    string grayReverseTitle = "反转灰度窗口";

    namedWindow(grayTitle, WINDOW_AUTOSIZE);
    namedWindow(grayReverseTitle, WINDOW_AUTOSIZE);

    //显示灰度图像
    imshow(grayTitle, gray);

    //灰度图像反转
    //算法:反转后的像素a = 255 - a
    grayDst = gray.clone();
    for (int i = 0; i < gray.rows; i++)
    {
        for (int j = 0; j < gray.cols; j++)
        {
            //灰度反转
            grayDst.at<uchar>(i, j) = 255 - gray.at<uchar>(i, j);
        }
    }
    //显示反转图像
    imshow(grayReverseTitle, grayDst);

    //保存反色后的图片
    imwrite("outputGray.jpg", grayDst);

    //暂停,保持图像显示
    waitKey(0);

    return 0;
}

基于opencv的五种滤波方法

方框滤波–> boxFilter函数来实现 –>线性滤波

均值滤波(邻域平均滤波)–> blur函数 –>线性滤波

高斯滤波–>GaussianBlur函数 –>线性滤波

中值滤波–>medianBlur函数 –>非线性滤波

双边滤波–>bilateralFilter函数 –>非线性滤波

方框滤波


boxFilter( InputArray src, OutputArray dst, int ddepth,
                Size ksize, Point anchor = Point(-1,-1),
                bool normalize = true,
                int borderType = BORDER_DEFAULT )
  • src:输入图像
  • dst:输出图像
  • ddepth:输入图像的深度,-1 代表使用原图深度
  • ksize: 滤波内核的大小。一般这样写Size(w, h)来表示内核的大小,Size(10, 10)就表示 10x10 的核大小
  • anchor = Point(-1,-1) :表示锚点(即被平滑的那个点),注意他有默认值Point(-1,-1) 如果这个点坐标是负值的话,就表示取核的中心为锚点,所以默认值Point(-1,-1)表示这个锚点在核的中心。
  • normalize = true:默认值为true,一个标识符,表示内核是否被其区域归一化(normalized)了
  • borderType = BORDER_DEFAULT:用于推断图像外部像素的某种边界模式。有默认值BORDER_DEFAULT,我们一般不去管它。

均值滤波


blur( InputArray src,OutputArray dst, Size ksize, 
      Point anchor = Point(-1,-1),
      int borderType = BORDER_DEFAULT)
  • src:输入图像 。
  • dst:输出图像 。
  • ksize:内核大小 ,一般用 Size(w,h),w 为宽度,h 为深度。
  • anchor:被平滑的点,表示取 内核中心 ,默认值 Point(-1,-1)。
  • boderType:推断图像外部像素的某种边界模式。默认值 BORDER_DEFAULT

高斯滤波

1
2
3
GaussianBlur( InputArray src, OutputArray dst, Size ksize,
                   double sigmaX, double sigmaY = 0,
                   int borderType = BORDER_DEFAULT )
  • src:输入图像 。
  • dst:输出图像 。
  • ksize:ksize.width 和 ksize.height 可以不同,但他们都必须为正数和奇数,或者为0,可由 sigma 计算而来
  • sigmaX:高斯核函数在 X 方向的的标准差
  • sigmaY:高斯核函数在 Y 方向的的标准差

若 sigmaY 为零,就将它设为 sigmaX;若 sigmaX 和 sigmaY 都是0,那么就由 ksize.width 和 ksize.height 计算出来

中值滤波

medianBlur(InputArray src,OutputArray dst,int ksize)
  • src:输入图像 。
  • dst:输出图像 。
  • ksize:孔径的线性尺寸,这个参数必须是大于1 的奇数

双边滤波


bilateralFilter(InputArray src,OutputArray dst, int d, 
                double sigmaColor,double sigmaSpace, 
                int borderType=BORDER_DEFAULT) 
  • src: 输入图像,可以是Mat类型,图像必须是8位或浮点型单通道、三通道的图像。
  • dst: 输出图像,和原图像有相同的尺寸和类型。
  • d: 表示在过滤过程中每个像素邻域的直径范围。如果这个值是非正数,则函数会从第五个参数sigmaSpace计算该值。
  • sigmaColor: 颜色空间过滤器的sigma值,这个参数的值月大,表明该像素邻域内有月宽广的颜色会被混合到一起,产生较大的半相等颜色区域。
  • sigmaSpace: 坐标空间中滤波器的sigma值,如果该值较大,则意味着颜色相近的较远的像素将相互影响,从而使更大的区域中足够相似的颜色获取相同的颜色。当d>0时,d指定了邻域大小且与sigmaSpace五官,否则d正比于sigmaSpace.
  • borderType=BORDER_DEFAULT: 用于推断图像外部像素的某种边界模式,有默认值BORDER_DEFAULT.

上面所有滤波的综合案例



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

using namespace cv;
using namespace std;

int main()
{
    // 读取图像
    Mat srcImg = imread("D:/Gerry/project/opencvproj/singleandslot/OpenCV-2/ImageAndVideoHandle/resources/lean_guitar.jpg");
    // 定义六个窗口的名称
    string srcTitle = "原始图像";
    string boxFilterTitle = "方框滤波";
    string blurTitle = "均值滤波";
    string gaussianTitle = "高斯滤波";
    string medianTitle = "中值滤波";
    string bilateralTitle = "双边滤波";

    // 创建6个窗口
    namedWindow(srcTitle, WINDOW_NORMAL);
    namedWindow(boxFilterTitle, WINDOW_NORMAL);
    namedWindow(blurTitle, WINDOW_NORMAL);
    namedWindow(gaussianTitle, WINDOW_NORMAL);
    namedWindow(medianTitle, WINDOW_NORMAL);
    namedWindow(bilateralTitle, WINDOW_NORMAL);

    // 显示原图
    imshow(srcTitle, srcImg);

    // 方框滤波处理
    Mat boxFilterImg;
    // 首先进行方框滤波处理
    boxFilter(srcImg, boxFilterImg, srcImg.depth(), Size(5,5));
    // 显示到对应窗口上
    imshow(boxFilterTitle, boxFilterImg);

    // 均值滤波处理
    Mat blurImg;
    // 首先进行均值滤波处理
    blur(srcImg, blurImg, Size(5,5));
    // 显示到对应窗口上
    imshow(blurTitle, blurImg);

    // 高斯率处理
    Mat gaussianImg;
    // 首先进行均值滤波处理
    GaussianBlur(srcImg, gaussianImg, Size(5,5), 0);
    // 显示到对应窗口上
    imshow(gaussianTitle, gaussianImg);

    // 中值滤波处理
    Mat medianImg;
    // 首先进行均值滤波处理
    medianBlur(srcImg, medianImg, 9);
    // 显示到对应窗口上
    imshow(medianTitle, medianImg);

    // 双边滤波处理
    Mat bilateralImg;
    // 首先进行均值滤波处理
    bilateralFilter(srcImg, bilateralImg, 11, 21, 19);
    // 显示到对应窗口上
    imshow(bilateralTitle, bilateralImg);

    waitKey(0);

    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2384269.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

pytorch语法学习

启动 python main.py --config llve.yml --path_y test -i output

5:OpenCV—图像亮度、对比度变换

1.更改图像和视频的亮度 更改亮度 更改图像的亮度是常用的点操作。在此操作中&#xff0c;图像中每个像素的值应增加/减少一个常数。要更改视频的亮度&#xff0c;应对视频中的每一帧执行相同的操作。 如果要增加图像的亮度&#xff0c;则必须为图像中的每个像素添加一些正常…

Oracle 的V$ACTIVE_SESSION_HISTORY 视图

Oracle 的V$ACTIVE_SESSION_HISTORY 视图 V$ACTIVE_SESSION_HISTORY显示数据库中的 Sampled Session 活动。 它包含每秒拍摄一次的活动数据库会话的快照。如果数据库会话位于 CPU 上或正在等待不属于等待类的事件&#xff0c;则认为该会话处于活动状态。请参阅 view 以了解有…

【Python 算法零基础 4.排序 ② 冒泡排序】

目录 一、引言 二、算法思想 三、时间复杂度和空间复杂度 1.时间复杂度 2.空间复杂度 四、冒泡排序的优缺点 1.算法的优点 2.算法的缺点 五、实战练习 88. 合并两个有序数组 算法与思路 ① 合并数组 ② 冒泡排序 2148. 元素计数 算法与思路 ① 排序 ② 初始化计数器 ③ 遍历数组…

Python:操作Excel设置行高和列宽

Python 操作 Excel:轻松设置行高与列宽 📊✨ 在处理 Excel 表格时,除了正确展示数据本身,合理设置行高与列宽也是提升可读性和专业度的关键因素。本文将带你了解如何使用 Python 的 openpyxl 库,优雅地控制 Excel 表格的排版布局,实现行高、列宽的灵活设置与自动适配! …

docker-volume-backup 备份 ragflow volumes

自定义项目名称 这里我自定义了 ragflow 项目的名称&#xff0c;修改 .env&#xff0c;添加环境配置 # 自定义项目名称 COMPOSE_PROJECT_NAMEragflow创建备份脚本配置文件 在 ragflow/docker 目录下创建文件 docker-compose-backup.yml version: 3services:backup:image: o…

Axure设计数字乡村可视化大屏:从布局到交互的实战经验分享

乡村治理正从传统模式向“数据驱动”转型。数字乡村可视化大屏作为数据展示的核心载体&#xff0c;不仅能直观呈现乡村发展全貌&#xff0c;还能为决策提供科学依据。本文以Axure为工具&#xff0c;结合实际案例&#xff0c;分享如何从零设计一个功能完备、交互流畅的数字乡村大…

算法第26天 | 贪心算法、455.分发饼干、376. 摆动序列、 53. 最大子序和

弹性算法理论基础 想清楚 局部最优 是什么&#xff0c;如果可以推导出全局最优&#xff0c;那就是正确的贪心算法 455. 分发饼干 题目 思路与解法 class Solution:def findContentChildren(self, g: List[int], s: List[int]) -> int:res 0i 0j 0g.sort()s.sort()whi…

PDF处理控件Aspose.PDF教程:以编程方式将 PDF 导出为 JPG

在本节中&#xff0c;我们将探讨如何使用 Aspose.PDF 库将 PDF 文档转换为 JPG 图像。Aspose.PDF 是一个功能强大且用途广泛的库&#xff0c;专为需要以编程方式处理 PDF 文件的开发人员而设计。它提供了丰富的功能&#xff0c;可用于跨多个平台创建、编辑和转换 PDF 文档。其主…

AI大模型应用之评测篇

在看到公司对于AI 工程师 的岗位要求 &#xff1a;“能够熟练使用各种自动化评测工具与方法&#xff0c;对AI 模型的输出进行有效评估” 时&#xff0c;其实比较疑惑&#xff0c;这个是对大模型能力例如像Deepseek ,GPT-4 ,千问&#xff0c;LLAMA这些模型的能力评测&#xff0c…

力扣小题, 力扣113.路径总和II力扣.111二叉树的最小深度 力扣.221最大正方形力扣5.最长回文子串更加优秀的算法:中心扩展算法

目录 力扣113.路径总和II 力扣.111二叉树的最小深度 力扣.221最大正方形 力扣5.最长回文子串 更加优秀的算法:中心扩展算法 力扣113.路径总和II 这道题&#xff0c;让我明白回溯了到底啥意思 之前我找的时候&#xff0c;我一直在想&#xff0c;如果可以&#xff0c;请你对比…

el-form elform 对齐方式调整

如下页面表单&#xff0c;展示后就很丑。 页面表单&#xff0c;有时候我们想着最左侧的应该合理整齐的左对齐&#xff0c;右侧的表单都是右对齐&#xff0c;这样页面看起来会整洁很多。 <el-form class"w-100 a_form" style"padding: 0 15px 0px 15px"…

JESD204 ip核使用与例程分析(二)

JESD204 ip核使用与例程分析(二) JESD204时钟方案专用差分时钟对例程分析jesd204_0_transport_layer_demapperjesd204_0_sig_chkjesd204_0_clockingjesd204_0 ip核port寄存器AXI-LITE寄存器配置jesd204_phy ip核JESD204时钟方案 图3-1所示为最通用、灵活的时钟解决方案。在图…

50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | Blurry Loading (毛玻璃加载)

&#x1f4c5; 我们继续 50 个小项目挑战&#xff01;—— Blurry Loading 组件 仓库地址&#xff1a;https://github.com/SunACong/50-vue-projects 项目预览地址&#xff1a;https://50-vue-projects.vercel.app/ ✨ 组件目标 实现一个加载进度条&#xff0c;随着加载进度的…

演示:【WPF-WinCC3D】 3D工业组态监控平台源代码

一、目的&#xff1a;分享一个应用WPF 3D开发的3D工业组态监控平台源代码 二、功能介绍 WPF-WinCC3D是基于 WPF 3D研发的工业组态软件&#xff0c;提供将近200个预置工业模型&#xff08;机械手臂、科幻零部件、熔炼生产线、机加生产线、管道等&#xff09;&#xff0c;支持组态…

【PostgreSQL数据分析实战:从数据清洗到可视化全流程】1.4 数据库与表的基本操作(DDL/DML语句)

&#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 文章大纲 1.4 数据库与表的基本操作&#xff08;DDL/DML语句&#xff09;1.4.1 数据库生命周期管理&#xff08;DDL核心&#xff09;1.4.1.1 创建数据库&#xff08;CREATE DATABASE&…

如何在电脑上登录多个抖音账号?多开不同IP技巧分解

随着短视频的爆发式增长&#xff0c;抖音已经成为许多人生活和工作的必备平台。不论是个人内容创作者、品牌商家&#xff0c;还是营销人员&#xff0c;都可能需要管理多个抖音账号。如何在电脑上同时登录多个抖音账号&#xff0c;提升工作效率&#xff0c;避免频繁切换账号的麻…

【东枫科技】usrp rfnoc 开发环境搭建

作者 太原市东枫电子科技有限公司 &#xff0c;代理销售 USRP&#xff0c;Nvidia&#xff0c;等产品与技术支持&#xff0c;培训服务。 环境 Ubuntu 20.04 依赖包 sudo apt-get updatesudo apt-get install autoconf automake build-essential ccache cmake cpufrequtils …

【JAVA资料,C#资料,人工智能资料,Python资料】全网最全编程学习文档合集,从入门到全栈,保姆级整理!

文章目录 前言一、编程学习前的准备​1.1 明确学习目标​1.2 评估自身基础​ 二、编程语言的选择​2.1 热门编程语言介绍​2.2 如何根据目标选择语言​ 三、编程基础学习​3.1 变量与数据类型​3.2 控制结构​3.3 函数​ 四、面向对象编程&#xff08;OOP&#xff09;​4.1 OOP…

[IMX] 05.串口 - UART

目录 1.通信格式 2.电平标准 3.IMX UART 模块 4.时钟寄存器 - CCM_CSCDR1 5.控制寄存器 5.1.UART_UCR1 5.2.UART_UCR2 5.3.UART_UCR3 6.状态寄存器 6.1.UART_USR1 6.2.UART_USR2 7.FIFO 控制寄存器 - UART_UFCR 8.波特率寄存器 8.1.分母 - UART_UBIR 8.2.分子 -…