持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第10天,点击查看活动详情
前言
在本节中,我们将学习如何通过移动像素来修改图像,在此过程不会改变像素值;而是将每个像素的位置重新映射到新位置。这对于在图像上创建特殊效果或校正由镜头等引起的图像失真时非常有用。
图像重映射
为了使用 OpenCV 重映射功能,首先需定义要在重映射过程中使用的映射,然后,将此映射应用于输入图像。显然,定义映射的方式将决定将产生的效果。在本节中,我们定义转换函数用于在图像上创建波浪效果。
1. 用两个参数创建wave函数获得波浪效果,一个输入图像和一个输出图像结果:
// 通过创建波浪效果重新映射图像
void wave(const cv::Mat &image, cv::Mat &result)
2. 创建两个映射变量,一个用于 x 位置,另一个用于 y 位置,用于存储重新映射的新位置:
cv::Mat srcX(image.rows,image.cols,CV_32F);
cv::Mat srcY(image.rows,image.cols,CV_32F);
3. 遍历每个像素:
// 创建映射
for (int i=0; i<image.rows; i++) {
for (int j=0; j<image.cols; j++){
4. 将实际位置 j 分配给映射 x 位置:
srcX.at<float>(i,j) = j;
5. 使用正弦函数计算 y 的新位置,使用 x 值作为 sin 的输入,然后关闭计算映射变量的循环:
srcY.at<float>(i,j) = i+5*sin(j/10.0);
}
}
将重映射函数应用于输入图像:
cv::remap(image, result, srcX, srcY, cv::INTER_LINEAR);
得到的结果如下图所示:
重新映射的目的是生成一个新图像,其中像素的位置发生了变化。为了构建这个新图像,我们需要知道目标图像中每个像素的原始位置在源图像中的位置。因此,所需的映射函数需要根据原始像素位置计算新像素位置;反向映射 (backward mapping) 则描述了新图像的像素如何映射回原始图像。在 OpenCV 中,反向映射使用两个映射来描述——一个用于 x 坐标,一个用于 y 坐标,它们都由浮点 cv::Mat 实例表示:
cv::Mat srcX(image.rows,image.cols,CV_32F); // x-map
cv::Mat srcY(image.rows,image.cols,CV_32F); // y-map
这些矩阵的大小将定义目标图像的大小,然后可以使用以下代码在源图像中读取目标图像的 (i,j) 像素值:
(srcX.at<float>(i,j) , srcY.at<float>(i,j))
目标图像中的像素可以映射回非整数值(即像素之间的位置),这样我们就可以选择映射函数。例如,在我们的重映射函数中,我们使用正弦函数来定义我们的变换,这也意味着我们必须在真实像素之间插入新像素。有多种不同方法执行像素插值,remap 函数的最后一个参数允许我们选择像素插值方法。