创建您自己的线性滤波器

Posted

技术标签:

【中文标题】创建您自己的线性滤波器【英文标题】:Creating Your Own Linear Filter 【发布时间】:2018-02-07 10:29:53 【问题描述】:

我是 Opencv C++ 的新手。我正在尝试将蒙版与图像进行卷积。为此,我想创建自己的蒙版,以便可以使用 filter2D 数组函数将蒙版与图像进行卷积。我要创建的面具是:

char mask [3][3]=  -1,0,1,-1,0,1,-1,0,1;

为此,我尝试了以下代码(生成此掩码):-

Mat kernel(3,3, CV_8UC1, Scalar(-1,0,1)); 

我已将掩码值打印为

std::cout << kernel;

但我得到的答案是 0, 0, 0; 0, 0, 0; 0, 0, 0

我期待答案是 -1, 0, 1; -1, 0, 1; -1, 0, 1

我知道我在正确编写频道时犯了一个错误。谁能帮我理解通道(CV_8UC1....)的含义以及如何纠正它并获得正确的输出。

【问题讨论】:

Mat kernel(3,3, CV_8UC1, Scalar(-1,0,1));意味着,您将第一个通道设置为 -1,将第二个通道设置为 0,将第三个通道设置为 1。但是由于您只有一个通道矩阵,因此只使用第一个通道:-1。但是由于你有无符号类型,它会饱和到 0。所以你的示例图像的每个像素都是 0。 【参考方案1】:

CV_8UC1 表示 1 通道,8 位,uchar 图像。

标量用于设置每个通道的值,而不是每个像素/坐标。

例 1:

Mat kernel(3,3, CV_8UC1, Scalar::all(0)) 

意味着创建一个 0 的 3X3 矩阵,由于它是 CV_8UC1 类型,因此您只能提及一个值,在本例中为 0。

EX 2:

Mat kernel(3,3, CV_8UC3, Scalar(0,0,255)) 

表示创建一个具有 3 个通道的 3X3 矩阵,因为类型为 CV_8UC3,并将通道 1 设置为 0,通道 2 设置为 0,通道 3 设置为 255。

因此,为了设置行值,您不能使用标量。 而是这样做:

Mat C = (Mat_<double>(3,3) << -1, 0, 1, -1, 0, 1, -1, 0, 1);

查看this了解更多信息。

希望这会有所帮助!

【讨论】:

【参考方案2】:

您想为filter2D 创建一个带有negative 元素的kernel,那么您不应该使用CV_8UC1 的数据类型。 There is no negative value in unsigned type.

Mat kernel(3,3, CV_8UC1, Scalar(-1,0,1)); 表示创建一个信号通道无符号字符内核。您将Scalar(-1,0,1) 设置为kernel,则只使用the first element(that is double -1),而saturate_cast&lt;unchar&gt;(-1) = 0

一般情况下,请改用CV_32FC1


例如:

#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;

int main()
    float mask[9] = -1,0,1, -1, 0, 1, -1,0,1;
    Mat kernel(3,3, CV_32FC1);
    memcpy(kernel.data, mask, sizeof(float)*9);
    cout << kernel<<endl;


结果:

[-1, 0, 1;
 -1, 0, 1;
 -1, 0, 1]

一个类似的问题:

How to create cv::Mat from buffer (array of T* data) using a template function?

【讨论】:

以上是关于创建您自己的线性滤波器的主要内容,如果未能解决你的问题,请参考以下文章

线性卡尔曼滤波详解

线性卡尔曼滤波详解

线性卡尔曼滤波详解

simulink中滤波器怎么设置

翻译: 使用非线性卡尔曼滤波来估计信号

翻译: 使用非线性卡尔曼滤波来估计信号