创建您自己的线性滤波器
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<unchar>(-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?
【讨论】:
以上是关于创建您自己的线性滤波器的主要内容,如果未能解决你的问题,请参考以下文章