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

发布于:2025-02-22 ⋅ 阅读:(9) ⋅ 点赞:(0)

目录

图像处理

实现

测试

unittest

pytest


图像处理

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

实现

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

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

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


网站公告

今日签到

点亮在社区的每一天
去签到