<学习opencv>图像变换

 

拉伸、收缩、扭曲和旋转

统一调整大小
我们经常会遇到一些我们希望转换为其他尺寸的图像。 
我们可能想要扩大或缩小图像; 这两项任务都是由同一个功能完成的。


cv::resize()
该cv::resize()函数的作用是:处理所有这些调整大小的需求。
我们提供我们的输入图像和我们希望它转换成的大小,它将生成一个所需大小的新图像。

void cv::resize(
    cv::InputArray src,
    cv :: OutputArray dst,//结果图像
    cv :: Size dsize,//新尺寸
    double fx = 0// x-rescale
    double fy = 0// y-rescale
    int interpolation = CV :: INTER_LINEAR //插值方法
);

我们可以用两种方式指定输出图像的大小。一种方法是使用绝对尺寸 ; 
在这种情况下,dsize 参数直接设置我们希望结果图像的大小dst 。
另一种选择是使用相对尺寸;在这种情况下,我们设置dsize 到cv::Size(0,0),并设置fx 和fy 对规模因素,
我们想分别适用于x轴和y轴。最后一个参数是方法,默​​认为线性插值。

cv :: resize()插值选项
---------------------------------------------
插值    含义
cv::INTER_NEAREST    最近的邻居
cv::INTER_LINEAR    双线性
cv::INTER_AREA    像素区域重采样
cv::INTER_CUBIC    双立方插值
cv::INTER_LANCZOS4    Lanczos插值超过8×8邻域。
---------------------------------------------
Interpolation是这里的一个重要问题。源图像中的像素位于整数网格上;
例如,我们可以在位置(2017)引用像素。当这些整数位置映射到新图像时,
可能会有间隙-要么是因为整数源像素位置映射到目标图像中的浮点位置,
必须四舍五入到最近的整数像素位置,要么是因为有些位置没有像素配置到e映射
(考虑通过拉伸使图像大小加倍;然后将其他目标像素留空)。
这些问题通常被称为正投影问题。为了解决这种舍入问题和目的地间隙,
我们实际上是向后解决问题:我们跨过目的地图像的每个像素,
然后问,“源中需要哪些像素来填充目的地像素?”
“这些源像素几乎总是在分数像素位置上,因此我们必须对源像素进行插值,
以获得目标值的正确值。默认方法是双线性插值,但您可以选择其他方法

最简单的方法是从源图像中最接近的像素获取调整后的像素值;
这是选择插值值cv::inter-nearest的效果。
或者,我们可以根据2×2周围的源像素值与目标像素的距离对其进行线性加权,
这就是cv::inter_linear所做的。我们还可以将新的、调整大小的像素放置在旧像素上,
然后平均覆盖的像素值,就像使用cv::inter_区域一样。2对于更平滑的插值,
我们可以选择在源图像中的4×4周围像素之间拟合一个三次样条曲线,
然后从拟合的样条曲线中读取相应的目标值;这是选择cv::inter-cubic插值方法的结果。
最后,我们有兰佐斯插值,这类似于三次方方法,但使用来自8×8像素周围区域的信息。

[注意]
注意cv::resize()与cv::mat类中类似名称的cv::mat::resize()
成员函数之间的区别是很重要的。cv::resize()创建一个不同大小的新图像,
在该图像上映射原始像素。cv::mat::resize()成员函数可调整正在调用其成员的图像的大小,
并将该图像裁剪为新的大小。在cv::mat::resize()的情况下,像素不会被插值(或外推)


图像金字塔
图像金字塔[Adelson84]广泛应用于各种视觉应用。
图像金字塔是一组图像——所有这些图像都来自于一个原始图像——它们被连续地降采样,
直到达到某个所需的停止点。(此停止点可以是单像素图像!)
在文献和应用中经常出现两种图像金字塔:高斯金字塔和拉普拉斯金字塔。
高斯金字塔用于对图像进行降采样,当我们想从金字塔中较低的图像重建上采样图像时,需要使用拉普拉斯金字塔。


cv::pyrDown()
通常,我们 在高斯中产生层(i + 1) 金字塔(我们用金字塔表示G i + 1)
表示金字塔的层G i ,首先将G i 与高斯核卷积,然后删除每个偶数行和列。
当然,在这种情况下,每个图像恰好是其前身的四分之一面积。
在输入图像G 0上迭代该过程产生整个金字塔。
OpenCV为我们提供了一种从其前身生成每个金字塔阶段的方法: 
void cv::pyrDown(
    cv::InputArray src,     //输入图像
    cv::OutputArray dst,    //结果图像
    const cv::size&dstsize = cv::Size() //输出图像大小
)

如果我们将destination size参数dstsize设置为其默认值cv::size(),
cv::pyrdown()方法将为我们实现这一点。
更具体地说,输出图像的默认大小是((src.cols+1)/2,(src.rows+1)/2)。
或者,我们可以提供一个dstsize,它将指示我们希望输出图像的大小;
但是dstsize必须遵守一些非常严格的约束。

此限制意味着目标图像非常接近 源图像大小的一半。
dstsize参数只用于处理一些需要对金字塔的构造方式进行非常严格控制的深奥情况。

cv::buildPyramid()
有一个图像并希望构建一个新图像序列是一种相对常见的情况,
每个新图像都是从其前一个图像缩小的。
函数cv::buildPyramid()在一次调用中为您创建这样一组图像

void cv :: buildPyramid(
  cv :: InputArray src,//输入图像
  cv :: OutputArrayOfArrays dst,//从金字塔输出图像
  int maxlevel //金字塔等级数
);

参数src是源映像。参数dst的类型cv::outputarayofrays看起来有些不寻常,
但可以将其视为stl向量<>或cv::outputaray类型的对象。
最常见的例子是vector<cv::mat>。参数maxlevel指示要构造多少金字塔级别。

参数maxlevel是大于或等于0的任何整数,并指示要生成的金字塔图像数。
当cv::buildPyramid()运行时,它将返回DST中长度为maxLevel+1的向量。
DST中的第一个条目将与SRC相同。第二个将是最大的一半,
也就是说,调用cv::pyrdown()所产生的结果。
第三个将是第二个的一半大小,以此类推.


cv::pyrUp()
同样,我们可以通过以下类似的方法(但不是相反的方法)将现有图像转换为每个方向两倍大的图像。
操作:
void cv :: pyrUp(
  cv :: InputArray src,//输入图像
  cv :: OutputArray dst,//结果图像
  const cv :: Size&dstsize = cv :: Size()//输出图像大小
);

在这种情况下,图像首先增大到每个维度中原始的两倍,新(偶数)行填充0。此后,利用高斯滤波器5执行卷积 以近似“丢失”像素的值。

类似于cv::PyrDown() ,如果dstsize 设置为其默认值cv::Size(),
则生成的图像将是大小(在每个维度中)的两倍src。
同样,我们可以提供一个dstsize指示我们想要输出图像的大小dstsize,
但它必须再次遵守一些非常严格的约束。特别:

这一限制意味着目标图像的大小接近源图像的两倍。和以前一样,
dstsize参数只用于处理一些需要对金字塔的构造方式进行非常严格控制的深奥情况。

拉普拉斯金字塔
我们之前已经注意到,运算符cv::pyrup()不是cv::pyrup()的倒数。
这应该很明显,因为cv::pyrdown()是一个丢失信息的运算符。
为了恢复原始(高分辨率)图像,我们需要访问被降采样过程丢弃的信息。
这些数据形成了拉普拉斯金字塔。

这里,操作者UP() 通过将 原始图像中的位置(x,y)
中的每个像素映射到目标图像中的像素(2 x + 1,2 y + 1)来进行放大。
⊗符号表示卷积; 和g 5 × 5 是一个5×5高斯核。当然,UP (ģ i 1 )⊗ 克5 × 5 是定义 由OpenCV中提供的操作员。
因此,我们可以使用OpenCV直接计算拉普拉斯算子:cv::pyrUp()

 

posted @ 2019-11-12 09:19  Xu_Lin  阅读(305)  评论(0编辑  收藏  举报