边缘填充函数
在本入门部分,您将了解 OpenCV 中可用的不同线性和非线性图像滤波方法。 重要的是要注意,本节中讨论的所有函数都将Mat
图像作为输入,并产生相同大小和相同通道数的Mat
图像。 实际上,过滤器是独立应用于每个通道的。 通常,滤波方法从输入图像中获取一个像素及其相邻像素,并基于来自这些像素的函数响应来计算所得图像中相应像素的值。
这通常需要在计算滤波后的像素结果时对不存在的像素进行假设。 OpenCV 提供了许多方法来解决此问题,可以使用cv::BorderTypes
枚举在几乎所有需要处理此现象的 OpenCV 函数中指定它们。 稍后我们将在本章的第一个示例中看到如何使用它,但是在此之前,让我们确保使用下图完全理解它:
如上图所示,计算(或在这种情况下为滤波函数)将区域 A 中的像素作为像素,并在处理后的所得图像(在这种情况下为过滤后的图像)中给我们像素 A。 在这种情况下没有问题,因为输入图像中像素 A 附近的所有像素都在图像内部,即区域 A。但是,图像边缘附近的像素或 OpenCV 中称为“边界像素”的像素又如何呢? 如您所见,并非像素 B 的所有相邻像素都落入输入图像,即区域 B。 这就是我们需要做的假设,即将图像外部像素的值视为零,与边界像素相同,依此类推。这正是cv::BorderTypes
枚举的含义,我们需要在示例中使用合适的值进行指定。现在,在开始图像过滤函数之前,让我们用第一个示例演示cv::BorderTypes
的用法。 我们将借此机会还学习如何为上一章中开始的Computer_Vision
项目创建新插件(或克隆现有插件)。
copymakeborder_plugin.cpp
void CopyMakeBorder_Plugin::setupUi(QWidget *parent)
{
ui = new Ui::PluginGui;
ui->setupUi(parent);
QStringList items;
items.append("BORDER_CONSTANT");
items.append("BORDER_REPLICATE");
items.append("BORDER_REFLECT");
items.append("BORDER_WRAP");
items.append("BORDER_REFLECT_101");
ui->borderTypeComboBox->addItems(items);
connect(ui->borderTypeComboBox,
SIGNAL(currentIndexChanged(int)),
this,
SLOT(on_borderTypeComboBox_currentIndexChanged(int)));
}
void CopyMakeBorder_Plugin::processImage(const cv::Mat &inputImage, cv::Mat &outputImage)
{
int top, bot, left, right;
top = bot = inputImage.rows/2;
left = right = inputImage.cols/2;
cv::copyMakeBorder(inputImage,
outputImage,
top,
bot,
left,
right,
ui->borderTypeComboBox->currentIndex());
}
void CopyMakeBorder_Plugin::on_borderTypeComboBox_currentIndexChanged(int index)
{
Q_UNUSED(index);
emit updateNeeded();
}
在这里,我们将调用copyMakeBorder
函数,该函数也称为内部函数,该函数需要处理有关图像外部不存在的像素的假设。 我们仅假设图像顶部和底部添加的边框是图像高度的一半,而图像左侧和右侧添加的边框是图像宽度的一半。 至于borderType
参数,我们只需从插件 GUI 上的选定项中获取即可。
BORDER_CONSTANT
BORDER_REPLICATE
BORDER_REFLECT
BORDER_WRAP
BORDER_REFLECT_101