OpenCV3 6.3 用滤波器进行缩减像素采样

缩减像素采样

降低图像精度的过程称为缩减像素采样(downsampling),提升图像精度的过程称为提升像素采样(upsampling)。

空间假频

如果要缩小一幅图像,仅仅消除图像中部分行和列,再将剩余的像素拼接起来,得到的图像效果往往不尽人意。

cv::Mat image = cv::imread("boldt.jpg");
cv::Mat reduced1(image.rows / 4, image.cols / 4, CV_8UC3);
for (int i = 0; i < reduced1.rows; i++)
{
    for (int j = 0; j < reduced1.cols; j++)
    {
        reduced1.at<cv::Vec3b>(i, j) = image.at<cv::Vec3b>(i * 4, j * 4);
    }
}
//将每个像素按原大小的四倍显示(使用最近点插值)
cv::resize(reduced1, reduced1, cv::Size(), 4, 4, cv::INTER_NEAREST);
cv::imshow("badly reduced", reduced1);

在这里插入图片描述
在本例中,先遍历保留四个像素中的一个,再通过cv::resize()函数放大。可以看出,图像的质量明显降低了,可以看到明显的锯齿变形,是由于空间假频造成的。

当试图在图像中包含高频成分而由于图像太小无法包含时,就会出现空间假频,解决办法是在缩小图像之前去除其高频成分,本例中使用了上一节的高斯滤波。

cv::Mat reduced2(image.rows / 4, image.cols / 4, CV_8UC3);
//首先使用高斯滤波去除高频成分
cv::GaussianBlur(image, image, cv::Size(11, 11), 2.0);
for (int i = 0; i < reduced2.rows; i++)
{
    for (int j = 0; j < reduced2.cols; j++)
    {
        reduced2.at<cv::Vec3b>(i, j) = image.at<cv::Vec3b>(i * 4, j * 4);
    }
}
//将每个像素按原大小的四倍显示(使用最近点插值)
cv::resize(reduced2, reduced2, cv::Size(), 4, 4, cv::INTER_NEAREST);
cv::imshow("reduced image", reduced2);

在这里插入图片描述
图像质量比直接去除像素要好很多,但也丢失了一些精致的细节。

另外,引出一个定理Nyquist-Shannon定理,即图像缩小一半,其可见的频率带宽也将减少一半。

cv::pyrDown实现图像缩减

OpenCV内置了cv::pyrDown函数实现了图像缩减,其原理是使用5*5的高斯滤波器,先对图像进行低通滤波再进行缩减(只能缩减到1/2)。

其参数分别为原图像、输出图像。

cv::Mat reduced3;
cv::pyrDown(image, reduced3);
cv::imshow("pyrdown", reduced3);

在这里插入图片描述
与此相反,还有一个cv::pyrUp函数可以实现图像尺寸的放大,原理是先在每两行/两列间插入像素值为0的像素,再对扩展后的图像应用5*5的高斯滤波器。

其参数分别为:原图像、输出图像。

cv::Mat enlarged;
cv::pyrUp(image, enlarged);
cv::imshow("pyrup", enlarged);

在这里插入图片描述
上述的两个内置函数只能实现两倍的缩减和放大,其实还有一个更通用的函数cv::resize,可以指定缩放后图像的尺寸。

cv::resize函数的使用

函数签名

CV_EXPORTS_W void resize( InputArray src, OutputArray dst,
                          Size dsize, double fx = 0, double fy = 0,
                          int interpolation = INTER_LINEAR );
  • 参数分别为:原图像,输出图像,输出图像的大小,x方向放大系数,y方向放大系数,插值方法。
  • 可以不指定输出图像的大小(指定为空cv::Size()),则必须指定x和y方向的放大系数,如为2就是放大两倍。
  • 可以不指定放大系数(默认为0),则必须指定输出图像的大小。
  • 此处的插值方法若不指定为双线性插值 cv::INTER_LINEAR ,可以结合多个邻近像素的值,效果较好。此外还有最邻近插值 cv::INTER_LINEAR ,会选区最近的像素点进行插值。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值