目录
一,图像缩放
图像的缩放可以使用图像金字塔,也可以使用图像插值,每一种算法都既可以用于放大,也可以用于缩小。
二,图像金字塔(pyrUp、pyrDown)
1,缩放
用pyrUp实现放大2倍,pyrDown实现缩小2倍
string path = "D:\im.jpg";
Mat image = imread(path, IMREAD_COLOR);
namedWindow("1", WINDOW_GUI_NORMAL);
Mat image2, image3;
pyrUp(image, image2);
pyrDown(image, image3);
imshow("1", image);
imshow("2", image2);
imshow("3", image3);
waitKey(0);
结果:
如果进行多次的放大缩小:
Mat image2, image3;
pyrUp(image, image2);
pyrDown(image2, image3);
pyrUp(image3, image2);
pyrDown(image2, image3);
pyrUp(image3, image2);
pyrDown(image2, image3);
imshow("1", image);
imshow("3", image3);
结果:

很明显,多次放大缩小之后会越来越模糊。
2,高斯缩放
缩小:
首先进行高斯模糊卷积(Convolution)_nameofcsdn的博客-优快云博客
然后把所有的偶数行和偶数列都删掉,就得到了缩小2倍的图片。
放大:
首先隔行隔列插入新的行列,值为0,然后进行高斯模糊,最后所有像素乘以4倍。
pyrUp、pyrDown的实现就是高斯缩放。
3,高斯金字塔
利用高斯缩小,不断的缩小2倍,直到变成满足条件的尺寸,中间过程组织起来共同构成一个金字塔:

4,拉普拉斯差值
任意一张图片,先高斯缩小,再高斯放大,就会得到接近原图的图,但是会略有差异。
把2张图的所有像素的差值都存起来,我们称之为原图的拉普拉斯差值。
利用缩小之后的图和拉普拉斯差值,即可得到原图。
5,拉普拉斯金字塔
对高斯金字塔的每一级,计算拉普拉斯差值,所有的拉普拉斯差值组织起来共同构成一个金字塔,叫拉普拉斯金字塔。
也就是说,拉普拉斯金字塔和高斯金字塔是对应的。
三,图像插值
图像插值是给定一个像素点,根据它周围像素点的信息来对该像素点的值进行预测。
常见的插值方式:
import cv2
image = cv2.imread("D:/im.jpg", 0)
cv2.imshow("img",image)
image2 = cv2.resize(image,(300,500),cv2.INTER_NEAREST)
cv2.imshow("img2",image2)
image3 = cv2.resize(image,(300,500),cv2.INTER_LINEAR)
cv2.imshow("img3",image3)
image4 = cv2.resize(image,(300,500),cv2.INTER_CUBIC)
cv2.waitKey(0)
1,最近邻插值 INTER_NEAREST

根据最近的像素点来取值
2,双线性插值 INTER_LINEAR
根据四个角落的像素值,进行加权平均:

也可以表示成方程组的形式:
![]()
把四个角落的点代入得到四个方程,求出系数a b c d,从而得到v(x,y)
3,双三次插值 INTER_CUBIC

根据最近的16个点,算出16个系数,从而得到v(x,y)
四,边界扩充插值
有时我们需要把图像扩充一点点,需要在边界处使用插值算法。
1,坐标计算 borderInterpolate
C++接口:
int borderInterpolate(int p, int len, int borderType);
copy.cpp中有borderInterpolate的实现,其中第三个参数borderType的类型是BorderTypes枚举类型:
enum BorderTypes {
BORDER_CONSTANT = 0, //!< `iiiiii|abcdefgh|iiiiiii` with some specified `i`
BORDER_REPLICATE = 1, //!< `aaaaaa|abcdefgh|hhhhhhh`
BORDER_REFLECT = 2, //!< `fedcba|abcdefgh|hgfedcb`
BORDER_WRAP = 3, //!< `cdefgh|abcdefgh|abcdefg`
BORDER_REFLECT_101 = 4, //!< `gfedcb|abcdefgh|gfedcba`
BORDER_TRANSPARENT = 5, //!< `uvwxyz|abcdefgh|ijklmno`
BORDER_REFLECT101 = BORDER_REFLECT_101, //!< same as BORDER_REFLECT_101
BORDER_DEFAULT = BORDER_REFLECT_101, //!< same as BORDER_REFLECT_101
BORDER_ISOLATED = 16 //!< do not look outside of ROI
};
2,边界扩充 copyMakeBorder
void copyMakeBorder(InputArray src, OutputArray dst,
int top, int bottom, int left, int right,
int borderType, const Scalar& value = Scalar() );
copy.cpp中有copyMakeBorder的实现,截选片段:
if( borderType != BORDER_CONSTANT )
copyMakeBorder_8u( src.ptr(), src.step, src.size(),
dst.ptr(), dst.step, dst.size(),
top, left, (int)src.elemSize(), borderType );
else
{
int cn = src.channels(), cn1 = cn;
AutoBuffer<double> buf(cn);
if( cn > 4 )
{
CV_Assert( value[0] == value[1] && value[0] == value[2] && value[0] == value[3] );
cn1 = 1;
}
scalarToRawData(value, buf.data(), CV_MAKETYPE(src.depth(), cn1), cn);
copyMakeConstBorder_8u( src.ptr(), src.step, src.size(),
dst.ptr(), dst.step, dst.size(),
top, left, (int)src.elemSize(), (uchar*)buf.data() );
}
其中copyMakeBorder_8u会调用borderInterpolate
五,滚动条缩放
int maxScaleUp = 100;
int scaleFactor = 0;
string windowName = "Resize Image";
string trackbarValue = "Scale";
void scaleImage(int, void*)
{
Mat image = imread("D:/2.png");
// Get the Scale factor from the trackbar
double scaleFactorDouble = 1 + scaleFactor / 100.0;
Mat scaledImage;
// Resize the image
resize(image, scaledImage, Size(), scaleFactorDouble, scaleFactorDouble, INTER_LINEAR);
imshow(windowName, scaledImage);
waitKey(0);
//destroyAllWindows();
}
int main()
{
Mat image = imread("D:/2.png");
namedWindow(windowName, WINDOW_AUTOSIZE);
createTrackbar(trackbarValue, windowName, &scaleFactor, maxScaleUp, scaleImage);
scaleImage(25, 0);
return 0;
}

本文详细介绍了OpenCV中图像缩放的方法,包括图像金字塔(pyrUp、pyrDown)的原理与应用,如高斯缩放、高斯金字塔和拉普拉斯金字塔。同时,讨论了图像插值的不同方式,如最近邻、双线性及双三次插值,并解释了边界扩充插值的重要性。此外,还提及了滚动条缩放的概念。

348





