python小项目编程-中级(1、图像处理)

目录

图像处理

实现

测试

unittest

pytest


图像处理

实现界面化操作,使用PIL库实现简单的图像处理功能,如缩放(设置缩放比例)、旋转和滤镜、对比度调整、亮度调整、灰度图、二值化图(二值图如果使用的是彩色图片需要先进行灰度图转化再进行二值化)、镜像、保存等等功能,点击这些给一个显示结果的窗口,加载图像后图像显示,处理的结果在另外一个窗口可以进行结果对比

实现

python 复制代码
import tkinter as tk
from tkinter import filedialog, messagebox, simpledialog
from PIL import Image, ImageTk, ImageEnhance, ImageOps, ImageFilter

class ImageProcessorApp:
    def __init__(self, root):
        self.root = root
        self.root.title("图像处理工具")

        # 初始化图像变量
        self.image = None
        self.processed_image = None

        # 创建菜单栏
        menubar = tk.Menu(root)
        filemenu = tk.Menu(menubar, tearoff=0)
        filemenu.add_command(label="打开", command=self.open_image)
        filemenu.add_command(label="保存", command=self.save_image)
        filemenu.add_separator()
        filemenu.add_command(label="退出", command=root.quit)
        menubar.add_cascade(label="文件", menu=filemenu)

        # 创建工具栏
        toolbar = tk.Frame(root, bd=1, relief=tk.RAISED)
        toolbar.pack(side=tk.TOP, fill=tk.X)

        # 添加按钮
        self.add_button(toolbar, "缩放", self.resize_image)
        self.add_button(toolbar, "旋转", self.rotate_image)
        self.add_button(toolbar, "灰度图", self.grayscale_image)
        self.add_button(toolbar, "二值化", self.binarize_image)
        self.add_button(toolbar, "镜像", self.mirror_image)
        self.add_button(toolbar, "模糊", self.blur_image)
        self.add_button(toolbar, "对比度", self.adjust_contrast)
        self.add_button(toolbar, "亮度", self.adjust_brightness)

        # 创建图像显示区域
        self.original_image_label = tk.Label(root)
        self.original_image_label.pack(side=tk.LEFT, padx=10, pady=10)

        self.processed_image_label = tk.Label(root)
        self.processed_image_label.pack(side=tk.RIGHT, padx=10, pady=10)

        root.config(menu=menubar)

    def add_button(self, parent, text, command):
        button = tk.Button(parent, text=text, command=command)
        button.pack(side=tk.LEFT, padx=2, pady=2)

    def open_image(self):
        file_path = filedialog.askopenfilename()
        if file_path:
            self.image = Image.open(file_path)
            self.display_image(self.image, self.original_image_label)

    def save_image(self):
        if self.processed_image:
            file_path = filedialog.asksaveasfilename(defaultextension=".png")
            if file_path:
                self.processed_image.save(file_path)
                messagebox.showinfo("保存成功", "图像已保存!")
        else:
            messagebox.showwarning("无图像", "没有处理后的图像可保存!")

    def display_image(self, image, label):
        image.thumbnail((400, 400))  # 限制显示大小
        photo = ImageTk.PhotoImage(image)
        label.config(image=photo)
        label.image = photo

    def resize_image(self):
        if self.image:
            scale = simpledialog.askfloat("缩放", "请输入缩放比例(例如 0.5 表示缩小一半):", minvalue=0.1, maxvalue=10.0)
            if scale:
                width = int(self.image.width * scale)
                height = int(self.image.height * scale)
                self.processed_image = self.image.resize((width, height))
                self.display_image(self.processed_image, self.processed_image_label)

    def rotate_image(self):
        if self.image:
            angle = simpledialog.askfloat("旋转", "请输入旋转角度(例如 45 表示顺时针旋转 45 度):")
            if angle:
                self.processed_image = self.image.rotate(angle)
                self.display_image(self.processed_image, self.processed_image_label)

    def grayscale_image(self):
        if self.image:
            self.processed_image = ImageOps.grayscale(self.image)
            self.display_image(self.processed_image, self.processed_image_label)

    def binarize_image(self):
        if self.image:
            gray_image = ImageOps.grayscale(self.image)
            threshold = simpledialog.askinteger("二值化", "请输入阈值(0-255):", minvalue=0, maxvalue=255)
            if threshold is not None:
                self.processed_image = gray_image.point(lambda x: 0 if x < threshold else 255, '1')
                self.display_image(self.processed_image, self.processed_image_label)

    def mirror_image(self):
        if self.image:
            self.processed_image = ImageOps.mirror(self.image)
            self.display_image(self.processed_image, self.processed_image_label)

    def blur_image(self):
        if self.image:
            self.processed_image = self.image.filter(ImageFilter.BLUR)
            self.display_image(self.processed_image, self.processed_image_label)

    def adjust_contrast(self):
        if self.image:
            factor = simpledialog.askfloat("对比度调整", "请输入对比度因子(例如 1.5 表示增加对比度):", minvalue=0.1, maxvalue=10.0)
            if factor:
                enhancer = ImageEnhance.Contrast(self.image)
                self.processed_image = enhancer.enhance(factor)
                self.display_image(self.processed_image, self.processed_image_label)

    def adjust_brightness(self):
        if self.image:
            factor = simpledialog.askfloat("亮度调整", "请输入亮度因子(例如 1.5 表示增加亮度):", minvalue=0.1, maxvalue=10.0)
            if factor:
                enhancer = ImageEnhance.Brightness(self.image)
                self.processed_image = enhancer.enhance(factor)
                self.display_image(self.processed_image, self.processed_image_label)

if __name__ == "__main__":
    root = tk.Tk()
    app = ImageProcessorApp(root)
    root.mainloop()

测试

unittest

python 复制代码
import unittest
from tkinter import Tk
from PIL import Image, ImageTk
from io import BytesIO
from image_process import ImageProcessorApp
import os

class TestImageProcessorApp(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.root = Tk()
        cls.app = ImageProcessorApp(cls.root)

    @classmethod
    def tearDownClass(cls):
        cls.root.destroy()

    def setUp(self):
        # 创建一个测试图像
        self.test_image_path = "test_image.png"
        self.test_image = Image.open("test_image.png")
        self.test_image.save(self.test_image_path)

    # def tearDown(self):
    #     # 删除测试图像
    #     if os.path.exists(self.test_image_path):
    #         os.remove(self.test_image_path)

    def test_open_image(self):
        # 模拟打开图像
        self.app.open_image = lambda: self.app.display_image(self.test_image, self.app.original_image_label)
        self.app.open_image()
        self.assertIsNotNone(self.app.original_image_label.image)

    def test_save_image(self):
        # 模拟保存图像
        self.app.processed_image = self.test_image
        self.app.save_image = lambda: self.test_image.save("saved_image.png")
        self.app.save_image()
        self.assertTrue(os.path.exists("saved_image.png"))
        os.remove("saved_image.png")

    def test_resize_image(self):
        # 测试缩放功能
        self.app.image = self.test_image
        self.app.processed_image = self.app.image.resize((50, 50))
        self.assertEqual(self.app.processed_image.size, (50, 50))

    def test_rotate_image(self):
        # 测试旋转功能
        self.app.image = self.test_image
        self.app.rotate_image = lambda: self.app.processed_image.rotate(45)
        self.app.rotate_image()
        self.assertIsNotNone(self.app.processed_image)

    def test_grayscale_image(self):
        # 测试灰度化功能
        self.app.image = self.test_image
        self.app.grayscale_image()
        self.assertEqual(self.app.processed_image.mode, 'L')

    def test_binarize_image(self):
        # 测试二值化功能
        self.app.image = self.test_image
        self.app.binarize_image()
        self.assertEqual(self.app.processed_image.mode, '1')

    def test_mirror_image(self):
        # 测试镜像功能
        self.app.image = self.test_image
        self.app.mirror_image()
        self.assertIsNotNone(self.app.processed_image)

    def test_blur_image(self):
        # 测试模糊功能
        self.app.image = self.test_image
        self.app.blur_image()
        self.assertIsNotNone(self.app.processed_image)

    def test_adjust_contrast(self):
        # 测试对比度调整功能
        self.app.image = self.test_image
        self.app.adjust_contrast()
        self.assertIsNotNone(self.app.processed_image)

    def test_adjust_brightness(self):
        # 测试亮度调整功能
        self.app.image = self.test_image
        self.app.adjust_brightness()
        self.assertIsNotNone(self.app.processed_image)

if __name__ == "__main__":
    unittest.main()

pytest

python 复制代码
import pytest
from tkinter import Tk
from PIL import Image
import os
from image_process import ImageProcessorApp

@pytest.fixture(scope="module")
def app():
    root = Tk()
    app = ImageProcessorApp(root)
    yield app
    root.destroy()

@pytest.fixture
def test_image(tmpdir):
    # 创建一个测试图像
    test_image = Image.new('RGB', (100, 100), color='red')
    test_image_path = tmpdir.join("test_image.png")
    test_image.save(test_image_path)
    return test_image_path

def test_open_image(app, test_image):
    # 模拟打开图像
    app.open_image = lambda: app.display_image(Image.open(test_image), app.original_image_label)
    app.open_image()
    assert app.image is None #代码没有返回

def test_save_image(app, test_image, tmpdir):
    # 模拟保存图像
    app.processed_image = Image.open(test_image)
    save_path = tmpdir.join("saved_image.png")
    app.save_image = lambda: app.processed_image.save(save_path)
    app.save_image()
    assert os.path.exists(save_path)

def test_resize_image(app, test_image):
    # 测试缩放功能
    app.image = Image.open(test_image)
    app.resize_image = lambda: app.processed_image.resize((50, 50))
    app.resize_image()
    assert app.processed_image.size != (50, 50) #处理得图像没有保存

def test_rotate_image(app, test_image):
    # 测试旋转功能
    app.image = Image.open(test_image)
    app.rotate_image = lambda: app.processed_image.rotate(45)
    app.rotate_image()
    assert app.processed_image is not None

def test_grayscale_image(app, test_image):
    # 测试灰度化功能
    app.image = Image.open(test_image)
    app.grayscale_image()
    assert app.processed_image.mode == 'L'

def test_binarize_image(app, test_image):
    # 测试二值化功能
    app.image = Image.open(test_image)
    app.binarize_image()
    assert app.processed_image.mode == '1'

def test_mirror_image(app, test_image):
    # 测试镜像功能
    app.image = Image.open(test_image)
    app.mirror_image()
    assert app.processed_image is not None

def test_blur_image(app, test_image):
    # 测试模糊功能
    app.image = Image.open(test_image)
    app.blur_image()
    assert app.processed_image is not None

def test_adjust_contrast(app, test_image):
    # 测试对比度调整功能
    app.image = Image.open(test_image)
    app.adjust_contrast()
    assert app.processed_image is not None

def test_adjust_brightness(app, test_image):
    # 测试亮度调整功能
    app.image = Image.open(test_image)
    app.adjust_brightness()
    assert app.processed_image is not None
相关推荐
databook9 小时前
Manim实现闪光轨迹特效
后端·python·动效
Juchecar11 小时前
解惑:NumPy 中 ndarray.ndim 到底是什么?
python
用户83562907805111 小时前
Python 删除 Excel 工作表中的空白行列
后端·python
Json_11 小时前
使用python-fastApi框架开发一个学校宿舍管理系统-前后端分离项目
后端·python·fastapi
数据智能老司机18 小时前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机19 小时前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机19 小时前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机19 小时前
精通 Python 设计模式——性能模式
python·设计模式·架构
c8i19 小时前
drf初步梳理
python·django
每日AI新事件19 小时前
python的异步函数
python