大一期末作孽(python实现图片修改器)

Posted HUTEROX

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了大一期末作孽(python实现图片修改器)相关的知识,希望对你有一定的参考价值。

前言

本次提交的是期末作孽,一个图片修改器。
没办法规定用Python写,其他工具语言不香嘛。

效果预览

在这里插入图片描述

项目结构

在这里插入图片描述
text.py只是用来做测试的没啥用

屏幕适应

这个老问题了,也就是你电脑的缩放的问题
在这里插入图片描述
这里的话还是使用了一个类来实现我们的一个缩放转换的问题,不处理的话,对我们后面的功能会有很大的影响

class ChangeRealSize(object):
    '''

    该类主要对屏幕进行像素适配,按照缩放比对像素进行换算为100%显示
    示例:
    RealSize = ChangeRealSize()
    x=RealSize.getreal_xy(500)
    此时就可以换算为当前屏幕的像素

    '''


    def get_real_resolution(self):
        """获取真实的分辨率"""
        hDC = win32gui.GetDC(0)
        w = win32print.GetDeviceCaps(hDC, win32con.DESKTOPHORZRES)
        h = win32print.GetDeviceCaps(hDC, win32con.DESKTOPVERTRES)
        return w, h


    def get_screen_size(self):
        """获取缩放后的分辨率"""
        w = GetSystemMetrics (0)
        h = GetSystemMetrics (1)


        return w, h


    def getreal_xy(self,x):
        '''返回按照100%来算的真实的像素值'''
        real_resolution = self.get_real_resolution()
        screen_size = self.get_screen_size()
        screen_scale_rate = round(real_resolution[0] / screen_size[0], 2)
        try:
            x = x/screen_scale_rate
        except:
            #对笔记本进行适配,一般而言在100%比的机器上x不会出错
            x=1.25
        return int(x)

控件随窗口变化

我们这里使用的是place布局
但是呢使用的是相对的位置,这个换算呢就是 x/当前窗口大小
在这里插入图片描述
在这里插入图片描述

之后是图片随之变化
这个也简单其实就是实时获取控件大小,然后修改图片大小
在这里插入图片描述

图片处理的工具类

这个工具类的话,主要就是对图片进行处理的方法
具体的话就是实现这四个功能
在这里插入图片描述

图片处理的工具类的功能改变

由于我们的软件有两个模式,一个是单图模式,一个是批量模式
顾名思义,一个就是只对单个图片进行修改,另一个是批量处理,那么对应的方法自然有些区别(或者说是执行过程)。
那么具体是这么实现的呢大致如下:
在这里插入图片描述
工具类代码如下

class Tools(object):
    def __init__(self):
        self.RealSize = ChangeRealSize()

    def CHANGESIZE_One(self,path,x,y,save=".\\media\\Out_Image.png"):
        #不传递save为单图模式,默认是单图模式的所以函数名字就是单图模式
        image = Image.open(path)
        image = image.resize((self.RealSize.getreal_xy(x),self.RealSize.getreal_xy(y)), Image.ANTIALIAS)

        image.save(save)


        pass
    def ERZHIHUA_One(self,path,save=".\\media\\Out_Image.png"):
        image = Image.open(path)
        image = image.convert('L')
        t = []
        for i in range(256):
            # 杂质越多,值越大(轮廓越黑越明显)
            if i < 120:  # 160
                t.append(0)
            else:
                t.append(1)

        image = image.point(t, '1')

        image.save(save)

    def DANSHANGSE_One(self,path,RGB,save=".\\media\\Out_Image.png"):
        if save==".\\media\\Out_Image.png":
            self.ERZHIHUA_One(path)  # 执行二值化
            path = r'{}'.format(os.path.dirname((os.path.abspath(__file__)))) + '\\media\\Out_Image.png'
            image = Image.open(path)
            image = image.convert("RGB")
            width = image.size[0]
            height = image.size[1]
            new_image = Image.new("RGB", (width, height))
            for x in range(width):
                for y in range(height):
                    r, g, b = image.getpixel((x, y))
                    rgb = (r, g, b)

                    if rgb == (0, 0, 0):
                        rgb = RGB
                    new_image.putpixel((x, y), (int(rgb[0]), int(rgb[1]), int(rgb[2])))  # 画图
            new_image.save(path)
        else:
            self.ERZHIHUA_One(path,save)  # 执行二值化
            path = save
            image = Image.open(path)
            image = image.convert("RGB")
            width = image.size[0]
            height = image.size[1]
            new_image = Image.new("RGB", (width, height))
            for x in range(width):
                for y in range(height):
                    r, g, b = image.getpixel((x, y))
                    rgb = (r, g, b)

                    if rgb == (0, 0, 0):
                        rgb = RGB
                    new_image.putpixel((x, y), (int(rgb[0]), int(rgb[1]), int(rgb[2])))  # 画图
            new_image.save(path)

    def LUNKUO_One(self,path,save=".\\media\\Out_Image.png"):
        if save==".\\media\\Out_Image.png":

            self.ERZHIHUA_One(path)#执行二值化
            path = r'{}'.format(os.path.dirname((os.path.abspath(__file__))))+'\\media\\Out_Image.png'
            image = Image.open(path)
            image = image.convert("RGB")
            new_img = Image.new("RGB", (image.size[0], image.size[1]))
            for x in range(image.size[0]):
                for y in range(image.size[1]):
                    r, g, b = image.getpixel((x, y))
                    rgb = (r, g, b)
                    if rgb != (255, 255, 255):
                        if y > 2 and y < image.size[1] - 3:
                            r1, g1, b1 = image.getpixel((x, y - 3))
                            rgb1 = (r1, g1, b1)
                            r2, g2, b2 = image.getpixel((x, y + 3))
                            rgb2 = (r2, g2, b2)
                            if rgb1 == (255, 255, 255) and rgb == (0,0,0) and rgb2 == (0,0,0):
                                rgb = (0,0,0)
                            elif rgb1 == (0,0,0) and rgb == (0,0,0) and rgb2 == (255, 255, 255):
                                rgb = (0,0,0)
                            if rgb1 == (0,0,0) and rgb == (0,0,0) and rgb2 == (0,0,0):
                                rgb = (255, 255, 255)

                    new_img.putpixel((x, y), (int(rgb[0]), int(rgb[1]), int(rgb[2])))

            new_img.save(path)

        else:
            self.ERZHIHUA_One(path,save)  # 执行二值化
            path = save
            image = Image.open(path)
            image = image.convert("RGB")
            new_img = Image.new("RGB", (image.size[0], image.size[1]))
            for x in range(image.size[0]):
                for y in range(image.size[1]):
                    r, g, b = image.getpixel((x, y))
                    rgb = (r, g, b)
                    if rgb != (255, 255, 255):
                        if y > 2 and y < image.size[1] - 3:
                            r1, g1, b1 = image.getpixel((x, y - 3))
                            rgb1 = (r1, g1, b1)
                            r2, g2, b2 = image.getpixel((x, y + 3))
                            rgb2 = (r2, g2, b2)
                            if rgb1 == (255, 255, 255) and rgb == (0, 0, 0) and rgb2 == (0, 0, 0):
                                rgb = (0, 0, 0)
                            elif rgb1 == (0, 0, 0) and rgb == (0, 0, 0) and rgb2 == (255, 255, 255):
                                rgb = (0, 0, 0)
                            if rgb1 == (0, 0, 0) and rgb == (0, 0, 0) and rgb2 == (0, 0, 0):
                                rgb = (255, 255, 255)

                    new_img.putpixel((x, y), (int(rgb[0]), int(rgb[1]), int(rgb[2])))

            new_img.save(path)


单图模式下的图片处理

这个其实就是说明一点,那就是在单图模式下,由于只是针对一张图片处理
所以的话我们的工具类会默认把处理好的图片存放为一张图片
在这里插入图片描述
之后,我们再对图片进行转移
在这里插入图片描述

单图模式下的子线程方案

这个主要是由于有时候图片处理实在太慢,没有办法必须开一个子线程,这样防止页面卡顿。具体的实现见下:
在这里插入图片描述
当然还有一处
在这里插入图片描述

模式的切换

这个模式切换体现在两个方面
一个是控件变化
在这里插入图片描述

另一个自然是里面的函数发生了变化
我们通过这两个函数实现切换(在主类Window中)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这是控件显示与消失函数
在这里插入图片描述

在这里插入图片描述

批量模式下的路径读取(路径队列)(生产者)

这个毫无意外的是,批量模式下,多线程不可避免。
这里主要注意两点
一。路径获取与显示到窗口
在这里插入图片描述
二。队列加载
默认下队列大小为1000但是之后就会堵塞,所以只能去开个线程去添加队列
在这里插入图片描述

批量模式下的线程执行(消费者)

先看看执行函数
在这里插入图片描述

在这里插入图片描述

注意点

由于本程序使用了大量的子线程,所以对于每一个子线程,必须能够自己关闭,而不是一种运行或者处于堵塞状态,否者会带来大量的内存占用。
在这里插入图片描述

在这里插入图片描述

窗口类代码


GetRelXY = lambda x:x/600#相对布局换算默认600x600开始换算
Tools = Tools()
class Window():
    def __init__(self):
        self.win = tk.Tk()
        self.win.title("改图宝")
        self.win.geometry("600x600")
        self.win.iconbitmap(r".\\media\\tubioa.ico")
        self.win['background']='white'

        self.Top_menu = tk.Menu(self.win)

        self.Top_menu_G = tk.Menu(self.win,tearoff=0,activebackground="Aqua",font=("宋体",10))
        self.Top_menu_G.add_command(label="单图模式",command=self.Mode_One)
        self.Top_menu_G.add_separator()
        self.Top_menu_G.add_command(label="批量处理",command=self.Mode_Many)
        self.Top_menu_G.add_separator()
        self.Top_menu_G.add_command(label="退出",command=self.win.quit)

        self.Top_menu.add_cascade(label="模式选择",menu=self.Top_menu_G)

        self.win.config(menu=self.Top_menu)#顶栏字体不能改

        self.Select_Img=None #在单图模式下被选中的图片
        self._image_select_path=None
        self.Out_Image_Path =None#单图模式下的输出图片路径
        
        self.Select_Path=None #在批量模式下被选择的路径
        self.Check_Mode=tk.IntVar(value=1)

        #修改图片的复选框的变量,这个应该和线程在一块,其他的是radiobutton才对
        self.Check_Change_size=tk.IntVar()

        #图片提取处理
        self.Check_Radio_change=tk.IntVar()

        self.DanShangSe_color_rgb=(50,205,50) #单上色的颜色,默认绿色


        #线程数和线程的设置

        self.Thread_do_number=3#默认3个线程

            #相关设置
        self.Thread_number = tk.IntVar()
        self.Thread_listbox_l = ttk.Combobox(self.win, textvariable=self.Thread_number)
        self.Thread_listbox_l["values"] = (1, 2, 3, 4, 5)
        self.Thread_listbox_l.current(0)
        self.Thread_listbox_l.bind("<<ComboboxSelected>>", self.__set_thread_number)
        self.Thread_number.set(3)
        self.Thread_do_number = int(self.Thread_number.get())

            #2相关设置
        self.Thread_tips = tk.Label(self.win,bg='white',text="线程选择")

        #批量模式下的listbox

        self.Image_many_show_path_list=[]#显示的路径(图片)

        self.Many_Show_List_box_Sc大二期末作孽(SpringBoot+Vue前后端分离博客社区(重构White Hole))

python能做啥有趣的东西

HTML大一期末作业(html+css+js+jq)

大数据:大一整年感悟及总结

2022年大一下网页期末作业二十四节气纯htmlcss制作

安卓实训作孽之Linux命令手册