2020-12-28 learning opencv3: 十一:resize, pyrDown, buildPyramid, pyrUp

目录

cv::resize()

Image Pyramids

pyrDown()

buildPyramid()

pyrUp()

The Laplacian pyramid


cv::resize()
 

void cv::resize(
cv::InputArray src, // Input image
cv::OutputArray dst, // Result image
cv::Size dsize, // New size
double fx = 0, // x-rescale
double fy = 0, // y-rescale
int interpolation = CV::INTER_LINEAR // interpolation method
);

We can specify the size of the output image in two ways. One way is to use absolute
sizing; in this case, the dsize argument directly sets the size we would like the result
image dst to be. The other option is to use relative sizing; in this case, we set dsize to
cv::Size(0,0), and set fx and fy to the scale factors
we would like to apply to the xand y-axes, respectively.1 The last argument is the interpolation method, which
defaults to linear interpolation.

Image Pyramids
 

Image pyramids [Adelson84] are heavily used in a wide variety of vision applications.
An image pyramid is a collection of images—all arising from a single original image
—that are successively downsampled until some desired stopping point is reached.
(This stopping point could be a single-pixel image!)


There are two kinds of image pyramids that arise often in the literature and in appli‐
cations: the Gaussian [Rosenfeld80] and Laplacian [Burt83] pyramids [Adelson84].

The Gaussian pyramid is used to downsample images, and the Laplacian pyramid
(discussed shortly) is required when we want to reconstruct an upsampled image
from an image lower in the pyramid.
 

pyrDown()
 

void cv::pyrDown(
cv::InputArray src, // Input image
cv::OutputArray dst, // Result image
const cv::Size& dstsize = cv::Size() // Output image size
);

The cv::pyrDown() method will do exactly this for us if we leave the destination size
argument dstsize set to its default value of cv::Size(). To be a little more specific,
the default size of the output image is ( (src.cols+1)/2, (src.rows+1)/2 ).4
Alternatively, we can supply a dstsize, which will indicate the size we would like for
the output image; dstsize, however, must obey some very strict constraints. Specifi‐
cally
 

| dstsize.width*2 - src.cols | ≤ 2
| dstsize.height *2 - src.rows | ≤ 2
这个值会在图像长宽一半的附件,并且可以用的值范围很小,所以Size两个值自己输入想要的大小时要注意,不然程序会出错

#include <opencv2/opencv.hpp>

using namespace cv;

void copyPixel(const Mat& src, Mat& dst)
{
	for (size_t i = 0; i < src.rows; i++)
	{
		for (size_t j = 0; j < src.cols; j++)
		{
			dst.at<Vec3b>(i, j)[0] = src.at<Vec3b>(i, j)[0];  //蓝色通道
			dst.at<Vec3b>(i, j)[1] = src.at<Vec3b>(i, j)[1];  //绿色通道
			dst.at<Vec3b>(i, j)[2] = src.at<Vec3b>(i, j)[2];  //红是通道
		}
	}
}


int main()
{
	Mat src = imread("NWPULB.jpg", IMREAD_COLOR);
	int width = src.cols / 6;
	int height = src.rows / 6;

	//resize(src, src, Size(width, height));
	resize(src, src, Size(0, 0), 0.15, 0.15);
	Mat pyrSrc;
	//pyrDown(src, pyrSrc, Size(400, 300));
	pyrDown(src, pyrSrc, Size(0, 0));

	Mat image = Mat(Size(2*width, height), src.type());
	namedWindow("image", 1);
	//imshow("images", src);

	if (src.empty())
	{
		std::cout << "Could not open or find the image!\n" << std::endl;
		return EXIT_FAILURE;
	}
	

	Mat imageWarp = Mat(Size(src.cols, src.rows), src.type());
	Mat warp = (Mat_<float>(2, 3) << 1, 0, src.cols-1, 0, 1, 0);

	//warpAffine(src, imageWarp, warp, Size(2 * src.cols, src.rows));
	warpAffine(pyrSrc, imageWarp, warp, Size(2 * src.cols, src.rows));
	//imshow("image", imageWarp);

	copyPixel(src, imageWarp);
	imshow("image", imageWarp);
	waitKey();

	destroyWindow("image");

	return 0;
}

(4000,5328)-------resize后------》(600, 799)------>现在计算pyDown时自己输入长宽的值

393.5<= width <= 400.5

299<=height <= 301     所以自己输入时值并不可以“随便取”

This restriction means that the destination image is very close to half the size of the
source image. The dstsize argument is used only for handling somewhat esoteric
cases in which very tight control is needed on how the pyramid is constructed.

buildPyramid()
 

It is a relatively common situation that you have an image and wish to build a
sequence of new images that are each downscaled from their predecessor. The func‐
tion cv::buildPyramid() creates such a stack of images for you in a single call
 

void cv::buildPyramid(
cv::InputArray src, // Input image
cv::OutputArrayOfArrays dst, // Output images from pyramid
int maxlevel // Number of pyramid levels
);

The argument src is the source image. The argument dst is of a somewhat unusuallooking type cv::OutputArrayOfArrays, but you can think of this as just being an
STL vector<> or objects of type cv::OutputArray. The most common example of this would be vector<cv::Mat>. The argument maxlevel indicates how many pyramid levels are to be constructed

#include <opencv2/opencv.hpp>
#include <algorithm>
#pragma warning(disable:4996) 

using namespace cv;
using namespace std;

void copyPixel(const Mat& src, Mat& dst)
{
	for (size_t i = 0; i < src.rows; i++)
	{
		for (size_t j = 0; j < src.cols; j++)
		{
			dst.at<Vec3b>(i, j)[0] = src.at<Vec3b>(i, j)[0];  //蓝色通道
			dst.at<Vec3b>(i, j)[1] = src.at<Vec3b>(i, j)[1];  //绿色通道
			dst.at<Vec3b>(i, j)[2] = src.at<Vec3b>(i, j)[2];  //红是通道
		}
	}
}


int main()
{
	Mat src = imread("NWPULB.jpg", IMREAD_COLOR);

	if (src.empty())
	{
		std::cout << "Could not open or find the image!\n" << std::endl;
		return EXIT_FAILURE;
	}
	
	int width = src.cols / 6;
	int height = src.rows / 6;

	//resize(src, src, Size(width, height));
	resize(src, src, Size(0, 0), 0.15, 0.15);
	Mat pyrSrc;
	//pyrDown(src, pyrSrc, Size(400, 300));
	//pyrDown(src, pyrSrc, Size(0, 0));

	Mat image = Mat(Size(2 * width, height), src.type());
	namedWindow("image", 1);
	//imshow("images", src);
	vector<Mat> buildPyts;

	buildPyramid(src, buildPyts, 4);
	Mat imageWarp = Mat(Size(src.cols, src.rows), src.type());
	Mat warp;

	char* name = new char;
	for (size_t i = 0; i < buildPyts.size(); i++)
	{
		warp = (Mat_<float>(2, 3) << 1, 0, src.cols + i*50, 0, 1, 0);
		warpAffine(buildPyts[4-i], imageWarp, warp, Size(2 * src.cols, src.rows));
		sprintf(name, "pyts%d", i);
		imshow(name, buildPyts[i]);
	}

	copyPixel(src, imageWarp);
	imshow("image", imageWarp);
	waitKey();

	destroyWindow("image");

	return 0;
}

In practice, you will often want a pyramid with a finer logarithmic
scaling than factors of two. One way to achieve this is to simply call
cv::resize() yourself as many times as needed for whatever scale
factor you want to use—but this can be quite slow. An alternative
(for some common scale factors) is to call cv::resize() only once
for each interleaved set of images you want, and then call
cv::buildPyramid() on each of those resized “bases.” You can
then interleave these results together for one large, finer-grained
pyramid. Figure 11-1 (right) shows an example in which two pyra‐
mids are generated. The original image is first rescaled by a factor
of 2, and then cv::buildPyramid() is called on that one image to
make a second pyramid of four intermediate images. Once com‐
bined with the original pyramid, the result is a finer pyramid with a
scale factor of 2 across the entire pyramid.

pyrUp()
 

Analogous to cv::PyrDown(), if dstsize is set to its default value of cv::Size(), the
resulting image will be exactly twice the size (in each dimension) as src. Again, we
can supply a dstsize that will indicate the size we would like for the output image
dstsize, but it must again obey some very strict constraints. Specifically:

| dstsize.width*2 - src.cols | ≤ (dstsize.width%2)
| dstsize.height *2 - src.rows | ≤ (dstsize.height %2)

 

The Laplacian pyramid
 

We noted previously that the operator cv::pyrUp() is not the inverse of cv::pyr
Down(). This should be evident because cv::pyrDown() is an operator that loses
information. In order to restore the original (higher-resolution) image, we would
require access to the information that was discarded by the downsampling process.
This data forms the Laplacian pyramid.

The Gaussian and Laplacian pyramids are shown diagrammatically in Figure 11-2,
which also shows the inverse process for recovering the original image from the sub‐
images. Note how the Laplacian is really an approximation that uses the difference of
Gaussians, as revealed in the preceding equation and diagrammed in the figure.

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值