OpenCV的resize方法4种插值方法效果对比器
resize方法
OpenCV中的resize方法是一种用于调整图像尺寸的函数。它可以将图像缩放到指定的尺寸,或者按比例放大或缩小图像。
dst = cv2.resize(src, dsize, fx=None, fy=None,
interpolation=cv2.INTER_LINEAR)
参数说明:
- src:输入的原始图像。
- dsize:输出图像的目标尺寸,是一个包含宽度和高度的元组(width, height)。当dsize不为零时,它表示输出图像的确切尺寸。
- fx:沿水平轴的缩放因子。默认为None,表示不进行水平缩放。如果dsize为零,则可以通过fx和fy来指定缩放因子。
- fy:沿垂直轴的缩放因子。默认为None,表示不进行垂直缩放。
- interpolation:插值方法,用于指定如何在原始图像和目标图像之间进行插值。
插值方法介绍
最近邻插值(cv2.INTER_NEAREST):
- 该方法是从输入图像中最接近目标像素的位置获取像素值。
- 优点:计算速度快。
- 缺点:在放大图像时可能会导致图像出现像素化的效果,质量较差。
双线性插值(cv2.INTER_LINEAR):
- 该方法通过对周围像素进行加权平均来计算目标像素的值。
- 优点:速度较快,质量较好,可以有效减少图像的锯齿和模糊。
- 缺点:可能导致一些细节丢失。
双三次插值(cv2.INTER_CUBIC):
- 该方法使用周围4x4像素的立方函数来计算目标像素的值。
- 优点:速度适中,质量较好。
- 缺点:相比双线性插值计算更复杂。
区域像素混合插值(cv2.INTER_AREA)
- 该方法通过考虑目标像素周围的像素值来计算目标像素的值。
- 优点:在图像抽取(decimation)时能提供较好的效果。
- 缺点:在放大图像时,效果可能类似于最近邻插值法。
效果
代码
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QFileDialog, QLabel, QGridLayout, QHBoxLayout, QVBoxLayout, \
QWidget, QPushButton
from PyQt5.QtGui import QPixmap, QImage
from PyQt5.QtCore import Qt
import cv2
class ImageResizeWindow(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setWindowTitle('Image Resize with Interpolation')
self.setGeometry(100, 100, 1200, 900)
# 创建垂直布局
vertical_layout = QVBoxLayout()
# 创建按钮用于打开文件对话框
self.open_button = QPushButton('Open Image', self)
self.open_button.clicked.connect(self.loadImage)
vertical_layout.addWidget(self.open_button)
# 创建中心部件
central_widget = QWidget()
central_widget.setLayout(vertical_layout)
self.setCentralWidget(central_widget)
def loadImage(self):
options = QFileDialog.Options()
options |= QFileDialog.DontUseNativeDialog
file_name, _ = QFileDialog.getOpenFileName(self, "Open Image", "",
"All Files (*);;;PNG Files (*.png);;;JPG Files (*.jpg)",
options=options)
if file_name:
# 读取图片
self.original_image = cv2.imread(file_name)
# 将图片转换为Qt可以显示的格式
qt_image = QImage(self.original_image.data, self.original_image.shape[1], self.original_image.shape[0],
QImage.Format_RGB888).rgbSwapped()
self.original_pixmap = QPixmap.fromImage(qt_image)
# 创建水平布局来放置所有图片
horizontal_layout = QHBoxLayout()
# 添加原图
self.original_label = QLabel(self)
self.original_label.setPixmap(self.original_pixmap)
horizontal_layout.addWidget(self.original_label)
# 创建2x2的网格布局来放置插值图片
grid_layout = QGridLayout()
self.interpolation_labels = {}
interpolations = ['Nearest', 'Linear', 'Cubic', 'Lanczos']
for i, interpolation in enumerate(interpolations):
resized_image = self.resizeImage(interpolation)
qt_resized_image = QImage(resized_image.data, resized_image.shape[1], resized_image.shape[0],
QImage.Format_RGB888).rgbSwapped()
resized_pixmap = QPixmap.fromImage(qt_resized_image)
# 创建一个垂直布局,将图片和名字标签放入其中
vertical_layout = QVBoxLayout()
label = QLabel(self)
label.setPixmap(resized_pixmap)
vertical_layout.addWidget(label)
name_label = QLabel(interpolation, self)
#name_label.setAlignment(Qt.AlignVCenter) # 设置名字标签垂直居中对齐
vertical_layout.addWidget(name_label)
vertical_layout.setAlignment(Qt.AlignCenter)
# 将垂直布局添加到网格布局中
grid_layout.addLayout(vertical_layout, i // 2, i % 2)
self.interpolation_labels[interpolation] = (label, name_label)
# 将网格布局放入一个QWidget中,以便可以添加到水平布局中
grid_widget = QWidget()
grid_widget.setLayout(grid_layout)
horizontal_layout.addWidget(grid_widget)
# 将水平布局添加到垂直布局中
vertical_layout = self.centralWidget().layout()
vertical_layout.addLayout(horizontal_layout)
def resizeImage(self, interpolation):
# 原始图片的尺寸
original_height, original_width = self.original_image.shape[:2]
new_size = (int(original_width * 2), int(original_height * 2))
# 使用指定的插值方法进行缩放
resized_image = cv2.resize(self.original_image, new_size,
interpolation=cv2.INTER_CUBIC if interpolation == 'Cubic' else
cv2.INTER_LANCZOS4 if interpolation == 'Lanczos' else
getattr(cv2, f'INTER_{interpolation.upper()}'))
return resized_image
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = ImageResizeWindow()
ex.show()
sys.exit(app.exec_())