0基础带你python入门:pyQT + OpenCV相关练习
一、思路分析
这个代码主要实现了一个基于 PyQt6 和 OpenCV 的图像处理应用,能够加载图像并进行一系列处理,包括灰度化、旋转、翻转、图像增强(亮度、对比度调整)、模糊、锐化、边缘检测等操作。界面通过 PyQt6 进行构建,用户可以通过按钮、滑块和下拉框来控制图像处理效果。
具体实现的步骤可以分为以下几部分:
-
加载和显示图像
使用 OpenCV 加载图像,并通过cv2.QT_img
方法将图像转换为 Qt 支持的格式,以便在 QLabel 中显示。 -
图像预处理和效果实现
通过不同的按钮和控件,进行图像的不同处理。按钮包括:- 灰度化(通过
gary_lot
方法) - 恢复原图(通过
rec_lot
方法) - 翻转(通过
flip_lot
方法) - 旋转(通过
spin_lot
方法)
控件(滑块)控制亮度和对比度的调整,用户可以通过滑动条来调节图像的亮度和对比度。
- 灰度化(通过
-
特殊图像效果
- 模糊:使用
cv2.blur
来实现模糊效果。 - 锐化:使用高斯模糊后,再进行锐化处理。
- 边缘检测:使用 Canny 边缘检测和
findContours
来提取图像的轮廓并绘制。
- 模糊:使用
-
图像保存功能
使用cv2.imwrite
将当前图像保存为img.png
。
二、设计到的函数和方法
-
cv2_QT_img(self, img)
- 功能:将 OpenCV 图像转换为 Qt 图像格式,并显示在界面上的
QLabel
中。
- 功能:将 OpenCV 图像转换为 Qt 图像格式,并显示在界面上的
-
gary_lot(self)
- 功能:将图像转换为灰度图像并更新显示。
-
rec_lot(self)
- 功能:恢复原始图像。
-
flip_lot(self)
- 功能:水平翻转图像。
-
spin_lot(self)
- 功能:旋转图像 15 度。
-
qslider_slot(self)
- 功能:根据滑块的值调整图像的亮度和对比度。
-
comboBoxr_slot(self)
- 功能:根据下拉框选择不同的图像处理效果,分别为模糊、锐化和边缘检测。
-
writer_slot(self)
- 功能:将当前图像保存到本地文件
img.png
。
- 功能:将当前图像保存到本地文件
三、代码
import cv2
import numpy as np
import sys
from PyQt6 import uic
from PyQt6.QtGui import QPixmap, QImage
from PyQt6.QtWidgets import QWidget, QApplication, QLabel, QPushButton, QSlider, QComboBox, QFileDialog
class MyWidget(QWidget):
def cv2_QT_img(self, img):
"""将图像从 BGR 转换为 RGB 格式,并显示在 QLabel 中"""
img_QT = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
h, w, c = img_QT.shape
bytes_per_line = c * w
q_img = QImage(img_QT.data, w, h, bytes_per_line, QImage.Format.Format_RGB888)
self.label.setPixmap(QPixmap.fromImage(q_img))
self.label.setScaledContents(True)
return q_img
def __init__(self):
super().__init__()
ui = uic.loadUi("./Form.ui", self)
self.img_Boss = cv2.imread("./Lazy.png")
self.img = self.img_Boss.copy()
self.label: QLabel = ui.label
# 显示初始图像
self.cv2_QT_img(self.img)
self.garyBtn: QPushButton = ui.garyBtn
self.recBtn: QPushButton = ui.recBtn
self.flipBtn: QPushButton = ui.flipBtn
self.spinBtn: QPushButton = ui.spinBtn
self.writer: QPushButton = ui.writer
self.comboBox: QComboBox = ui.comboBox
self.luminance: QLabel = ui.luminance
self.contrast: QLabel = ui.contrast
self.luSlider: QSlider = ui.luSlider
self.conSlider: QSlider = ui.conSlider
self.luSlider.setRange(-100, 100)
self.conSlider.setRange(-100, 100)
self.garyBtn.clicked.connect(self.gary_lot)
self.gary_use = False
self.recBtn.clicked.connect(self.rec_lot)
self.flipBtn.clicked.connect(self.flip_lot)
self.spinBtn.clicked.connect(self.spin_lot)
self.writer.clicked.connect(self.writer_slot)
list1 = ["原图", "模糊", "锐化", "边缘检测"]
self.comboBox.addItems(list1)
self.comboBox.currentIndexChanged.connect(self.comboBoxr_slot)
self.luSlider.valueChanged.connect(self.qslider_slot)
self.conSlider.valueChanged.connect(self.qslider_slot)
def gary_lot(self):
"""灰度化图像"""
if not self.gary_use:
self.img = cv2.cvtColor(self.img, cv2.COLOR_BGR2GRAY)
self.cv2_QT_img(self.img)
self.gary_use = True
def rec_lot(self):
"""恢复原始图像"""
self.img = self.img_Boss.copy()
self.cv2_QT_img(self.img)
self.gary_use = False
def flip_lot(self):
"""水平翻转图像"""
self.img = cv2.flip(self.img, 1)
self.cv2_QT_img(self.img)
def spin_lot(self):
"""旋转图像"""
M = cv2.getRotationMatrix2D((self.img.shape[1]//2, self.img.shape[0]//2), 15, 1)
self.img = cv2.warpAffine(self.img, M, (self.img.shape[1], self.img.shape[0]))
self.cv2_QT_img(self.img)
def qslider_slot(self):
"""根据滑块调整亮度和对比度"""
con_ = self.conSlider.value() / 100.0 + 1
lu_ = self.luSlider.value()
img_copy = cv2.convertScaleAbs(self.img_Boss, alpha=con_, beta=lu_)
img_copy = np.clip(img_copy, 0, 255)
self.img = img_copy
self.cv2_QT_img(self.img)
def comboBoxr_slot(self):
"""根据选项应用模糊、锐化或边缘检测"""
if self.comboBox.currentText() == '模糊':
self.img = cv2.GaussianBlur(self.img, (5, 5), 0)
self.cv2_QT_img(self.img)
elif self.comboBox.currentText() == '锐化':
# 锐化操作
kernel = np.array([[0, -1, 0], [-1, 5,-1], [0, -1, 0]]) # 锐化滤波器
self.img = cv2.filter2D(self.img, -1, kernel)
self.cv2_QT_img(self.img)
elif self.comboBox.currentText() == '边缘检测':
M = cv2.Canny(self.img, 100, 200)
contours, h = cv2.findContours(M, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
self.img = cv2.drawContours(self.img, contours, -1, (0, 255, 0), 3)
self.cv2_QT_img(self.img)
def writer_slot(self):
# 通过 QFileDialog 弹出文件保存对话框
file_path, _ = QFileDialog.getSaveFileName(
self, # 父窗口
"保存文件", # 对话框标题
"", # 默认路径
"PNG文件 (*.png);;所有文件 (*.*)", # 文件过滤器
)
if file_path:
cv2.imwrite(file_path, self.img)
if __name__ == '__main__':
app = QApplication(sys.argv)
myWidget = MyWidget()
myWidget.show()
sys.exit(app.exec())
四、效果展示
原图
灰度化:点击灰度化按钮后,图像将转为黑白色。
恢复原图:点击恢复按钮后,图像恢复为原始的彩色图像。
翻转:点击翻转按钮后,图像将左右镜像翻转。
旋转:点击旋转按钮后,图像会顺时针旋转 30 度。
亮度和对比度调节:使用滑块调节亮度和对比度,实时显示效果。
模糊:图像将变得模糊。
锐化:图像锐化,使边缘更清晰。
边缘检测:图像中的边缘部分会用绿色轮廓标出。
保存:将图片保存到到指定路径