QT,opencv制作界面化图片操作
思路分析:
-
main.py
主要负责用户界面和事件处理。- 它首先导入许多所需的模块,然后定义一个
MyWidget
类来处理用户界面和信号。 MyWidget
类的构造函数在载入用户界面后,设置一些初值和预置的图像处理选项,然后与按钮、滑块和下拉框的信号(如点击、值改变、选择改变等)连接对应的槽函数。- 槽函数主要调用
Photo_Operate
模块中的函数来处理图像,并更新用户界面上的图像显示。
- 它首先导入许多所需的模块,然后定义一个
-
Photo_Operate.py
主要负责图像处理。- 它包含一系列的函数,每个函数对应一种特定的图像处理操作,如灰度化、旋转、亮度调整、对比度调整、模糊、边缘检测等。
- 这些函数读取路径下的图像文件,进行相应的处理,然后将结果保存到预定的路径下。
mian.py
import sys
from opencv import Photo_Operate
from PyQt6 import uic
from PyQt6.QtGui import QPixmap
from PyQt6.QtWidgets import QWidget, QApplication, QLabel, QPushButton, QFileDialog, \
QSlider, QComboBox
class MyWidget(QWidget):
def __init__(self):
super().__init__()
ui = uic.loadUi('1.ui', self)
self.photo_obj_sav = 'C:/Users/29610/new.jpg'
self.photo_obj_sav_gray = 'C:/Users/29610/new_gray.jpg'
self.photo_path_save = 'C:/Users/29610/save.jpg'
self.photo_path_open = ''
self.list = ['模糊', '锐化', '边缘检测']
self.label: QLabel = self.label
self.btn1: QPushButton = self.btn1
self.btn2: QPushButton = self.btn2
self.btn3: QPushButton = self.btn3
self.btn4: QPushButton = self.btn4
self.btn5: QPushButton = self.btn5
self.btn6: QPushButton = self.btn6
self.slider1: QSlider = self.slider1
self.slider2: QSlider = self.slider2
self.comboBox: QComboBox = self.comboBox
self.comboBox.addItems(self.list)
self.btn1.clicked.connect(self.btn1_slot)
self.btn2.clicked.connect(self.btn2_slot)
self.btn3.clicked.connect(self.btn3_slot)
self.btn4.clicked.connect(self.btn4_slot)
self.btn5.clicked.connect(self.btn5_slot)
self.btn6.clicked.connect(self.btn6_slot)
self.slider1.valueChanged.connect(self.slider1_slot)
self.slider2.valueChanged.connect(self.slider2_slot)
self.comboBox.activated.connect(self.getComboBox_slot)
#灰度化
def btn1_slot(self):
path = Photo_Operate.grayscale(
self.photo_obj_sav_gray,
self.photo_obj_sav_gray)
self.label.setPixmap(QPixmap(path))
self.photo_path_save = rf'{path}'
self.label.setScaledContents(True)
#打开
def btn2_slot(self):
path, filetype = QFileDialog.getOpenFileName(
window,
"打开图片",
"./",
"mage(*.png *.jpg *ico)"
)
self.photo_path_open = rf'{path}'
Photo_Operate.open_img(self.photo_path_open, self.photo_obj_sav_gray, self.photo_obj_sav)
self.label.setPixmap(QPixmap(self.photo_path_open))
self.label.setScaledContents(True)
self.photo_path_save = rf'{path}'
#保存
def btn3_slot(self):
self.photo_path_save = ''
if not self.label.pixmap():
print("No image to save")
return
path, filetype = QFileDialog.getSaveFileName(
window,
"保存图片",
"./",
"mage(*.png *.jpg *ico)"
)
self.photo_path_save = rf'{path}'
if path:
self.label.pixmap().save(self.photo_path_save)
print(self.photo_path_save)
#回复
def btn4_slot(self):
self.label.setPixmap(QPixmap(self.photo_obj_sav))
self.label.setScaledContents(True)
self.photo_path_save = self.photo_obj_sav
pass
#旋转
def btn5_slot(self):
path = Photo_Operate.warp(
self.photo_obj_sav_gray,
self.photo_obj_sav_gray, )
path2 = Photo_Operate.warp(
self.photo_obj_sav,
self.photo_obj_sav, )
if Photo_Operate.is_gray(self.photo_path_save):
self.label.setPixmap(QPixmap(path))
self.photo_path_save = path
else:
self.label.setPixmap(QPixmap(path2))
self.photo_path_save = path2
self.label.setScaledContents(True)
pass
#翻折
def btn6_slot(self):
path = Photo_Operate.flip(
self.photo_obj_sav_gray,
self.photo_obj_sav_gray,
-1)
path2 = Photo_Operate.flip(
self.photo_obj_sav,
self.photo_obj_sav,
-1)
if Photo_Operate.is_gray(self.photo_path_save):
self.label.setPixmap(QPixmap(path))
self.photo_path_save = path
else:
self.label.setPixmap(QPixmap(path2))
self.photo_path_save = path2
self.label.setScaledContents(True)
pass
#亮度
def slider1_slot(self):
path = Photo_Operate.change_brightness(
self.photo_path_open,
self.photo_obj_sav_gray,
self.slider1.value())
path2 = Photo_Operate.change_brightness(
self.photo_path_open,
self.photo_obj_sav,
self.slider1.value())
if Photo_Operate.is_gray(self.photo_path_save):
self.label.setPixmap(QPixmap(path))
self.photo_path_save = path
else:
self.label.setPixmap(QPixmap(path2))
self.photo_path_save = path2
self.label.setScaledContents(True)
pass
#对比度
def slider2_slot(self):
path = Photo_Operate.change_contrast(
self.photo_path_open,
self.photo_obj_sav_gray,
self.slider2.value())
path2 = Photo_Operate.change_contrast(
self.photo_path_open,
self.photo_obj_sav,
self.slider2.value())
if Photo_Operate.is_gray(self.photo_path_save):
self.label.setPixmap(QPixmap(path))
self.photo_path_save = path
else:
self.label.setPixmap(QPixmap(path2))
self.photo_path_save = path2
self.label.setScaledContents(True)
pass
#模糊,锐化,边缘检测
def getComboBox_slot(self):
if self.comboBox.currentText() == '模糊':
path = Photo_Operate.blur(
self.photo_obj_sav_gray,
self.photo_obj_sav_gray, )
path2 = Photo_Operate.blur(
self.photo_obj_sav,
self.photo_obj_sav, )
if Photo_Operate.is_gray(self.photo_path_save):
self.label.setPixmap(QPixmap(path))
self.photo_path_save = path
else:
self.label.setPixmap(QPixmap(path2))
self.photo_path_save = path2
self.label.setScaledContents(True)
elif self.comboBox.currentText() == '锐化':
path = Photo_Operate.sobel(
self.photo_obj_sav_gray,
self.photo_obj_sav_gray, )
path2 = Photo_Operate.sobel(
self.photo_obj_sav,
self.photo_obj_sav, )
if Photo_Operate.is_gray(self.photo_path_save):
self.label.setPixmap(QPixmap(path))
self.photo_path_save = path
else:
self.label.setPixmap(QPixmap(path2))
self.photo_path_save = path2
self.label.setScaledContents(True)
elif self.comboBox.currentText() == '边缘检测':
path = Photo_Operate.canny(
self.photo_obj_sav_gray,
self.photo_obj_sav_gray, )
path2 = Photo_Operate.canny(
self.photo_obj_sav,
self.photo_obj_sav, )
if Photo_Operate.is_gray(self.photo_path_save):
self.label.setPixmap(QPixmap(path))
self.photo_path_save = path
else:
self.label.setPixmap(QPixmap(path2))
self.photo_path_save = path2
self.label.setScaledContents(True)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MyWidget()
window.show()
sys.exit(app.exec())
Photo_Operate.py
import cv2
import numpy as np
def is_gray(path: str):
img = cv2.imdecode(np.fromfile(path, dtype=np.uint8), cv2.IMREAD_COLOR) # 从指定路径读取图像
if len(img.shape) == 2:
return True
elif len(img.shape) == 3:
if img.shape[2] == 3:
b, g, r = cv2.split(img)
if (b == g).all() and (b == r).all():
return True
return False
def open_img(path: str, path_save1: str, path_save2: str):
img = cv2.imdecode(np.fromfile(path, dtype=np.uint8), cv2.IMREAD_COLOR) # 从指定路径读取图像
img_new = img.copy()
img_new2 = img.copy()
cv2.imencode('.jpg', img_new)[1].tofile(path_save1) # 将图像保存为 .jpg 格式文件
cv2.imencode('.jpg', img_new2)[1].tofile(path_save2)
def grayscale(path: str, path_save: str): # 该函数将图像转换为灰度图
img = cv2.imdecode(np.fromfile(path, dtype=np.uint8), cv2.IMREAD_COLOR) # 从指定路径读取图像
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imencode('.jpg', img_gray)[1].tofile(path_save) # 将图像保存为 .jpg 格式文件
return path_save
def flip(path: str, path_save: str, num: int):
img = cv2.imdecode(np.fromfile(path, dtype=np.uint8), cv2.IMREAD_COLOR) # 从指定路径读取图像
img_new = cv2.flip(img, num)
cv2.imencode('.jpg', img_new)[1].tofile(path_save) # 将图像保存为 .jpg 格式文件
return path_save
def warp(path: str, path_save: str):
img = cv2.imdecode(np.fromfile(path, dtype=np.uint8), cv2.IMREAD_COLOR) # 从指定路径读取图像
M = cv2.getRotationMatrix2D((img.shape[1] / 2, img.shape[0] / 2), 90, -1)
img_rotate = cv2.warpAffine(img, M, (img.shape[1], img.shape[0]))
cv2.imencode('.jpg', img_rotate)[1].tofile(path_save) # 将图像保存为 .jpg 格式文件
return path_save
def change_brightness(path: str, path_save: str, b):
img = cv2.imdecode(np.fromfile(path, dtype=np.uint8), cv2.IMREAD_COLOR) # 从指定路径读取图像
img_copy = img.copy()
img_copy = img_copy + b
img_copy = np.clip(img_copy, 0, 255)
img_copy = np.uint8(img_copy)
cv2.imencode('.jpg', img_copy)[1].tofile(path_save) # 将图像保存为 .jpg 格式文件
return path_save
def change_contrast(path: str, path_save: str, a):
img = cv2.imdecode(np.fromfile(path, dtype=np.uint8), cv2.IMREAD_COLOR) # 从指定路径读取图像
img_copy = img.copy()
img_copy = (a + 100) / 100 * img_copy
img_copy = np.clip(img_copy, 0, 255)
img_copy = np.uint8(img_copy)
cv2.imencode('.jpg', img_copy)[1].tofile(path_save) # 将图像保存为 .jpg 格式文件
return path_save
def blur(path: str, path_save: str):
img = cv2.imdecode(np.fromfile(path, dtype=np.uint8), cv2.IMREAD_COLOR) # 从指定路径读取图像
img_blur = cv2.blur(img, (5, 5))
cv2.imencode('.jpg', img_blur)[1].tofile(path_save) # 将图像保存为 .jpg 格式文件
return path_save
def sobel(path: str, path_save: str):
img = cv2.imdecode(np.fromfile(path, dtype=np.uint8), cv2.IMREAD_COLOR) # 从指定路径读取图像
img_sobel = cv2.Sobel(img, -1, dx=0, dy=1, ksize=5)
cv2.imencode('.jpg', img_sobel)[1].tofile(path_save) # 将图像保存为 .jpg 格式文件
return path_save
def canny(path: str, path_save: str):
img = cv2.imdecode(np.fromfile(path, dtype=np.uint8), cv2.IMREAD_COLOR) # 从指定路径读取图像
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img_canny = cv2.Canny(img_gray,
30, # 低阈值
70 # 高阈值
)
_, img_th = cv2.threshold(img_canny, 127, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
can, _ = cv2.findContours(img_th, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
img_draw = img.copy()
cv2.drawContours(img_draw, can, -1, (0, 255, 255), 3)
cv2.imencode('.jpg', img_draw)[1].tofile(path_save) # 将图像保存为 .jpg 格式文件
return path_save
效果实现:
读取图片:
灰度化及灰度化恢复:
旋转翻折:
对比度,亮度:
模糊处理:
锐化处理:
边缘检测: