Opencv-PyQt 实战图像平滑处理小程序

Posted 卖报的大地主

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Opencv-PyQt 实战图像平滑处理小程序相关的知识,希望对你有一定的参考价值。

在尽量保留原有信息的情况下,过滤掉图像内部的噪声,这过程成为图像平滑处理,所得图像为平滑图像

图像平滑的基本原理是:将噪声所在像素点的像素值处理为其周围临近像素点的值的近似值。

本次所写小程序可对图像 .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展示:

以上是关于Opencv-PyQt 实战图像平滑处理小程序的主要内容,如果未能解决你的问题,请参考以下文章

OpenCV-PyQT项目实战项目案例01图像模糊

OpenCV-PyQT项目实战OpenCV 与PyQt的图像转换

OpenCV-PyQT项目实战OpenCV 与PyQt的图像转换

OpenCV-PyQT项目实战安装与环境配置

OpenCV-PyQT项目实战安装与环境配置

Python 图像处理 OpenCV :图像平滑(滤波)处理