目录
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.