第四周图像平滑模糊
本周主要任务:为“均值模糊”添加UI界面
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
img = cv.imread('改为你的图片.png')
blur = cv.blur(img,(5,5))
plt.subplot(121),plt.imshow(img),plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(blur),plt.title('Blurred')
plt.xticks([]), plt.yticks([])
plt.show()
核心步骤如下:
1. 函数声明
首先在m_init_process.py中创建一个函数
之后的大部分操作都是对m_init_process.py和m_ui.py文件的操作
m_init_process.py可以看作我们想要实现的图像处理的类
m_ui.py是将多个类对应的多个功能进行整合的主操作
def init_menu(instance):
#添加具体功能
在m_ui.py文件中引入该模块
from part2 import m_init_process, m_blur
2. UI界面
修改init_part2函数代码如下,运行,可以看到菜单栏多了图像选项。
def init_part2(instance):
menubar = instance.menuBar()
part5Menu = menubar.addMenu('&图像')
3. 添加子菜单和操作子界面
为“图像”操作添加一个子菜单选项“模糊”,即点开图像后可以选择模糊操作(锐化等操作同理)
这里用到了Qmenu模块,需要提前引用
def init_part2(instance):
sub_menu = QMenu('模糊', instance)
menubar = instance.menuBar()
part5Menu = menubar.addMenu('图像')
part5Menu.addMenu(sub_menu)
之后我们还希望能在模糊操作下具体划分出“均值模糊”,“高斯模糊”,“中值模糊”等子操作
所以我们需要定义操作子界面,这里以“均值模糊”为例
首先定义一个Action(在头文件中引用QAction模块),当这个Action被触发时执行mean_blur_widegt_show函数
def mean_blur_widegt_show(self):
# 显示均匀模糊操作窗口
然后把这个均值模糊的Action添加到模糊菜单下,至此可以实现图像→模糊→均值模糊的三级菜单结构
def init_menu(instance):
# 连接信号,当该信号被发射后执行括号内被连接函数
instance.signal_processing_bar_blur.connect(m_blur.blur)
# 创建一个窗口,定义位置,标题等属性
instance.widegt_mean_blur=QWidget()
instance.widegt_mean_blur.setWindowTitle('均值模糊')
# 创建一个action,当该action被触发时运行mean_blur_widegt_show
# mean_blur_widegt_show的作用为显示模糊操作窗口widegt_mean_blur
blur_mean_action = QAction('&均值模糊', instance)
blur_mean_action.triggered.connect(instance.mean_blur_widegt_show)
# 添加一个菜单:模糊,这个菜单在后面被添加成图像选项的子选项
# 为该选项添加一个action blur_mean_action
change_menu = QMenu('模糊', instance)
change_menu.addAction(blur_mean_action)
# 新增一个菜单选项:图像
# 图像选项新增一个子菜单模糊
menubar = instance.menuBar()
editMenu = menubar.addMenu('&图像')
editMenu.addMenu(change_menu)
4,信号发射
在这部分实现的功能如下,当滑块停止时执行信号发射函数,当信号被发射时执行信号绑定的函数,被绑定的函数根据传入的值令Label显示对应的结果
总共分为5步
1.定义信号
signal_part5_submenu1=pyqtSignal('PyQt_PyObject', int)
2.定义信号被发射后的执行函数
def show_value(instance,value):
print("show_value函数被执行")
3.将信号和执行函数连接
instance.signal_part5_submenu1.connect(label_show_slider_value.show_value)
4.定义信号发射函数
(由于后续会对这部分代码进行改进,所以在这一步没有放全部的代码部分)
def signal_show_slider_value_emit(self):
self.signal_part5_submenu1.emit(self,5)
5.当事件被触发时执行信号发射函数
instance.slider_part5_submenu1.sliderReleased.connect(instance.signal_show_slider_value_emit)
拖动滑块可以选择模糊程度,即均值模糊的模板大小如3x3,5x5
上一步实现的UI操作仍然存在缺点:
假设先对图像进行一次3x3大小的模糊,再对其重复一次3x3的模糊,这时图像会在第一步模糊的基础上进行第二次的模糊,也就是说我们实际上得到了一个5x5的模糊
1,创建一个label用来显示预览处理
首先我们用label添加一个图片框,这里添加了一个新的变量temp_image_blur用来存放预览图片的数据。
之后创建了一个label,它的父对象是widegt_mean_blur,用来显示图片
#----------------------------------------------------------------------------------------------
instance.temp_image_blur = instance.m_image
blur_image = QImage(instance.temp_image_blur[:],instance.temp_image_blur.shape[1],
instance.temp_image_blur.shape[0],instance.temp_image_blur.shape[1]*3,
QImage.Format_RGB888)
instance.blur_image_width = 400
instance.blur_image_height = instance.m_image.shape[0]/instance.m_image.shape[1]*instance.blur_image_width
instance.blur_image_pixmap = QPixmap(blur_image)
instance.blur_lbl = QLabel(instance.widegt_mean_blur)
instance.blur_lbl.setPixmap(instance.blur_image_pixmap)
instance.blur_lbl.resize(instance.blur_image_width , instance.blur_image_height)
instance.blur_lbl.setScaledContents(True)
instance.blur_lbl.setGeometry(200,200,instance.blur_image_width , instance.blur_image_height)
这时当我们点开均值模糊,出现的不止有一个滑块,同时还会有被处理图像的预览图,我们希望可以先在预览图上看到对图像处理的效果,达到令人满意的结果后在对原图像进行操作
2,更新对预览图象的处理
添加一个新的函数update_temp_image,用来更新temp_image_blur的值
def update_temp_image(instance):
blur_image = QImage(instance.temp_image_blur[:], instance.temp_image_blur.shape[1],
instance.temp_image_blur.shape[0], instance.temp_image_blur.shape[1] * 3,
QImage.Format_RGB888)
instance.blur_image_width = 400
instance.blur_image_height = instance.m_image.shape[0] / instance.m_image.shape[1] * instance.blur_image_width
instance.blur_image_pixmap = QPixmap(blur_image)
instance.blur_lbl.setPixmap(instance.blur_image_pixmap)
instance.blur_lbl.resize(instance.blur_image_width, instance.blur_image_height)
instance.blur_lbl.setScaledContents(True)
instance.blur_lbl.setGeometry(200, 200, instance.blur_image_width, instance.blur_image_height)
在m_ui文件中添加这个函数
def update_temp_image_for_blur(self):
m_blur.update_temp_image(self)
修改m_blur函数如下,当滑动条事件被触发后,我们不再修改主图像数据(m_image),而是修改预览图的图像数据。之后调用更新预览图的函数
def blur(intstance,type,value):
#根据type的类型选择不同模糊方法,比如均值模糊,高斯模糊
if type == 0:
intstance.temp_image_blur=cv.blur(intstance.m_image,(value,value))
intstance.update_temp_image_for_blur()
最后添加个确认button,当这个button被点击时执行button_mean_blur_clicked函数,button_mean_blur_clicked函数的作用是将预览图数据应用到主图像数据(m_image)
把botton添加到主程序m_ui中
3,运行结果