用滤波器进行缩减像素采样 - sumpig/OpenCV GitHub Wiki


降低图像精度的过程称为 缩减像素采样(downsampling),提升图像精度的过程称为 提升像素采样(upsampling)。人们通常采用低通滤波器来实现算法。

图像中精致的细节对应着高频,因此需要在缩小图像之前去除它的高频成分。在删除部分列和行之前,必须先在原始图像上应用低通滤波器,这样才能使图像在缩小后不出现伪影。

// 首先去除高频成分
cv::GaussianBlur(image, image, cv::Size(11,11), 2.0);

// 只保留每 4 个像素中的1 个
cv::Mat reduced(image.rows/4, image.cols/4, CV_8U);
for (int i=0; i<reduced.rows; i++)
    for (int j=0; j<reduced.cols; j++)
        reduced.at<uchar>(i,j) = image.at<uchar>(i*4,j*4);

OpenCV 中 cv::pyrDown 函数:,利用这个原理实现了图像缩减:

cv::Mat reducedImage; // 用于存储缩小后的图像
cv::pyrDown(image, reducedImage); // 图像尺寸缩小一半

cv::pyrUp 函数可以放大图像的尺寸。在这种提升像素采样的过程中,先在每两行和每两列之间分别插入值为0 的像素,然后对扩展后的图像应用同样的5×5 高斯滤波器(但系数要扩大 4 倍)。

此外还有一个更通用的函数 cv::resize,它可以指定缩放后图像的尺寸。你只需要在调用它时指定新的尺寸,这个尺寸可以比原始图像小,也可以比原始图像大:

cv::Mat resizedImage; // 用于存储缩放后的图像
cv::resize(image, resizedImage,
           cv::Size(image.cols/4, image.rows/4)); // 行和列均缩小为原来的1/4

你也可以指定缩放比例。在参数中提供一个空的图像实例,然后提供缩放比例:

cv::resize(image, resizedImage,
           cv::Size(), 1.0/4.0, 1.0/4.0); // 缩小为原来的1/4

像素插值

进行插值的最基本方法是使用最近邻策略:

cv::resize(reduced, newImage, cv::Size(), 3, 3, cv::INTER_NEAREST);

把待生成图像的像素网格放在原图像的上方,每个新像素被赋予原图像中最邻近像素的值。当图像升采样(即新网格比原始网格更密集时)时,会根据同一个原始像素,确定新网格中多个像素的值。

更好的做法是在插入新的像素值时,结合多个邻近像素的值。因此,可利用周围四个像素的值,线性地计算新像素值。这种双线性插值方案是 cv::resize 函数的缺省方法。

cv::resize(reduced, newImage, cv::Size(), 4, 4, cv::INTER_LINEAR);
⚠️ **GitHub.com Fallback** ⚠️