博主介绍:✌全网粉丝50W+,前互联网大厂软件研发、集结硕博英豪成立软件开发工作室,专注于计算机相关专业项目实战6年之久,累计开发项目作品上万套。凭借丰富的经验与专业实力,已帮助成千上万的学生顺利毕业,选择我们,就是选择放心、选择安心毕业✌
> 🍅想要获取完整文章或者源码,或者代做,拉到文章底部即可与我联系了。🍅

点击查看作者主页,了解更多项目!

🍅感兴趣的可以先收藏起来,点赞、关注不迷路,大家在毕设选题,项目以及论文编写等相关问题都可以给我留言咨询,希望帮助同学们顺利毕业 。🍅

1、毕业设计:2025年计算机专业毕业设计选题汇总(建议收藏)✅

2、最全计算机专业毕业设计选题大全(建议收藏)✅

1、项目介绍

技术栈:
python语言、OpenCV、PyQt5界面、图像处理

摘 要
本课设针对图像处理的难点,设计了一款界面友好的图像处理识别系统,意在帮助初学者形象的理解图像处理所涉及的部分知识点。本系统包含常见的图像处理实例,例如图像缩放、加噪、平滑锐化、直方图均衡、压缩编码,边缘检测、人脸检测等。这些模块涉及到较多图像处理知识,通过每个模块设计的实例,循序渐进的让初学者加深理解图像处理方法间的联系,激发初学者对图像处理的兴趣。
OpenCV与Python的NumPy科学计算库能无缝结合,能快速开发出性能可靠的图像处理系统,利用OpenCV提供的众多内置函数,能实现较多功能。本设计利用PyCharm和QT Designer开发平台,基于Python编程语言以及OpenCV计算机视觉库,利用Qt5作为GUI框架,构建了一个简单的图像处理识别系统。

关键字:图像处理;仿真系统;OpenCV;图像识别技术

2、项目界面

(1)功能模块

在这里插入图片描述

(2)图像加噪和平滑

在这里插入图片描述

(3)图像锐化
在这里插入图片描述

(4)人脸检测
在这里插入图片描述

(5)人脸检测
在这里插入图片描述

3、项目说明

1.图像表示:OpenCV库提供了一个名为cv::Mat的数据结构,用于表示二维图像。它包含图像的宽度、高度、通道数、像素类型等属性,可以用于表示灰度图像、彩色图像等各种类型的图像。在设计图像处理识别系统时,可以使用cv::Mat作为基本的图像表示数据结构。
2.特征点和描述符:在特征匹配和目标识别中,需要提取图像特征点及其描述符。可以使用cv::KeyPoint结构表示特征点,其中包含特征点的位置、尺度、方向等信息。描述符可以用cv::Mat来表示,每一行代表一个特征点的描述符。
3.图像色彩转换模块数据结构:原始图像数据结构:numpy.ndarray,包括图像的像素数据、通道数和尺寸等信息。目标图像数据结构:numpy.ndarray,与原始图像数据结构相同。
4.图像平滑加噪模块数据结构:原始图像数据结构:numpy.ndarray,包括图像的像素数据、通道数和尺寸等信息。目标图像数据结构:numpy.ndarray,与原始图像数据结构相同。
5.图像锐化模块数据结构:原始图像数据结构:numpy.ndarray,包括图像的像素数据、通道数和尺寸等信息。目标图像数据结构:numpy.ndarray,与原始图像数据结构相同。
6. 直方图变换模块数据结构:原始图像数据结构:numpy.ndarray,包括图像的像素数据、通道数和尺寸等信息。目标图像数据结构:numpy.ndarray,与原始图像数据结构相同。
7. 基于DCT的图像压缩模块数据结构:原始图像数据结构:numpy.ndarray,包括图像的像素数据、通道数和尺寸等信息。目标图像数据结构:numpy.ndarray,与原始图像数据结构相同。频域系数数据结构:int,表示压缩比。
8. 图像边缘检测模块数据结构:原始图像数据结构:numpy.ndarray,包括图像的像素数据、通道数和尺寸等信息。目标图像数据结构:numpy.ndarray,与原始图像数据结构相同。
9. 人脸检测模块数据结构:原始图像数据结构:numpy.ndarray,包括图像的像素数据、通道数和尺寸等信息。人脸检测结果数据结构:List[Tuple[int, int, int, int]],表示检测到的人脸区域,每个元组表示一个人脸区域,包括左上角坐标和宽高。
10. 系统主程序数据结构:图像数据结构:numpy.ndarray,包括图像的像素数据、通道数和尺寸等信息。模块选择数据结构:int,表示选择的功能模块。模块参数数据结构:字典,包括各模块需要的参数,如图像平滑加噪模块需要的滤波器大小等。输出结果数据结构:根据不同功能模块而定,如图像色彩转换模块输出的目标图像数据结构。

目录
1 绪论 1
1.1 图像处理技术的发展历程 1
1.2 本设计的研究背景与目的 1
2 数据结构设计描述 2
3 所用技术 3
3.1 Python 3
3.2 OpenCV计算机视觉开源库 3
3.3 Qt-GUI应用程序开发框架 4
4 各功能模块的实现 4
4.1 主窗口的设计 4
4.2 图像的缩放与剪裁模块 5
4.3 图像的色彩空间转换 5
4.3.1 彩色图转灰度图 5
4.3.2 灰度图转二值化图 6
4.4 图像加噪平滑模块 6
4.4.1 椒盐噪声添加 6
4.4.2 高斯噪声添加 7
4.4.3 乘积性噪声添加 7
4.4.4 图像平滑滤波 8
4.4.5 图像均值滤波 8
4.4.6 图像的高斯滤波 8
4.4.7 图像的中值滤波 9
4.4.8 双边滤波 9
4.5 图像的锐化增强 9
4.5.1 边缘锐化 10
4.5.2 Sobel边缘锐化 10
4.5.3 Laplace边缘锐化 10
4.5.4 保留背景信息的图像锐化 11
4.5.5 自定义卷积核 11
4.6 直方图变换 12
4.6.1 生成直方图 12
4.6.2 亮度提升直方图变换 13
4.6.3 对比度提升直方图均衡化 14
4.6.4 彩色图像的直方图均衡化 14
4.7 基于DCT的图像压缩 15
4.7.1 离散余弦变换(DCT变换) 15
4.7.2 图像信息的取舍 16
4.7.3 图像数据的保存 16
4.7.4 基于DCT压缩图像的整体实现 16
4.8 图像边缘检测 17
4.8.1 高斯平滑滤波 17
4.8.2 梯度矢量计算 17
4.8.3 非极大值抑制 17
4.8.4 双阈值滤波 17
4.9 人脸检测 18
4.9.1 视频流的读取 18
4.9.2 人脸级联器 18
4.9.3 在视频帧中标记人脸 18
5 软件功能测试 19
5.1 色彩空间转换和阈值化测试 19
5.2 椒盐噪声最佳抑制滤波器测试 20
5.3 亮度提升直方图变换测试 20
5.4 对比度提升直方均衡化测试 20
5.5 图像边缘锐化功能测试 21
5.6 基于DCT变换的图像压缩测试 21
5.7 人脸检测功能测试 22
6 课程设计总结 22
参考文献 24
附 录 25

4、核心代码

#mian.py
import sys
from PyQt5.QtWidgets import QApplication

# 窗口实例
from main_windows import main_window

def main():
    app = QApplication(sys.argv)
    main_window_ = main_window.MainWindow()
    main_window_.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()


#mian_window.py
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QIcon

# 主布局
from main_windows import ui_main_window
# 子窗口实例
from sub_windows import sub_window_1
from sub_windows import sub_window_2
from sub_windows import sub_window_3
from sub_windows import sub_window_4
from sub_windows import sub_window_5
from sub_windows import sub_window_6
from sub_windows import sub_window_7
from sub_windows import sub_window_8
from sub_windows import sub_window_10

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__(parent=None)
        # 布局初始化
        self.ui = ui_main_window.Ui_Form()
        self.ui.setupUi(Form=self)
        # 子窗口实例化命名空间
        self.sub_window_1_ = None  # 色彩空间转换
        self.sub_window_2_ = None  # 图像缩放剪裁
        self.sub_window_3_ = None  # 图像加噪平滑
        self.sub_window_4_ = None  # 图像锐化
        self.sub_window_5_ = None  # 直方图变换
        self.sub_window_6_ = None  # DCT图像压缩
        self.sub_window_7_ = None  # Canny边缘检测
        self.sub_window_8_ = None  # 人脸检测实例
        self.sub_window_10_ = None  # 关于页面
        # 多线程
        pass
        # 信号与槽定义
        self.signal_and_slot()
        # 图标
        self.setWindowIcon(QIcon('./static/icon.ico'))

    def signal_and_slot(self):
        self.ui.pushButton_1.clicked.connect(self.pushButton_1)
        self.ui.pushButton_2.clicked.connect(self.pushButton_2)
        self.ui.pushButton_3.clicked.connect(self.pushButton_3)
        self.ui.pushButton_4.clicked.connect(self.pushButton_4)
        self.ui.pushButton_5.clicked.connect(self.pushButton_5)
        self.ui.pushButton_6.clicked.connect(self.pushButton_6)
        self.ui.pushButton_7.clicked.connect(self.pushButton_7)
        self.ui.pushButton_8.clicked.connect(self.pushButton_8)
        self.ui.pushButton_10.clicked.connect(self.pushButton_10)

    def pushButton_1(self):
        self.sub_window_1_ = sub_window_1.SubWindow()
        self.sub_window_1_.show()

    def pushButton_2(self):
        self.sub_window_2_ = sub_window_2.SubWindow()
        self.sub_window_2_.show()

    def pushButton_3(self):
        self.sub_window_3_ = sub_window_3.SubWindow()
        self.sub_window_3_.show()

    def pushButton_4(self):
        self.sub_window_4_ = sub_window_4.SubWindow()
        self.sub_window_4_.show()

    def pushButton_5(self):
        self.sub_window_5_ = sub_window_5.SubWindow()
        self.sub_window_5_.show()

    def pushButton_6(self):
        self.sub_window_6_ = sub_window_6.SubWindow()
        self.sub_window_6_.show()

    def pushButton_7(self):
        self.sub_window_7_ = sub_window_7.SubWindow()
        self.sub_window_7_.show()

    def pushButton_8(self):
        self.sub_window_8_ = sub_window_8.SubWindow()
        self.sub_window_8_.show()

    def pushButton_10(self):
        self.sub_window_10_ = sub_window_10.SubWindow()
        self.sub_window_10_.show()


#ui_main_window.py
#主界面ui设计
from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(733, 546)
        self.label = QtWidgets.QLabel(Form)
        self.label.setGeometry(QtCore.QRect(220, 10, 291, 61))
        font = QtGui.QFont()
        font.setFamily("黑体")
        font.setPointSize(20)
        font.setBold(False)
        font.setWeight(50)
        self.label.setFont(font)
        self.label.setAlignment(QtCore.Qt.AlignCenter)
        self.label.setObjectName("label")
        self.groupBox = QtWidgets.QGroupBox(Form)
        self.groupBox.setGeometry(QtCore.QRect(30, 130, 331, 261))
        self.groupBox.setObjectName("groupBox")
        self.pushButton_1 = QtWidgets.QPushButton(self.groupBox)
        self.pushButton_1.setGeometry(QtCore.QRect(40, 50, 111, 71))
        self.pushButton_1.setObjectName("pushButton_1")
        self.pushButton_2 = QtWidgets.QPushButton(self.groupBox)
        self.pushButton_2.setGeometry(QtCore.QRect(170, 50, 111, 71))
        self.pushButton_2.setObjectName("pushButton_2")
        self.pushButton_3 = QtWidgets.QPushButton(self.groupBox)
        self.pushButton_3.setGeometry(QtCore.QRect(40, 140, 111, 71))
        self.pushButton_3.setObjectName("pushButton_3")
        self.pushButton_4 = QtWidgets.QPushButton(self.groupBox)
        self.pushButton_4.setGeometry(QtCore.QRect(170, 140, 111, 71))
        self.pushButton_4.setObjectName("pushButton_4")
        self.groupBox_2 = QtWidgets.QGroupBox(Form)
        self.groupBox_2.setGeometry(QtCore.QRect(380, 130, 331, 261))
        self.groupBox_2.setObjectName("groupBox_2")
        self.pushButton_8 = QtWidgets.QPushButton(self.groupBox_2)
        self.pushButton_8.setGeometry(QtCore.QRect(180, 140, 111, 71))
        self.pushButton_8.setObjectName("pushButton_8")
        self.pushButton_6 = QtWidgets.QPushButton(self.groupBox_2)
        self.pushButton_6.setGeometry(QtCore.QRect(180, 50, 111, 71))
        self.pushButton_6.setObjectName("pushButton_6")
        self.pushButton_5 = QtWidgets.QPushButton(self.groupBox_2)
        self.pushButton_5.setGeometry(QtCore.QRect(50, 50, 111, 71))
        self.pushButton_5.setObjectName("pushButton_5")
        self.pushButton_7 = QtWidgets.QPushButton(self.groupBox_2)
        self.pushButton_7.setGeometry(QtCore.QRect(50, 140, 111, 71))
        self.pushButton_7.setObjectName("pushButton_7")
        self.pushButton_10 = QtWidgets.QPushButton(Form)
        self.pushButton_10.setGeometry(QtCore.QRect(560, 430, 111, 71))
        self.pushButton_10.setObjectName("pushButton_10")

        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "图像处理识别系统"))
        self.label.setText(_translate("Form", "图像处理识别系统"))
        self.groupBox.setTitle(_translate("Form", "图像变换"))
        self.pushButton_1.setText(_translate("Form", "色彩空间转换"))
        self.pushButton_2.setText(_translate("Form", "图像缩放剪裁"))
        self.pushButton_3.setText(_translate("Form", "图像加噪平滑"))
        self.pushButton_4.setText(_translate("Form", "图像锐化"))
        self.groupBox_2.setTitle(_translate("Form", "应用实例"))
        self.pushButton_8.setText(_translate("Form", "人脸检测"))
        self.pushButton_6.setText(_translate("Form", "图像压缩"))
        self.pushButton_5.setText(_translate("Form", "直方图变换"))
        self.pushButton_7.setText(_translate("Form", "边缘检测"))
        self.pushButton_10.setText(_translate("Form", "关于"))

#sub_window_1.py
import cv2
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
# 子窗口布局
from sub_windows import ui_sub_window_1

class SubWindow(QMainWindow):
    def __init__(self):
        super().__init__(parent=None)
        self.ui = ui_sub_window_1.Ui_Form()
        self.ui.setupUi(self)
        self.ui_init()
        self.cv_srcImage = None
        self.q_image = None

    def ui_init(self):
        self.ui.pushButton_open_file.clicked.connect(self.open_file)
        self.ui.pushButton_gray_convert.clicked.connect(self.gray_convert)
        self.ui.pushButton_bin_convert.clicked.connect(self.bin_convert)
        self.ui.pushButton_reset.clicked.connect(self.reset)
#打开文件
    def open_file(self):
        file_path, file_type = QFileDialog.getOpenFileName(QFileDialog(), '选择图片', '', '图像文件(*.jpg *.bmp *.png)')
        self.cv_srcImage = cv2.imread(file_path)
        height, width, channels = self.cv_srcImage.shape
        ui_image = QImage(cv2.cvtColor(self.cv_srcImage, cv2.COLOR_BGR2RGB), width, height, QImage.Format_RGB888)
        if width > height:
            ui_image = ui_image.scaledToWidth(self.ui.label_image.width())
        else:
            ui_image = ui_image.scaledToHeight(self.ui.label_image.height())
        self._update_qimage_to_label(ui_image)
        self._show_image_information(1)
        self._set_pushbutton_enabled()
#灰度转换
    def gray_convert(self):
        gray_image = cv2.cvtColor(self.cv_srcImage, cv2.COLOR_BGR2GRAY)#色彩转换
        height, width = gray_image.shape
        ui_image = QImage(cv2.cvtColor(gray_image, cv2.COLOR_BGR2RGB), width, height, QImage.Format_RGB888)
        if width > height:
            ui_image = ui_image.scaledToWidth(self.ui.label_image.width())
        else:
            ui_image = ui_image.scaledToHeight(self.ui.label_image.height())
        self._update_qimage_to_label(ui_image)
        self._show_image_information(2)
#二值化转换
    def bin_convert(self):
        threshold_value = int(self.ui.spinBox_bin_threshold.value())
        gray_image = cv2.cvtColor(self.cv_srcImage, cv2.COLOR_BGR2GRAY)
        ret, bin_image = cv2.threshold(gray_image, threshold_value, 255, cv2.THRESH_BINARY)
        height, width = bin_image.shape
        ui_image = QImage(cv2.cvtColor(bin_image, cv2.COLOR_BGR2RGB), width, height, QImage.Format_RGB888)
        if width > height:
            ui_image = ui_image.scaledToWidth(self.ui.label_image.width())
        else:
            ui_image = ui_image.scaledToHeight(self.ui.label_image.height())
        self._update_qimage_to_label(ui_image)
        self._show_image_information(3)
#恢复默认图
    def reset(self):
        height, width, channels = self.cv_srcImage.shape
        ui_image = QImage(cv2.cvtColor(self.cv_srcImage, cv2.COLOR_BGR2RGB), width, height, QImage.Format_RGB888)
        if width > height:
            ui_image = ui_image.scaledToWidth(self.ui.label_image.width())
        else:
            ui_image = ui_image.scaledToHeight(self.ui.label_image.height())
        self._update_qimage_to_label(ui_image)
        self._show_image_information(1)

    def _update_qimage_to_label(self, qimage):
        self.ui.label_image.setPixmap(QPixmap.fromImage(qimage))
#根据图片类型显示图片
    def _show_image_information(self, current_image_type):
        if current_image_type == 1:
            self.ui.label_color_space_2.setText('彩色图')
        if current_image_type == 2:
            self.ui.label_color_space_2.setText('灰度图')
        if current_image_type == 3:
            self.ui.label_color_space_2.setText('二值图')
#按钮
    def _set_pushbutton_enabled(self):
        self.ui.pushButton_gray_convert.setEnabled(True)
        self.ui.pushButton_bin_convert.setEnabled(True)
        self.ui.pushButton_reset.setEnabled(True)



##sub_window_2.py
import cv2
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

# 子窗口布局
from sub_windows import ui_#sub_window_1.py

class SubWindow(QMainWindow):
    def __init__(self):
        super().__init__(parent=None)
        self.ui = ui_sub_window_2.Ui_Form()
        self.ui.setupUi(self)
        self.ui_init()
        self.zoom_factor = 1.0
        self.cv_srcImage = None
        self.q_image = None

    def ui_init(self):
        self.ui.pushButton_open_file.clicked.connect(self.open_file)
        self.ui.pushButton_zoom_in.clicked.connect(self.zoom_in)
        self.ui.pushButton_zoom_out.clicked.connect(self.zoom_out)
        self.ui.pushButton_zoom_reset.clicked.connect(self.zoom_reset)
        self.ui.pushButton_screenshot.clicked.connect(self.clip_image)
#打开文件
    def open_file(self):
        file_path, file_type = QFileDialog.getOpenFileName(QFileDialog(), '选择图片', '', '图像文件(*.jpg *.bmp *.png)')
        self.cv_srcImage = cv2.imread(file_path)
        height, width, channels = self.cv_srcImage.shape
        ui_image = QImage(cv2.cvtColor(self.cv_srcImage, cv2.COLOR_BGR2RGB), width, height, QImage.Format_RGB888)
        if width > height:
            ui_image = ui_image.scaledToWidth(self.ui.label_image.width())
        else:
            ui_image = ui_image.scaledToHeight(self.ui.label_image.height())
        self.zoom_factor = 1.0
        self._show_qimage_to_label(ui_image)
#缩小图片,最小缩小十倍
    def zoom_in(self):
        if 10 > self.zoom_factor > 0.1:
            self.zoom_factor += 0.1
            print(self.zoom_factor)
            height, width, channels = self.cv_srcImage.shape
            ui_image = QImage(cv2.cvtColor(self.cv_srcImage, cv2.COLOR_BGR2RGB), width, height, QImage.Format_RGB888)
            if width > height:
                ui_image = ui_image.scaledToWidth(self.ui.label_image.width() * self.zoom_factor)
            else:
                ui_image = ui_image.scaledToHeight(self.ui.label_image.height() * self.zoom_factor)
            self._show_qimage_to_label(ui_image)
#放大图片,最大放大10倍
    def zoom_out(self):
        if 10 > self.zoom_factor > 0.2:
            self.zoom_factor -= 0.1
            print(self.zoom_factor)
            height, width, channels = self.cv_srcImage.shape
            ui_image = QImage(cv2.cvtColor(self.cv_srcImage, cv2.COLOR_BGR2RGB), width, height, QImage.Format_RGB888)
            if width > height:
                ui_image = ui_image.scaledToWidth(self.ui.label_image.width() * self.zoom_factor)
            else:
                ui_image = ui_image.scaledToHeight(self.ui.label_image.height() * self.zoom_factor)
            self._show_qimage_to_label(ui_image)
#恢复原值
    def zoom_reset(self):
        self.zoom_factor = 1.0 #图片初始值设为1
        height, width, channels = self.cv_srcImage.shape
        ui_image = QImage(cv2.cvtColor(self.cv_srcImage, cv2.COLOR_BGR2RGB), width, height, QImage.Format_RGB888)
        #按比例缩小、放大
        if width > height:
            ui_image = ui_image.scaledToWidth(self.ui.label_image.width())
        else:
            ui_image = ui_image.scaledToHeight(self.ui.label_image.height())
        self._show_qimage_to_label(ui_image)
#修剪图片
    def clip_image(self):
        anchor_x = int(self.ui.spinBox_anchor_x.value())
        anchor_y = int(self.ui.spinBox_anchor_y.value())
        offset_x = int(self.ui.spinBox_X_offset.value())
        offset_y = int(self.ui.spinBox_Y_offset.value())
        clip_image = self.cv_srcImage.copy()[anchor_y: offset_y - 1, anchor_x: offset_x - 1]
        cv2.imshow('clip_image', clip_image)
        cv2.waitKey(0)
#缩放系数展示
    def _show_zoom_factor(self):
        self.ui.label_zoom_factor_2.setText(str(self.zoom_factor)[:3] + 'x')

    def _update_srcImage_size(self):
        height, width, channels = self.cv_srcImage.shape
        self.ui.label_srcImage_size.setText('原图X轴*Y轴:' + str(width) + ' x ' + str(height))
        self.ui.spinBox_anchor_x.setMaximum(width)
        self.ui.spinBox_anchor_y.setMaximum(height)
        self.ui.spinBox_X_offset.setMaximum(width)
        self.ui.spinBox_Y_offset.setMaximum(height)
        self.ui.spinBox_anchor_x.setValue(0)
        self.ui.spinBox_anchor_y.setValue(0)
        self.ui.spinBox_X_offset.setValue(width)
        self.ui.spinBox_Y_offset.setValue(height)

    def _show_qimage_to_label(self, qimage):
        self.ui.label_image.setPixmap(QPixmap.fromImage(qimage))
        self._show_zoom_factor()
        self._update_srcImage_size()

🍅✌感兴趣的可以先收藏起来,点赞关注不迷路,想学习更多项目可以查看主页,大家在毕设选题,项目编程以及论文编写等相关问题都可以给我留言咨询,希望可以帮助同学们顺利毕业!🍅✌

5、源码获取方式

🍅由于篇幅限制,获取完整文章或源码、代做项目的,拉到文章底部即可看到个人联系方式。🍅

点赞、收藏、关注,不迷路,下方查看👇🏻获取联系方式👇🏻

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐