OpenCV对图像进行尺寸变换
Posted 卓晴
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenCV对图像进行尺寸变换相关的知识,希望对你有一定的参考价值。
简 介: 本博文给你展示了如何通过指定输出结果的宽高来对图像进行尺寸变化。你也了解如何根据比例因子来保持图像的纵横比不发生变化,从而在改变图像尺寸的过程中图像不发生形变。最后也讨论了不同的插值方法如何改变尺寸变化的结果的。
关键词
: resize,OpenCV,图片尺寸
本文翻译自 Image Resizing with OpenCV中对事OpenCV中对于图像进行尺寸变换。
§00 简 介
下面我们来谈谈如何通过OpenCV来对图片进行尺寸变化。 所谓的图片尺寸变化,就是沿着不同的坐标轴(也就是图片的高、宽)进行收缩,通过指定收缩尺度比例因子或者直接指定结果图片的尺寸(高、宽)。
在进行图片尺寸变换的时候:
- 如果你想保持图片不变形,维持相同的纵横比,则需要注意原始图像的尺寸比例(也就是宽度比上高度的数值)。
- 在降低图片尺寸的时候,需要对于是图像进行重采样。
- 增加图片的尺寸,则要求对图像进行重构,这意味着需要通过插值来获得增加像素点的数值。
不同的插值方法用于完成这些操作。OpenCV也提供了部分这些方法,针对不同的应用可以选择合适的插值方法。
0.1 样例代码
下面的代码通过指定对应的高、宽来对图像 进行拉伸或者压缩。随着你进一步研读代码,我们将进一步讨论是所有不同的尺度因子和插值方法来实现对图像的尺寸变化。
0.1.1 Python代码
# let's start with the Imports
import cv2
import numpy as np
# Read the image using imread function
image = cv2.imread('image.jpg')
cv2.imshow('Original Image', image)
# let's downscale the image using new width and height
down_width = 300
down_height = 200
down_points = (down_width, down_height)
resized_down = cv2.resize(image, down_points, interpolation= cv2.INTER_LINEAR)
# let's upscale the image using new width and height
up_width = 600
up_height = 400
up_points = (up_width, up_height)
resized_up = cv2.resize(image, up_points, interpolation= cv2.INTER_LINEAR)
# Display images
cv2.imshow('Resized Down by defining height and width', resized_down)
cv2.waitKey()
cv2.imshow('Resized Up image by defining height and width', resized_up)
cv2.waitKey()
#press any key to close the windows
cv2.destroyAllWindows()
0.1.2 C语言代码
// let's start with including libraries
#include<opencv2/opencv.hpp>
#include<iostream>
// Namespace to nullify use of cv::function(); syntax
using namespace std;
using namespace cv;
int main()
// Read the image using imread function
Mat image = imread("image.jpg");
imshow("Original Image", image);
// let's downscale the image using new width and height
int down_width = 300;
int down_height = 200;
Mat resized_down;
//resize down
resize(image, resized_down, Size(down_width, down_height), INTER_LINEAR);
// let's upscale the image using new width and height
int up_width = 600;
int up_height = 400;
Mat resized_up;
//resize up
resize(image, resized_up, Size(up_width, up_height), INTER_LINEAR);
// Display Images and press any key to continue
imshow("Resized Down by defining height and width", resized_down);
waitKey();
imshow("Resized Up image by defining height and width", resized_up);
waitKey();
destroyAllWindows();
return 0;
§01 读入图像
首先导入所需要的软件包。
- Python
# Importing the libraries
import cv2
import numpy as np
- C++
#include<opencv2/opencv.hpp>
#include<iostream>
// Namespace to nullify use of cv::function(); syntax
using namespace std;
using namespace cv;
下面这两漂亮的跑车就是下面代码测试中所使用的图片。
▲ 图1.1 用于实验的图片:一辆漂亮的跑车
- Python
# Reading image
image= cv2.imread('image.jpg')
- C++
// Reading image
Mat image = imread("image.jpg");
请注意在上面的C++代码片段中,你需要先创先一个图像的矩阵实例,然后通过 imread() 函数读取图片。
在你开始对图片进行尺寸变化之前,你需要先了解他的原始尺寸。通过以下方式方式可以获得图片的尺寸:
- 使用 python中的 shape方法;
- 在C++中通过 rows 和 cols 获得;
image.shape是在Python中可以 获得对应的图像的高、宽以及颜色通道的数量。
在C++中:
- image.rows给出的图片的高;
- image.columns 给出了图片的宽度;
也可通过size()函数获得上述结果:
-
image.size().width:返回宽度;
-
image.size().height返回高度是数值。
-
Python
# Get original height and width
h,w,c = image.shape
print("Original Height and Width:", h,"x", w)
- C++
// Get height and width
cout << "Original Height and Width :" << image.rows << "x" << image.cols << endl;
一个重要事情需要记住,在OpenCV中输出的图片的形状为:heightwidthchannels的格式,但一些其他的上T片处理库则使用 width*height的格式。因此需要注意这方面的逻辑差异。
OpenCV读取图片之后,在内存使用NumPy矩阵存储图片数据,所以一般情况下,你总可以通过矩阵的形状来确定图片的尺寸,也就是通过 rowscolumns(rows代表图片的高度,columns代表图片的宽度)。 因此,计时通过OpenCV过得他们的 形状,NumpPy矩阵法则在此也起作用。你所得到的图片数据形状为 heightwidth*channels。
§02 尺寸变化
下面让我们看看 OpenCV中的尺寸变化函数 resize() 的调用语法。 可以注意到它只要两个必须输入参数,其他参数都可以省略。
1. 源图像;
2. 所需要变化后的图像尺寸, dsize
下面是resize的调用格式,后面给出了参数定义。
resize(src, dsize[, dst[, fx[, fy[, interpolation]]]])
- rc: It is the required input image, it could be a string with the path of the input image (eg: ‘test_image.png’).
- dsize: It is the desired size of the output image, it can be a new height and width.
- fx: Scale factor along the horizontal axis.
- fy: Scale factor along the vertical axis.
- interpolation: It gives us the option of different methods of resizing the image.
§03 指定宽高
下面的例子是通过指定新的图像的宽高来对图像进行缩小。在下面的代码中:
-
我们设置结果图像的宽为300, 高为200;
-
这两个数字使用2D向量表示,这是resize() 函数要求的;
-
我们同样指明插值的方法,这也是缺省的参数;
-
Python
# Set rows and columns
# lets downsize the image using new width and height
down_width = 300
down_height = 200
down_points = (down_width, down_height)
resize_down = cv2.resize(image, down_points, interpolation= cv2.INTER_LINEAR)
- C++
// Set rows and columns
// lets downsize the image using new width and height
int down_width = 300;
int down_height = 200;
Mat resize_down;
// resize down
resize(image, resize_down, Size(down_width, down_height), INTER_LINEAR);
下面我们使用另外的尺寸来变换图像。
- Python
# Set rows and columns
up_width = 600
up_height = 400
up_points = (up_width, up_height)
# resize the image
resized_up = cv2.resize(image, up_points, interpolation = cv2.INTER_LINEAR)
- C++
// Set rows and columns
int up_width = 600;
int up_height = 400;
Mat resized_up;
//resize up
resize(image, resized_up, Size(up_width, up_height), INTER_LINEAR);
在上面Python代码片段中,我们通过定义型的宽、高来拉伸原始图像,这都是通过 resize() 这个函数,处理过程与前面缩小图像的过程是一样的。
在C++的代码片段中:
- 我们通过定出了新的宽、高整形数来拉伸图像;
- 获得了输出图的矩阵;
- 使用相同的 resize() 函数进行上述操作;
现在,我们通过OpenCV中的imshow()来显示变化后的图像。
- Python
# Display images
cv2.imshow('Resized Down by defining height and width', resized_down)
cv2.waitKey()
cv2.imshow('Resized Up image by defining height and width', resized_up)
cv2.waitKey()
cv2.destroyAllWindows()
- C++
// Display Images and press any key to continue
imshow("Resized Down by defining height and width", resized_down);
waitKey();
imshow("Resized Up image by defining height and width", resized_up);
waitKey();
destroyAllWindows();
▲ 图3.1 尺寸变化后的两个图像:左:缩小尺寸;右:拉伸尺寸
上面图像中,左边的图像是缩小的图片,右边的图像是拉伸后的图片。
正如我们期望的那样,我们通过resize改变了图像的尺寸,图像可以增大,也可以缩小,这都是根据给定的高和宽参数来决定的。
但我们可以感觉得,通过这样指明高和宽参数来改变图像的大小,对于图像来说好像出现了变形,也就是图像的宽高比发生了改变,也就是图像的纵横比例发生的改变。
怎么纠正这个问题呢。好的,下面我们可以通过指定比例因子来进行尺寸变换。
§04 指定比例
OK,下面我们通过指定比例因子来改变图片的尺寸。不过首先需要了解什么事比例因子。
比例因子,也称尺度因子也就是一个数字,用于乘以,或者按比例改变某些数值。在我们对图片处理中,也就是将该数字乘以图像的宽、高。这样可以保持图像的本身的纵横比例不发生改变,进而保持图像的质量。因此图像在你进行拉伸或者压缩的过程中也不会显得发生了变形。
- Python
# Scaling Up the image 1.2 times by specifying both scaling factors
scale_up_x = 1.2
scale_up_y = 1.2
# Scaling Down the image 0.6 times specifying a single scale factor.
scale_down = 0.6
scaled_f_down = cv2.resize(image, None, fx= scale_down, fy= scale_down, interpolation= cv2.INTER_LINEAR)
scaled_f_up = cv2.resize(image, None, fx= scale_up_x, fy= scale_up_y, interpolation= cv2.INTER_LINEAR)
- C++
// Scaling Up the image 1.2 times by specifying both scaling factors
double scale_up_x = 1.2;
double scale_up_y = 1.2;
// Scaling Down the image 0.6 times specifying a single scale factor.
double scale_down = 0.6;
Mat scaled_f_up, scaled_f_down;
//resize
resize(image,scaled_f_down, Size(), scale_down, scale_down, INTER_LINEAR);
resize(image, scaled_f_up, Size(), scale_up_x, scale_up_y, INTER_LINEAR);
在上面的Python代码片段中:
- 我们定义了新的沿着水平和垂直方向上的比例因子;
- 通过比例因子,省略了指明宽和高的像素个数,所以对应的dsize为 None;
在上面的C++代码片段中:
- 通过指明型的比例因子来改变图像数据矩阵;
- 所以也不需要额外指明矩阵的高和宽,对应的Size()是一个空向量;
下面通过显示结果图像可以更好地理解变换的结果。
- Python
# Display images and press any key to check next image
cv2.imshow('Resized Down by defining scaling factor', scaled_f_down)
cv2.waitKey()
cv2.imshow('Resized Up image by defining scaling factor', scaled_f_up)
cv2.waitKey()
- C++
// Display images and Press any key to continue check next image
imshow("Resized Down by defining scaling factor", scaled_f_down);
waitKey();
imshow("Resized Up by defining scaling factor", scaled_f_up);
waitKey();
▲ 图4.1 通过指明比例因子对图像进行拉伸和缩小的结果
左边的图像是缩小的图片,右边则是拉伸的图片。
§05 插值方法
下面讨论一下不同的插值方法用于图片的尺寸变化。
下面给出了不同的插值方法选项所对应的变化方法。
- INTER_AREA: INTER_AREA uses pixel area relation for resampling. This is best suited for reducing the size of an image (shrinking). When used for zooming into the image, it uses the INTER_NEAREST method.
- INTER_CUBIC: This uses bicubic interpolation for resizing the image. While resizing and interpolating new pixels, this method acts on the 4×4 neighboring pixels of the image. It then takes the weights average of the 16 pixels to create the new interpolated pixel.
- INTER_LINEAR: This method is somewhat similar to the INTER_CUBIC interpolation. But unlike INTER_CUBIC, this uses 2×2 neighboring pixels to get the weighted average for the interpolated pixel.
- INTER_NEAREST: The INTER_NEAREST method uses the nearest neighbor concept for interpolation. This is one of the simplest methods, using only one neighboring pixel from the image for interpolation.
不易担心,如果你不完全理解上述方法的函数,后面还会通过不同的博文来进行展示。
- Python
# Scaling Down the image 0.6 times using different Interpolation Method
res_inter_nearest = cv2.resize(image, None, fx= scale_down, fy= scale_down, interpolation= cv2.INTER_NEAREST)
res_inter_linear = cv2.resize以上是关于OpenCV对图像进行尺寸变换的主要内容,如果未能解决你的问题,请参考以下文章