在尽量保留原有信息的情况下,过滤掉图像内部的噪声,这过程成为图像平滑处理,所得图像为平滑图像。
图像平滑的基本原理是:将噪声所在像素点的像素值处理为其周围临近像素点的值的近似值。
本次所写小程序可对图像 .jpg .png .gif 图像进行处理,支持的平滑操作有:
代码的主要业务实现部分如下:
import sys
import cv2
import numpy as np
from PyQt5.QtGui import QPixmap, QImage
from PyQt5.QtWidgets import QApplication, QWidget, QFileDialog
from PyQt5.QtCore import QDir, pyqtSlot
from ui_OpencvFilter import Ui_OpencvFilter
class Qopencv_filter_Qwidget(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.ui = Ui_OpencvFilter()
self.ui.setupUi(self)
self.filename = ""
self.cv_img = np.ndarray(())
@pyqtSlot()
def on_pushButtonOpen_clicked(self):
curPath = QDir.currentPath()
title = "选择图片"
filt = "所有文件(*.*);;图片文件(*.jpg *.png *.gif)"
self.filename, filtUsed = QFileDialog.getOpenFileName(self, title, curPath, filt)
if self.filename == "":
return
pixmap = QPixmap(self.filename)
if pixmap.width() > 400:
pixRatio = pixmap.width() / 400
pixmap.setDevicePixelRatio(pixRatio)
self.ui.labelImg.setPixmap(pixmap)
self.ui.labelImg.setScaledContents(True)
@pyqtSlot()
def on_pushButtonSave_clicked(self):
curPath = QDir.currentPath()
title = "保存图片"
filt = "所有文件(*.*);;图片文件(*.jpg *.png *.gif)"
savename, filtUsed = QFileDialog.getSaveFileName(self, title, curPath, filt)
if savename == "":
return
cv2.imwrite(savename, self.cv_img)
@pyqtSlot()
def on_pushButtonOrg_clicked(self):
if self.filename == "":
return
pixmap = QPixmap(self.filename)
if pixmap.width() > 400:
pixRatio = pixmap.width() / 400
pixmap.setDevicePixelRatio(pixRatio)
self.ui.labelImg.setPixmap(pixmap)
self.ui.labelImg.setScaledContents(True)
# 高斯滤波
@pyqtSlot()
def on_pushButtonGaussian_clicked(self):
if self.filename == "":
return
self.cv_img = cv2.imdecode(np.fromfile(self.filename, dtype=np.uint8), 1)
self.cv_img = cv2.GaussianBlur(self.cv_img, ksize=(5, 5), sigmaX=0, sigmaY=0)
self.refreshShow(self.cv_img)
# 方框滤波
@pyqtSlot()
def on_pushButtonBox_clicked(self):
if self.filename == "":
return
self.cv_img = cv2.imdecode(np.fromfile(self.filename, dtype=np.uint8), 1)
self.cv_img = cv2.boxFilter(self.cv_img, ksize=(5, 5), ddepth=-1)
self.refreshShow(self.cv_img)
# 均值滤波
@pyqtSlot()
def on_pushButtonBlur_clicked(self):
if self.filename == "":
return
self.cv_img = cv2.imdecode(np.fromfile(self.filename, dtype=np.uint8), 1)
self.cv_img = cv2.blur(self.cv_img, ksize=(5, 5))
self.refreshShow(self.cv_img)
# 中值滤波
@pyqtSlot()
def on_pushButtonMedian_clicked(self):
if self.filename == "":
return
self.cv_img = cv2.imdecode(np.fromfile(self.filename, dtype=np.uint8), 1)
self.cv_img = cv2.medianBlur(self.cv_img, ksize=5)
self.refreshShow(self.cv_img)
# 双边滤波
@pyqtSlot()
def on_pushButtonBilateral_clicked(self):
if self.filename == "":
return
self.cv_img = cv2.imdecode(np.fromfile(self.filename, dtype=np.uint8), 1)
self.cv_img = cv2.bilateralFilter(self.cv_img, d=5, sigmaColor=100, sigmaSpace=100)
self.refreshShow(self.cv_img)
def refreshShow(self, img):
# 提取图像的通道和尺寸,用于将OpenCV下的image转换成Qimage
height, width, channel = img.shape
bytesPerline = 3 * width
qimg = QImage(img.data, width, height, bytesPerline, QImage.Format_BGR888)
pixmap = QPixmap.fromImage(qimg)
# 将QImage显示出来
if pixmap.width() > 400:
pixRatio = pixmap.width() / 400
pixmap.setDevicePixelRatio(pixRatio)
self.ui.labelImg.setPixmap(pixmap)
self.ui.labelImg.setScaledContents(True)
if __name__ == '__main__':
app = QApplication(sys.argv)
main_widget = Qopencv_filter_Qwidget()
main_widget.show()
sys.exit(app.exec_())
小程序UI代码部分(由可视化UI界面设计生成)如下:
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'OpencvFilter.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_OpencvFilter(object):
def setupUi(self, OpencvFilter):
OpencvFilter.setObjectName("OpencvFilter")
OpencvFilter.setWindowModality(QtCore.Qt.NonModal)
OpencvFilter.resize(417, 367)
self.verticalLayout = QtWidgets.QVBoxLayout(OpencvFilter)
self.verticalLayout.setObjectName("verticalLayout")
self.gridLayout = QtWidgets.QGridLayout()
self.gridLayout.setObjectName("gridLayout")
spacerItem = QtWidgets.QSpacerItem(29, 25, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.gridLayout.addItem(spacerItem, 0, 1, 1, 1)
spacerItem1 = QtWidgets.QSpacerItem(29, 25, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.gridLayout.addItem(spacerItem1, 1, 1, 1, 1)
self.pushButtonBox = QtWidgets.QPushButton(OpencvFilter)
self.pushButtonBox.setObjectName("pushButtonBox")
self.gridLayout.addWidget(self.pushButtonBox, 0, 2, 1, 1)
self.pushButtonGaussian = QtWidgets.QPushButton(OpencvFilter)
self.pushButtonGaussian.setObjectName("pushButtonGaussian")
self.gridLayout.addWidget(self.pushButtonGaussian, 1, 0, 1, 1)
spacerItem2 = QtWidgets.QSpacerItem(30, 25, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.gridLayout.addItem(spacerItem2, 0, 3, 1, 1)
self.pushButtonOrg = QtWidgets.QPushButton(OpencvFilter)
self.pushButtonOrg.setObjectName("pushButtonOrg")
self.gridLayout.addWidget(self.pushButtonOrg, 0, 0, 1, 1)
spacerItem3 = QtWidgets.QSpacerItem(30, 25, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.gridLayout.addItem(spacerItem3, 1, 3, 1, 1)
self.pushButtonBlur = QtWidgets.QPushButton(OpencvFilter)
self.pushButtonBlur.setObjectName("pushButtonBlur")
self.gridLayout.addWidget(self.pushButtonBlur, 0, 4, 1, 1)
self.pushButtonMedian = QtWidgets.QPushButton(OpencvFilter)
self.pushButtonMedian.setObjectName("pushButtonMedian")
self.gridLayout.addWidget(self.pushButtonMedian, 1, 2, 1, 1)
self.pushButtonBilateral = QtWidgets.QPushButton(OpencvFilter)
self.pushButtonBilateral.setObjectName("pushButtonBilateral")
self.gridLayout.addWidget(self.pushButtonBilateral, 1, 4, 1, 1)
self.verticalLayout.addLayout(self.gridLayout)
self.labelImg = QtWidgets.QLabel(OpencvFilter)
self.labelImg.setText("")
self.labelImg.setObjectName("labelImg")
self.verticalLayout.addWidget(self.labelImg)
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.pushButtonOpen = QtWidgets.QPushButton(OpencvFilter)
self.pushButtonOpen.setObjectName("pushButtonOpen")
self.horizontalLayout.addWidget(self.pushButtonOpen)
spacerItem4 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout.addItem(spacerItem4)
self.pushButtonSave = QtWidgets.QPushButton(OpencvFilter)
self.pushButtonSave.setObjectName("pushButtonSave")
self.horizontalLayout.addWidget(self.pushButtonSave)
self.verticalLayout.addLayout(self.horizontalLayout)
self.retranslateUi(OpencvFilter)
QtCore.QMetaObject.connectSlotsByName(OpencvFilter)
def retranslateUi(self, OpencvFilter):
_translate = QtCore.QCoreApplication.translate
OpencvFilter.setWindowTitle(_translate("OpencvFilter", "图像平滑处理小程序"))
self.pushButtonBox.setText(_translate("OpencvFilter", "方框滤波"))
self.pushButtonGaussian.setText(_translate("OpencvFilter", "高斯滤波"))
self.pushButtonOrg.setText(_translate("OpencvFilter", "原图"))
self.pushButtonBlur.setText(_translate("OpencvFilter", "均值滤波"))
self.pushButtonMedian.setText(_translate("OpencvFilter", "中值滤波"))
self.pushButtonBilateral.setText(_translate("OpencvFilter", "双边滤波"))
self.pushButtonOpen.setText(_translate("OpencvFilter", "打开文件"))
self.pushButtonSave.setText(_translate("OpencvFilter", "保存文件"))
小程序UI展示: