实际应用筛选器的内容
What is actually applying a filter?
我正在尝试用我不熟悉的概念解决C++中一个具有挑战性的问题。
我正在尝试对矩阵应用过滤器。然而,正如我所说,我在这方面还很陌生,经过一些调查,我发现了这个链接,它表明应用滤波器基本上是一个乘法
然而,让我困惑的是,如果我的滤波器是[0,1,0],并且我必须将其应用于5x5矩阵。我该怎么做?
基于内核的GIMP过滤
第一链路的替代方案
编辑:第二个链接真的让我很困惑。我现在正试图决定"申请"过程。如果我遵循创建一个只有对角线[0,1,0]的3x3矩阵的想法,我是要像在第二个链接中那样应用它,还是必须将它应用到矩阵中的每个单元格。或者,如果它真的是一个一维过滤器,我应该再次将其应用于每个单元格还是去掉边和角?
这是一个卷积内核。
这个想法是用它和它的邻居的加权平均值来替换每个像素,其中权重由卷积核给出。这个过程解释得很好,例如在这里。
我觉得奇怪的是,你有一个一维卷积内核(即,它适用于一维图像),而通常用于图像处理时,会使用二维卷积内核(也从上面/下面的行中获取像素),但可能你的算法只需要处理当前行中的像素。
我认为被忽略的是,使用输入数据的子集对输入数组的每个元素重复乘法。
GIMP示例展示了如何使用单个像素的3x3滤波器对5x5图像进行滤波:
. . . . . . . . . .
. - - - . . . . . . . . .
. - @ - . x . . . -> . . @ . .
. - - - . . . . . . . . .
. . . . . . . . . .
我用@
标记了一个输入像素,用-
标记了它的邻居。您使用较小的矩阵:
- - - . . .
- @ - x . . . = 3x3 array
- - - . . .
将生成的3x3数组中的数字相加,并将该值存储到新图像中,以代替@
像素。
举个例子,当使用3x1过滤器过滤5x5图像时:
. . . . . . . . . .
. . . . . . . . . .
. - @ - . x . . . -> . . @ . .
. . . . . . . . . .
. . . . . . . . . .
您将使用输入数组的较小子集来匹配内核;
- @ - x . . . = 1x3 array
然后,再次对所得阵列中的数字求和,并将该值存储到新图像中以代替@
像素。
这会混淆您在答案中寻找的内容。如果我们假设您的过滤器存储在一个名为filter
的std::vector<double>
中,并且您的图像实际上是2D的,并且类型为std::vector< std::vector<double> >
,称为image
,那么我们可以执行以下操作来应用一维过滤器[-1,0,1]
:
std::vector< std::vector<double> > new_image;
std::vector<double> filter;
filter.push_back(-1.0); filter.push_back(0.0); filter.push_back(1.0);
for(int i = 0; i < image.size(); i++){
for(int j = 0; j < image.at(i).size(); j++){
new_image.at(i).push_back( filter.at(0)*image.at(i).at(j-1)
+ filter.at(1)*image.at(i).at(j)
+ filter.at(2)*image.at(i).at(j+1) );
}
}
如果你想有一个像这样的二维过滤器,例如
[0 1 0]
[1 0 1]
[0 1 0]
然后我们假设它也被存储为向量中的一个向量,基本上也是这样做的。
std::vector< std::vector<double> > new_image;
for(int i = 0; i < image.size(); i++){
for(int j = 0; j < image.at(i).size(); j++){
top_filter_term = filter.at(0).at(0)*image.at(i-1).at(j-1)
+ filter.at(0).at(1)*image.at(i-1).at(j)
+ filter.at(0).at(2)*image.at(i-1).at(j+1);
mid_filter_term = filter.at(1).at(0)*image.at(i).at(j-1)
+ filter.at(1).at(1)*image.at(i).at(j)
+ filter.at(1).at(2)*image.at(i).at(j+1);
bot_filter_term = filter.at(2).at(0)*image.at(i+1).at(j-1)
+ filter.at(2).at(1)*image.at(i+1).at(j)
+ filter.at(2).at(2)*image.at(i+1).at(j+1);
new_image.at(i).push_back(top_filter_term + mid_filter_term + bot_filter_term);
}
}
请注意--我没有为过滤器阵列做任何边界检查,你真的应该只在远离图像边缘的地方应用它,或者添加代码来应用你想要的过滤器的任何类型的边界条件。我也没有对这一点进行任何优化。对于大多数目的,使用向量是一种很好的方法,因为它们可以动态调整大小,并提供足够的内置支持来进行许多有用的图像操作。但对于真正的大规模处理,您需要优化过滤操作等操作。
至于您关于过滤3D阵列的问题,有几件事需要考虑。第一,确保您确实想要过滤整个数组。对于许多图像处理任务,将所有颜色通道拆分为自己的2D阵列,进行处理,然后将它们重新组合在一起会更好、更高效。如果你确实想要一个真正的3D过滤器,那么请确保你的过滤器实际上是3D的,也就是说,它将是一个向量的向量。然后,您将使用与上面完全相同的逻辑,但对于应用于图像的每个颜色通道或"切片"的过滤器部分,您将有一层额外的术语。
我想你说的是滤色器。从技术上讲,5X5图像实际上是5X5X3(a),其中"3"对应于3种基本颜色(RGB)。现在,创建一个对角线为[0,1,0](T)的3X3矩阵。
现在将这两个矩阵(AXT)相乘,得到新的5X5X3图像矩阵。
- 试图在visual studio上用C++创建一个桌面应用程序
- FFmpeg:制作一个应用程序比直接使用ffmepg更好吗
- c++r值引用应用于函数指针
- 在C应用程序中运行C++(带有STL)函数
- 使用VerQueryValue检索应用程序的文件描述
- Qt C++静态thread_local QNetworkAccessManager是线程应用程序的好选择吗
- 使用调试/崩溃报告将应用程序部署到客户端
- C++控制台应用程序阻止退出
- 码头化的C++应用程序是否向后兼容早期的内核版本
- 将应用程序从32位移植到64位时出现问题
- 有没有任务栏API可以立即应用注册表更改
- 如何改变c++应用程序的视觉效果
- WM_CTLCOLORSTATIC从未在WIN32应用程序中触发
- PC中的程序和PHONE中的本机描述应用程序之间的数据连接
- 应用程序崩溃并显示"symbol _ZdlPvm, version Qt_5 not defined in file libQt5Core.so.5 with link time reference"
- 微筛选器从用户模式应用程序接收常量值
- 是否可以让一个应用程序配置和管理 DirectShow 筛选器,但将输出引脚绑定到另一个应用程序
- 实际应用筛选器的内容
- 为什么启用 Windows 基本筛选引擎服务后,我的应用程序无法接收 UDP 数据包?
- 如何在 Vista 和 Win7 上连接 FS 微筛选器驱动程序和我的应用程序?