三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

opencv 滤波

opencv 滤波

1. 卷积核

卷积核就是一个小数字矩阵 ,在图像上滑动,小数字矩阵和对应位置的像素做运算,实现模糊、锐化、边缘检测。

blurGaussianBlurmedianBlurfilter2D全部底层都是卷积运算

假设 3×3 卷积核,滑动到图像某一块:

图像像素 卷积核kernel [10 20 30] [a b c] [40 50 60] [d e f] [70 80 90] [g h i]

输出中心像素 =10*a + 20*b +30*c +40*d +50*e +60*f +70*g +80*h +90*i

核窗口逐像素向右、向下滑动,遍历整张图,生成输出图像。

2. 均值滤波

void blur(

InputArray src,

InputArray dst,

Size ksize,

Point point = Point(-1, -1),

int borderType = BORDER_DEFAULT

);

原理:在图像上滑动一个矩形窗口(卷积核),把窗口内所有像素求算术平均值,赋值给窗口中心输出像素。

cv::Mat src,dst; src = imread("test.jpg"); cv::blur(src,dst,cv::Size(5,5));

cv::Size(3,3) 卷积核大小,必须奇数, size越大越模糊

2. 高斯模糊

void GaussianBlur(

InputArray src,

InputArray dst,

Size ksize,

double sigmaX,

double sigmaY = 0,

int borderType = BORDER_DEFAULT

);

Size 设置卷积核的大小,必须是奇数 Size(0,0) 核大小有sigmaX自动计算

sigmaX:X方向高斯标准差;数值越大,模糊越强 sigmaX = 0 ,sigmaX由Size()自动计算

sigmaY: Y方向高斯标准差;sigmaY传0就自动等于sigmaX

Mat src,dst; GaussianBlur(src,dst,Size(5,5),0); // sigmaX由size自动计算 GaussianBlue(src,dst,Size(0,0),4); // Size(0,0) 核大小由sigmaX 自动计算

3. 中值滤波

void medianBlur(InputArray src, InputArray dst, int ksize);

原理:取卷积窗口内像素中位数,不是平均值。

ksize 窗口大小,取像素值,必须是奇数

cv::Mat src,dst; medianBlure(src, dst, 5);

4. 双边滤波

void bilateral(

InputArray src,

InputArray dst,

int d,

double sigmaColor,

double sigmaSpace,

int borderType = BORDER_DEAFAULT

);

双边滤波:保边缘的模糊,美颜算法底层。

❗不是固定卷积核,权重是动态计算,每一个位置的权重都不一样,计算开销大。

  1. d:滤波邻域直径。
    • d = 0:程序自动根据sigmaSpace计算邻域大小(推荐写 0)
  2. sigmaColor:颜色域标准差
    • 值越大:允许相差更大的颜色参与平滑;越大模糊越强。
    • 一般取值:25 ~ 100
  3. sigmaSpace:空间域标准差,单位像素
    • 值越大:参与计算的像素范围越大。
    • 一般取值:25 ~ 100
  4. borderType:边界填充,默认即可,不用修改

实例代码:

mainwindow.cpp

#include "mainwindow.h" #include "ui_mainwindow.h" #include <QDebug> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { qDebug() << __func__ << __LINE__; ui->setupUi(this); initMainWindow(); } MainWindow::~MainWindow() { delete ui; } void MainWindow::initMainWindow() { qDebug() << __func__ << __LINE__; ui->blurViewLabel->setFixedSize(723,399); ui->gaussianViewLabel->setFixedSize(723,399); ui->medianViewLabel->setFixedSize(723,399); ui->bilateralViewLabel->setFixedSize(723,399); QString imgPath = R"(D:\new_share\016_opencv\OpenCVFilter\1.jpg)"; Mat imgData = imread(imgPath.toStdString()); // BGR 格式 cvtColor(imgData, imgData , COLOR_BGR2RGB); // 转为 RGB 格式 myImg = imgData; blurImg = QImage((const unsigned char*)imgData.data, imgData.cols, imgData.rows, static_cast<int>(imgData.step),QImage::Format_RGB888).copy(); gaussianImg = blurImg; medianImg = blurImg; bilateralImg = blurImg; imgShow(); } void MainWindow::imgShow() { qDebug() << __func__ << __LINE__; ui->blurViewLabel->setPixmap(QPixmap::fromImage(blurImg.scaled(ui->blurViewLabel->size()))); ui->gaussianViewLabel->setPixmap(QPixmap::fromImage(gaussianImg.scaled(ui->gaussianViewLabel->size()))); ui->medianViewLabel->setPixmap(QPixmap::fromImage(medianImg.scaled(ui->medianViewLabel->size()))); ui->bilateralViewLabel->setPixmap(QPixmap::fromImage(bilateralImg.scaled(ui->bilateralViewLabel->size()))); } void MainWindow::imgProc(int kernel) { qDebug() << __func__ << __LINE__; Mat imgSrc = myImg; Mat imgBlurDst = imgSrc.clone(); Mat imgGaussianDst = imgSrc.clone(); Mat imgMedianDst = imgSrc.clone(); Mat imgBilateralDst = imgSrc.clone(); int value = 1; value = value + kernel*2; blur(imgSrc,imgBlurDst,Size(value,value),Point(-1,-1)); GaussianBlur(imgSrc, imgGaussianDst, Size(value,value),0); medianBlur(imgSrc,imgMedianDst,value); bilateralFilter(imgSrc, imgBilateralDst, value, value*2.0, value/2.0); blurImg = QImage((const unsigned char*)imgBlurDst.data, imgBlurDst.cols, imgBlurDst.rows, static_cast<int>(imgBlurDst.step),QImage::Format_RGB888).copy(); gaussianImg = QImage((const unsigned char*)imgGaussianDst.data, imgGaussianDst.cols, imgGaussianDst.rows, static_cast<int>(imgGaussianDst.step), QImage::Format_RGB888).copy(); medianImg = QImage((const unsigned char*)imgMedianDst.data, imgMedianDst.cols, imgMedianDst.rows, static_cast<int>(imgMedianDst.step), QImage::Format_RGB888).copy(); bilateralImg = QImage((const unsigned char*)imgBilateralDst.data, imgBilateralDst.cols, imgBilateralDst.rows, static_cast<int>(imgBilateralDst.step), QImage::Format_RGB888).copy(); imgShow(); } void MainWindow::on_verticalSlider_valueChanged(int value) { qDebug() << __func__ << __LINE__; imgProc(value); }

mainwindow.h

#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <opencv2/opencv.hpp> QT_BEGIN_NAMESPACE using namespace cv; namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); void initMainWindow(); void imgShow(); void imgProc(int kernel); private slots: void on_verticalSlider_valueChanged(int value); private: Ui::MainWindow *ui; Mat myImg; QImage blurImg; QImage gaussianImg; QImage medianImg; QImage bilateralImg; }; #endif // MAINWINDOW_H

← 返回列表