创建自己的线性滤波器

4

我是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。 - Micka
2个回答

3

CV_8UC1表示一通道、8位、无符号字符型图像。

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

示例1:

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

意味着创建一个由0组成的3X3矩阵,由于其类型为CV_8UC1,因此您只需提及一个值,即0。

例子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);

希望这可以帮到您!
请查看此链接以获取更多信息。

1
您想要创建一个带有负元素的内核(kernel),用于filter2D,那么就不应该使用CV_8UC1数据类型。无符号类型中没有负值
Mat kernel(3,3, CV_8UC1, Scalar(-1,0,1));意味着创建一个单通道无符号字符型(kernel)。您将Scalar(-1,0,1)设置为kernel,那么只有第一个元素(即双精度-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]

一个类似的问题:

如何使用模板函数从缓冲区(T *数据数组)创建cv :: Mat?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接