Opencv 图像缩放

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

目录

一,图像缩放

二,图像金字塔(pyrUp、pyrDown)

1,缩放

2,高斯缩放

3,高斯金字塔

4,拉普拉斯差值

5,拉普拉斯金字塔

三,图像插值

1,最近邻插值 INTER_NEAREST

2,双线性插值 INTER_LINEAR

3,双三次插值 INTER_CUBIC

四,边界扩充插值

1,坐标计算 borderInterpolate

2,边界扩充 copyMakeBorder

五,滚动条缩放


一,图像缩放

图像的缩放可以使用图像金字塔,也可以使用图像插值,每一种算法都既可以用于放大,也可以用于缩小。

二,图像金字塔(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;
}

 

评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值