OpenCV3 和 Qt5 计算机视觉 学习笔记 - 颜色和色彩空间 - OpenCV 中的过滤函数

本文主要是介绍OpenCV3 和 Qt5 计算机视觉 学习笔记 - 颜色和色彩空间 - OpenCV 中的过滤函数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

OpenCV 中的所有过滤函数均会拍摄图像,并产生尺寸和通道完全相同的图像。 如前所述,它们也都带有borderType参数,我们刚刚完成了实验和学习。 除此之外,每个过滤函数都有自己的必需参数来配置其行为。 这是可用的 OpenCV 过滤函数的列表及其说明和使用方法。 在列表的最后,您可以找到一个示例插件(称为filter_plugin)及其源代码的链接,其中包括以下列表中提到的大多数过滤器,并带有 GUI 控件以试验不同的参数和设置。 为每一个:

  • bilateralFilter:可用于获取图像的Bilateral Filtered副本。 根据σ值和直径,您可以获得的图像看上去可能与原始图像没有太大差异,或者获得的图像看起来像卡通图像(如果σ值足够高)。 这是bilateralFilter函数作为我们的应用的插件工作的示例代码:
        bilateralFilter(inpMat,outMat,15,200,200); 

在这里插入图片描述

//tag 选项
#define BILATERAL_FILTER_PAGE           0
#define BLUR_FILTER_PAGE                1
#define BOX_FILTER_PAGE                 2
#define GAUSSIAN_FILTER_PAGE            3
#define MEDIAN_FILTER_PAGE              4
#define FILTER2D_PAGE                   5
#define DERIVATIVES_PAGE                6
#define MORPH_PAGE                      7设置插件的界面
void Filter_Plugin::setupUi(QWidget *parent)
{ui = new Ui::PluginGui;ui->setupUi(parent);ui->mainTabs->setCurrentIndex(0);connect(ui->mainTabs, SIGNAL(currentChanged(int)), this, SLOT(on_mainTabs_currentChanged(int)));connect(ui->bilateralDiaSpin, SIGNAL(valueChanged(int)), this, SLOT(on_bilateralDiaSpin_valueChanged(int)));connect(ui->bilateralSigmaColorSpin, SIGNAL(valueChanged(double)), this, SLOT(on_bilateralSigmaColorSpin_valueChanged(double)));connect(ui->bilateralSigmaSpaceSpin, SIGNAL(valueChanged(double)), this, SLOT(on_bilateralSigmaSpaceSpin_valueChanged(double)));connect(ui->blurKernelSizeSpinBox, SIGNAL(valueChanged(int)), this, SLOT(on_blurKernelSizeSpinBox_valueChanged(int)));connect(ui->blurAnchoXSpin, SIGNAL(valueChanged(int)), this, SLOT(on_blurAnchoXSpin_valueChanged(int)));connect(ui->blurAnchoYSpin, SIGNAL(valueChanged(int)), this, SLOT(on_blurAnchoYSpin_valueChanged(int)));connect(ui->boxKernelSizeSpinBox, SIGNAL(valueChanged(int)), this, SLOT(on_boxKernelSizeSpinBox_valueChanged(int)));connect(ui->boxDepthSpin, SIGNAL(valueChanged(int)), this, SLOT(on_boxDepthSpin_valueChanged(int)));connect(ui->boxAnchoXSpin, SIGNAL(valueChanged(int)), this, SLOT(on_boxAnchoXSpin_valueChanged(int)));connect(ui->boxAnchoYSpin, SIGNAL(valueChanged(int)), this, SLOT(on_boxAnchoYSpin_valueChanged(int)));connect(ui->boxNormalCheck, SIGNAL(toggled(bool)), this, SLOT(on_boxNormalCheck_toggled(bool)));connect(ui->gaussKernelSizeSpinBox, SIGNAL(valueChanged(int)), this, SLOT(on_gaussKernelSizeSpinBox_valueChanged(int)));connect(ui->gaussSigmaXSpin, SIGNAL(valueChanged(double)), this, SLOT(on_gaussSigmaXSpin_valueChanged(double)));connect(ui->gaussSigmaYSpin, SIGNAL(valueChanged(double)), this, SLOT(on_gaussSigmaYSpin_valueChanged(double)));connect(ui->medianApertureSpin, SIGNAL(valueChanged(int)), this, SLOT(on_medianApertureSpin_valueChanged(int)));connect(ui->derivSobelRadio, SIGNAL(toggled(bool)), this, SLOT(on_derivSobelRadio_toggled(bool)));connect(ui->derivScharrRadio, SIGNAL(toggled(bool)), this, SLOT(on_derivScharrRadio_toggled(bool)));connect(ui->derivLaplacRadio, SIGNAL(toggled(bool)), this, SLOT(on_derivLaplacRadio_toggled(bool)));connect(ui->derivDeltaSpin, SIGNAL(valueChanged(double)), this, SLOT(on_derivDeltaSpin_valueChanged(double)));connect(ui->derivScaleSpin, SIGNAL(valueChanged(double)), this, SLOT(on_derivScaleSpin_valueChanged(double)));ui->morphShapesCombo->addItems(QStringList() << "MORPH_RECT" << "MORPH_CROSS" << "MORPH_ELLIPSE");ui->morphTypesCombo->addItems(QStringList() << "MORPH_ERODE" << "MORPH_DILATE" << "MORPH_OPEN" << "MORPH_CLOSE"<< "MORPH_GRADIENT" << "MORPH_TOPHAT" << "MORPH_BLACKHAT");connect(ui->morphDilateRadio, SIGNAL(toggled(bool)), this, SLOT(on_morphDilateRadio_toggled(bool)));connect(ui->morphErodeRadio, SIGNAL(toggled(bool)), this, SLOT(on_morphErodeRadio_toggled(bool)));connect(ui->morphMorphRadio, SIGNAL(toggled(bool)), this, SLOT(on_morphMorphRadio_toggled(bool)));connect(ui->morphIterSpin, SIGNAL(valueChanged(int)), this, SLOT(on_morphIterSpin_valueChanged(int)));connect(ui->morphShapesCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(on_morphShapesCombo_currentIndexChanged(int)));connect(ui->morphTypesCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(on_morphTypesCombo_currentIndexChanged(int)));
}void Filter_Plugin::processImage(const cv::Mat &inputImage, cv::Mat &outputImage)
{using namespace cv;Matx33f f2dkernel;switch(ui->mainTabs->currentIndex()){// 双边滤波case BILATERAL_FILTER_PAGE:bilateralFilter(inputImage, // 输入图像,可以是Mat类型,图像必须是8位或浮点型单通道、三通道的图像outputImage,//输出图像,和原图像有相同的尺寸和类型ui->bilateralDiaSpin->value(), //表示在过滤过程中每个像素邻域的直径范围。如果这个值是非正数,则函数会从第五个参数sigmaSpace计算该值。 ui->bilateralSigmaColorSpin->value(), // 颜色空间过滤器的sigma值,这个参数的值月大,表明该像素邻域内有越宽广的颜色会被混合到一起,产生较大的半相等颜色区域。ui->bilateralSigmaSpaceSpin->value());//坐标空间中滤波器的sigma值,如果该值较大,则意味着越远的像素将相互影响,从而使更大的区域中足够相似的颜色获取相同的颜色。当d>0时,d指定了邻域大小且与sigmaSpace无关,否则d正比于sigmaSpace. (这个参数可以理解为空间域核w_d的\sigma_d)break;case BLUR_FILTER_PAGE:blur(inputImage,outputImage,Size(ui->blurKernelSizeSpinBox->value(),ui->blurKernelSizeSpinBox->value()),Point(ui->blurAnchoXSpin->value(),ui->blurAnchoYSpin->value()));break;case BOX_FILTER_PAGE:boxFilter(inputImage,outputImage,ui->boxDepthSpin->value(),Size(ui->boxKernelSizeSpinBox->value(),ui->boxKernelSizeSpinBox->value()),Point(ui->boxAnchoXSpin->value(),ui->boxAnchoYSpin->value()),ui->boxNormalCheck->isChecked());// replace with sqrBoxFilterbreak;case GAUSSIAN_FILTER_PAGE:GaussianBlur(inputImage,outputImage,Size(ui->gaussKernelSizeSpinBox->value(),ui->gaussKernelSizeSpinBox->value()),ui->gaussSigmaXSpin->value(),ui->gaussSigmaYSpin->value());break;case MEDIAN_FILTER_PAGE:medianBlur(inputImage,outputImage,ui->medianApertureSpin->value());break;case FILTER2D_PAGE:f2dkernel = Matx33f(0, +1.5, 0,+1.5, -6, +1.5,0, +1.5, 0);filter2D(inputImage,outputImage,-1, // Output should have same depth as sourcef2dkernel,Point(-1,-1));break;case DERIVATIVES_PAGE:if(ui->derivSobelRadio->isChecked())Sobel(inputImage, outputImage, -1, 1, 1, 3, ui->derivScaleSpin->value(), ui->derivDeltaSpin->value());else if(ui->derivScharrRadio->isChecked())Scharr(inputImage, outputImage, -1, 1, 0, ui->derivScaleSpin->value(), ui->derivDeltaSpin->value());else if(ui->derivLaplacRadio->isChecked())Laplacian(inputImage, outputImage, -1, 3, ui->derivScaleSpin->value(), ui->derivDeltaSpin->value());break;case MORPH_PAGE:if(ui->morphErodeRadio->isChecked()){erode(inputImage,outputImage,getStructuringElement(ui->morphShapesCombo->currentIndex(),Size(5,5)),Point(-1,-1),ui->morphIterSpin->value());}else if(ui->morphDilateRadio->isChecked()){dilate(inputImage,outputImage,getStructuringElement(ui->morphShapesCombo->currentIndex(),Size(5,5)),Point(-1,-1),ui->morphIterSpin->value());}else if(ui->morphMorphRadio->isChecked()){morphologyEx(inputImage,outputImage,ui->morphTypesCombo->currentIndex(),getStructuringElement(ui->morphShapesCombo->currentIndex(),Size(5,5)),Point(-1,-1),ui->morphIterSpin->value());}break;}
}
  • blurboxFiltersqrBoxFilterGaussianBlurmedianBlur:这些均用于获取输入图像的平滑版本。 所有这些函数都使用核大小参数,该参数与直径参数基本相同,并且用于确定从中计算出滤波后像素的相邻像素的直径。 (尽管我们没有了解它们的详细信息,但是这些过滤器函数与我们在本书前面各章中使用的过滤器函数相同。)GaussianBlur函数需要提供高斯核标准差(σ)参数,在XY方向上。 (有关这些参数的数学来源的足够信息,请参阅 OpenCV 文档。)实际上,值得注意的是,高斯过滤器中的核大小必须为奇数和正数。 同样,如果核大小也足够高,较高的σ值只会对结果产生重大影响。 以下是提到的平滑过滤器的几个示例(左侧为GaussianBlur,右侧为medianBlur),以及示例函数调用:
 		Size kernelSize(5,5); blur(inpMat,outMat,kernelSize); int depth = -1; // output depth same as source Size kernelSizeB(10,10); Point anchorPoint(-1,-1); bool normalized = true; boxFilter(inutMat,outMat,depth, kernelSizeB,anchorPoint, normalized); double sigma = 10; GaussianBlur(inpMat,outMat,kernelSize,sigma,sigma); int apertureSize = 10; medianBlur(inpMat,outMat,apertureSize); 

在这里插入图片描述

  • filter2D:此函数可用于将自定义过滤器应用于图像。 您需要为此函数提供的一个重要参数是核矩阵。 此函数非常强大,它可以产生许多不同的结果,包括与我们先前看到的模糊函数相同的结果,以及许多其他过滤器,具体取决于提供的核。 这里有几个示例核,以及如何使用它们以及生成的图像。 确保尝试使用不同的核(您可以在互联网上搜索大量有用的核矩阵),并亲自尝试使用此函数:
  // Sharpening image Matx33f f2dkernel(0, -1, 0, -1, 5, -1, 0, -1, 0); int depth = -1; // output depth same as source filter2D(inpMat,outMat,depth,f2dkernel); ***** // Edge detection Matx33f f2dkernel(0, +1.5, 0, +1.5, -6, +1.5, 0, +1.5, 0); int depth = -1; // output depth same as source filter2D(inpMat,outMat,depth,f2dkernel); 

在这里插入图片描述

  • LaplacianScharrSobelspatialGradient:这些函数处理图像导数。 图像导数在计算机视觉中非常重要,因为它们可用于检测图像中具有变化或更好的是显着变化的区域(因为这是导数的用例之一)。 无需过多地讨论其理论和数学细节,可以提及的是,在实践中,它们用于处理边缘或角点检测,并且在 OpenCV 框架中被关键点提取方法广泛使用。 在前面的示例和图像中,我们还使用了导数计算核。 以下是一些有关如何使用它们以及产生的图像的示例。 屏幕截图来自Computer_Vision项目和filter_plugin,此列表后不久有一个链接。 您始终可以使用 Qt 控件(例如旋转框,刻度盘和滑块)来获取 OpenCV 函数的不同参数值,以更好地控制该函数的行为:
        int depth = -1; int dx = 1; int dy = 1; int kernelSize = 3; double scale = 5; double delta = 220; Sobel(inpMat, outMat, depth,dx,dy,kernelSize,scale,delta); 

在这里插入图片描述

如果我们使用以下代码:

        int depth = -1; int dx = 1; int dy = 0; double scale = 1.0; double delta = 100.0; Scharr(inpMat,outMat,depth,dx,dy,scale,delta);

在这里插入图片描述

对于以下代码:

        int depth = -1; int kernelSize = 3; double scale = 1.0; double delta = 0.0; Laplacian(inpMat,outMat,depth, kernelSize,scale,delta); 

在这里插入图片描述

  • erodedilate:从它们的名称可以猜出这些函数,它们对于获得腐蚀和膨胀效果很有用。 这两个函数都采用一个结构元素矩阵,可以通过简单地调用getStructuringElement函数来构建它。 (可选)您可以选择多次运行该函数(或对其进行迭代),以获得越来越腐蚀或膨胀的图像。 以下是如何同时使用这两个函数及其生成的图像的示例:
        erode(inputImage, outputImage, getStructuringElement(shapeComboBox->currentIndex(), Size(5,5)), // Kernel size Point(-1,-1), // Anchor point (-1,-1) for default iterationsSpinBox->value()); 

在这里插入图片描述

在这里插入图片描述

您可以将完全相同的参数传递给dilate函数。 在前面的代码中,假设使用组合框小部件获取结构元素的形状,该小部件可以是MORPH_RECTMORPH_CROSSMORPH_ELLIPSE。 同样,通过使用旋转框小部件设置迭代计数,该小部件可以是大于零的数字。

让我们继续下一个函数:

  • morphologyEx
    

    :此函数可用于执行各种形态学操作。 它需要一个操作类型参数以及我们在

    dilate
    

    erode
    

    函数中使用的相同参数。 以下是可以传递给

    morphologyEx
    

    函数的参数及其含义:

    • MORPH_ERODE:产生与erode函数相同的结果。

    • MORPH_DILATE:产生与dilate函数相同的结果。

    • MORPH_OPEN:可用于执行打开操作。 这与对侵蚀的图像进行放大相同,对于消除图像中的细微伪影很有用。

    • MORPH_CLOSE:可用于执行关闭操作。 它与侵蚀膨胀的图像相同,可用于消除线条中的细小断开等。

    • MORPH_GRADIENT:此函数提供图像的轮廓,并且与同一图像的侵蚀和膨胀版本的区别相同。

    • MORPH_TOPHAT:可用于获取图像与其打开的变形之间的差异。

    • MORPH_BLACKHAT:这可以用来获取图像关闭和图像本身之间的差异。

              morphologyEx(inputImage, outputImage, morphTypeComboBox->currentIndex(), getStructuringElement(shapeComboBox->currentIndex(), Size(5,5)), // kernel size Point(-1,-1), // default anchor point iterationsSpinBox->value()); 
      

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

这篇关于OpenCV3 和 Qt5 计算机视觉 学习笔记 - 颜色和色彩空间 - OpenCV 中的过滤函数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/900494

相关文章

Java中的Opencv简介与开发环境部署方法

《Java中的Opencv简介与开发环境部署方法》OpenCV是一个开源的计算机视觉和图像处理库,提供了丰富的图像处理算法和工具,它支持多种图像处理和计算机视觉算法,可以用于物体识别与跟踪、图像分割与... 目录1.Opencv简介Opencv的应用2.Java使用OpenCV进行图像操作opencv安装j

Oracle的to_date()函数详解

《Oracle的to_date()函数详解》Oracle的to_date()函数用于日期格式转换,需要注意Oracle中不区分大小写的MM和mm格式代码,应使用mi代替分钟,此外,Oracle还支持毫... 目录oracle的to_date()函数一.在使用Oracle的to_date函数来做日期转换二.日

opencv实现像素统计的示例代码

《opencv实现像素统计的示例代码》本文介绍了OpenCV中统计图像像素信息的常用方法和函数,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录1. 统计像素值的基本信息2. 统计像素值的直方图3. 统计像素值的总和4. 统计非零像素的数量

如何测试计算机的内存是否存在问题? 判断电脑内存故障的多种方法

《如何测试计算机的内存是否存在问题?判断电脑内存故障的多种方法》内存是电脑中非常重要的组件之一,如果内存出现故障,可能会导致电脑出现各种问题,如蓝屏、死机、程序崩溃等,如何判断内存是否出现故障呢?下... 如果你的电脑是崩溃、冻结还是不稳定,那么它的内存可能有问题。要进行检查,你可以使用Windows 11

Mybatis拦截器如何实现数据权限过滤

《Mybatis拦截器如何实现数据权限过滤》本文介绍了MyBatis拦截器的使用,通过实现Interceptor接口对SQL进行处理,实现数据权限过滤功能,通过在本地线程变量中存储数据权限相关信息,并... 目录背景基础知识MyBATis 拦截器介绍代码实战总结背景现在的项目负责人去年年底离职,导致前期规

C++11的函数包装器std::function使用示例

《C++11的函数包装器std::function使用示例》C++11引入的std::function是最常用的函数包装器,它可以存储任何可调用对象并提供统一的调用接口,以下是关于函数包装器的详细讲解... 目录一、std::function 的基本用法1. 基本语法二、如何使用 std::function

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;