|
|
# -*- coding: utf-8 -*-
|
|
|
import sys
|
|
|
import cv2
|
|
|
import math
|
|
|
from PyQt5.QtCore import QRect, QCoreApplication, QMetaObject, Qt
|
|
|
from PyQt5.QtGui import QImage, QPixmap
|
|
|
from PyQt5.QtWidgets import QMainWindow, QApplication, QMenuBar, QWidget, QPushButton, QGraphicsView, QGraphicsScene, \
|
|
|
QFileDialog, QStatusBar, QMessageBox
|
|
|
|
|
|
|
|
|
class Ui_MainWindow(object):
|
|
|
def setupUi(self, MainWindow):
|
|
|
if not MainWindow.objectName():
|
|
|
MainWindow.setObjectName("MainWindow")
|
|
|
MainWindow.resize(800, 600)
|
|
|
self.centralwidget = QWidget(MainWindow)
|
|
|
self.centralwidget.setObjectName("centralwidget")
|
|
|
|
|
|
self.pushButton_1 = QPushButton(self.centralwidget)
|
|
|
self.pushButton_1.setObjectName("pushButton_1")
|
|
|
self.pushButton_1.setGeometry(QRect(80, 470, 191, 71))
|
|
|
|
|
|
self.pushButton_2 = QPushButton(self.centralwidget)
|
|
|
self.pushButton_2.setObjectName("pushButton_2")
|
|
|
self.pushButton_2.setGeometry(QRect(300, 470, 201, 71))
|
|
|
|
|
|
self.pushButton_3 = QPushButton(self.centralwidget)
|
|
|
self.pushButton_3.setObjectName("pushButton_3")
|
|
|
self.pushButton_3.setGeometry(QRect(530, 470, 201, 71))
|
|
|
|
|
|
self.graphicsView = QGraphicsView(self.centralwidget)
|
|
|
self.graphicsView.setObjectName("graphicsView")
|
|
|
self.graphicsView.setGeometry(QRect(70, 60, 275, 330))
|
|
|
|
|
|
self.graphicsView_2 = QGraphicsView(self.centralwidget)
|
|
|
self.graphicsView_2.setObjectName("graphicsView_2")
|
|
|
self.graphicsView_2.setGeometry(QRect(450, 60, 280, 330))
|
|
|
MainWindow.setCentralWidget(self.centralwidget)
|
|
|
self.menubar = QMenuBar(MainWindow)
|
|
|
self.menubar.setObjectName("menubar")
|
|
|
self.menubar.setGeometry(QRect(0, 0, 800, 23))
|
|
|
MainWindow.setMenuBar(self.menubar)
|
|
|
self.statusbar = QStatusBar(MainWindow)
|
|
|
self.statusbar.setObjectName("statusbar")
|
|
|
MainWindow.setStatusBar(self.statusbar)
|
|
|
|
|
|
self.retranslateUi(MainWindow)
|
|
|
QMetaObject.connectSlotsByName(MainWindow)
|
|
|
|
|
|
def retranslateUi(self, MainWindow):
|
|
|
MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", "MainWindow", None))
|
|
|
self.pushButton_2.setText(QCoreApplication.translate("MainWindow", "Apply Funny Mirror", None))
|
|
|
self.pushButton_1.setText(QCoreApplication.translate("MainWindow", "Select Image", None))
|
|
|
self.pushButton_3.setText(QCoreApplication.translate("MainWindow", "Save Image", None))
|
|
|
|
|
|
def enlarge_effect(img):
|
|
|
#获取图像的高度 h,宽度 w,和颜色通道数
|
|
|
h, w, n = img.shape
|
|
|
#计算图像的中心点坐标
|
|
|
cx = w / 2
|
|
|
cy = h / 2
|
|
|
#定义影响的区域
|
|
|
radius = min(h, w) // 2
|
|
|
r = int(radius / 2.0)
|
|
|
#创建原始图像的一个副本,在这个副本上应用效果
|
|
|
new_img = img.copy()
|
|
|
#用双重循环来遍历图像的每一个像素
|
|
|
for i in range(w):
|
|
|
for j in range(h):
|
|
|
tx = i - cx
|
|
|
ty = j - cy
|
|
|
distance = tx * tx + ty * ty
|
|
|
#判断当前像素是否在影响范围内
|
|
|
if distance < radius * radius:
|
|
|
#图像中心区域的像素进行重新映射,创建一种放大效果
|
|
|
x = int(int(tx / 2.0) * (math.sqrt(distance) / r) + cx)
|
|
|
y = int(int(ty / 2.0) * (math.sqrt(distance) / r) + cy)
|
|
|
if 0 <= x < w and 0 <= y < h: # 添加边界检查
|
|
|
new_img[j, i, 0] = img[y, x, 0]
|
|
|
new_img[j, i, 1] = img[y, x, 1]
|
|
|
new_img[j, i, 2] = img[y, x, 2]
|
|
|
return new_img
|
|
|
|
|
|
class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
def __init__(self):
|
|
|
super(MainWindow, self).__init__()
|
|
|
self.setupUi(self)
|
|
|
self.pushButton_1.clicked.connect(self.select_image)
|
|
|
self.pushButton_2.clicked.connect(self.apply_effect)
|
|
|
self.pushButton_3.clicked.connect(self.save_image)
|
|
|
self.input_img = None
|
|
|
self.output_img = None
|
|
|
|
|
|
def select_image(self):
|
|
|
options = QFileDialog.Options()
|
|
|
fileName, _ = QFileDialog.getOpenFileName(self, "Select Image", "", "Image Files (*.png *.jpg *.bmp)", options=options)
|
|
|
if fileName:
|
|
|
self.input_img = cv2.imread(fileName)
|
|
|
if self.input_img is None:
|
|
|
print("Error: Unable to read image file")
|
|
|
return
|
|
|
self.show_image(self.input_img, self.graphicsView)
|
|
|
|
|
|
def apply_effect(self):
|
|
|
if self.input_img is None:
|
|
|
return
|
|
|
self.output_img = enlarge_effect(self.input_img)
|
|
|
self.show_image(self.output_img, self.graphicsView_2)
|
|
|
|
|
|
def show_image(self, img, view):
|
|
|
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
|
|
|
h, w, ch = img_rgb.shape
|
|
|
bytes_per_line = ch * w
|
|
|
qimg = QImage(img_rgb.data, w, h, bytes_per_line, QImage.Format_RGB888)
|
|
|
pixmap = QPixmap.fromImage(qimg)
|
|
|
scene = QGraphicsScene()
|
|
|
scene.addPixmap(pixmap)
|
|
|
view.setScene(scene)
|
|
|
view.fitInView(scene.itemsBoundingRect(), Qt.KeepAspectRatio) # 修正了参数名称
|
|
|
|
|
|
def save_image(self):
|
|
|
if self.output_img is not None:
|
|
|
options = QFileDialog.Options()
|
|
|
options |= QFileDialog.ShowDirsOnly
|
|
|
file_name, _ = QFileDialog.getSaveFileName(self, "保存图片", "", "Images (*.png *.xpm *.jpg);;All Files (*)", options=options)
|
|
|
if file_name:
|
|
|
cv2.imwrite(file_name, self.output_img)
|
|
|
else:
|
|
|
QMessageBox.warning(self, "Warning", "没有转换后的图片可保存")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
app = QApplication(sys.argv)
|
|
|
mainWin = MainWindow()
|
|
|
mainWin.show()
|
|
|
sys.exit(app.exec_())
|