OpenCV教程02:图像处理系统1.0(翻转+形态学+滤波+缩放+旋转)

-------------OpenCV教程集合-------------

Python教程99:一起来初识OpenCV(一个跨平台的计算机视觉库)

OpenCV教程01:图像的操作(读取+显示+保存+属性+获取和修改像素值)

OpenCV教程02:图像处理系统1.0(翻转+形态学+滤波+缩放+旋转)
OpenCV教程03:绘制图形(线段、矩形、圆形、椭圆、多边形、箭头线)+水印文本

1.准备一张要输入的图像素材,没有的话也可以拿下面的图片练习一下,大小为250250或300300。基于OpenCV+tkinter的图像处理系统1.0,主要功能,翻转+形态学+滤波+缩放+旋转的示例用法,代码已跑亲测有效。感兴趣的朋友,自己学习一下。当然运行该代码,一些必要的第三方安装包是必不可少的,自己看着源码,逐一模块安装一下。

2.py源码不足的地方:
a.仅支持png和jpe的图片格式,如果你要添加其他的图片格式,自己在源码里面的通用对话框增加一些格式,默认是显示png格式。
b.没有办法,保存生成的新图片,当然你可以参考,历史pillow教程博文中,tk是如何显示和保存图片的。
Pillow教程10:设计博文的文字背景封面图,再也不担心找不到素材了
c.显示图片的窗口大小是固定的,输入的图像最好为250*250,这样刚好显示。如果你要显示更大的,自己调一下tk窗口组件的大小。
在这里插入图片描述
运行后的效果
在这里插入图片描述

# -*- coding: utf-8 -*-
# @Author : 小红牛
# 微信公众号:WdPython
import tkinter.messagebox as messagebox
import tkinter as tk
from tkinter import ttk
from PIL import Image, ImageTk
import os
from tkinter.filedialog import askopenfilename, asksaveasfilename
import cv2
import numpy as np

file_path = os.path.dirname(__file__)
test_file_path = file_path + os.sep + 'example.png'

WIN_WIDTH = 700
WIN_HEIGHT = 400


class Image_sys():
    def __init__(self):
        self.root = tk.Tk()
        self.root.geometry('700x400+80+80')
        self.root.title('图像处理系统1.0——微信公众号:WdPython')  # 设置窗口标题
        # self.root.iconbitmap('icon/icon.ico')  # 设置窗口图标
        # scnWidth, scnHeight = self.root.maxsize()
        # 屏幕中心居中
        # center = '%dx%d+%d+%d' % (WIN_WIDTH, WIN_HEIGHT, (scnWidth - WIN_WIDTH) / 2, (scnHeight - WIN_HEIGHT) / 2)
        # print(center)
        # 设置窗口的大小宽x高+偏移量
        # self.root.geometry(center)
        # 调用方法会禁止根窗体改变大小
        self.root.resizable(False, False)

        menubar = tk.Menu(self.root)  # 创建菜单栏 (Menu)
        self.root.config(menu=menubar)

        # 创建文件下拉菜单
        # 文件菜单下 tearoff=0 表示有没有分隔符,默认为有分隔符
        file_menu = tk.Menu(menubar, tearoff=0)
        # 为顶级菜单实例添加菜单,并级联相应的子菜单实例
        menubar.add_cascade(label="文件", menu=file_menu)
        file_menu.add_command(label="打开测试文件", command=self.open_test_file)
        file_menu.add_command(label="打开自定义文件", command=self.open_file)
        file_menu.add_command(label="复原", command=self.recover)
        file_menu.add_command(label="清除", command=self.clear)
        file_menu.add_command(label="退出", command=self.exit_sys)

        # 创建翻转下拉菜单
        turn_menu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="翻转", menu=turn_menu)
        turn_menu.add_command(label="水平", command=self.flip_horizontal)
        turn_menu.add_command(label="垂直", command=self.flip_vertical)
        turn_menu.add_command(label="水平&垂直", command=self.flip_hor_ver)

        # 形态学
        morph_menu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="形态学", menu=morph_menu)
        morph_menu.add_command(label="腐蚀", command=self.mor_corrosion)
        morph_menu.add_command(label="膨胀", command=self.mor_expand)
        morph_menu.add_command(label="开运算", command=self.mor_open_operation)
        morph_menu.add_command(label="闭运算", command=self.mor_close_operation)
        morph_menu.add_command(label="Morphological Gradient", command=self.mor_gradient)
        morph_menu.add_command(label="顶帽", command=self.mor_top_hat)
        morph_menu.add_command(label="黑帽", command=self.mor_black_hat)

        # 滤波
        filter_menu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="滤波", menu=filter_menu)
        filter_menu.add_command(label="均值", command=self.filter_mean)
        filter_menu.add_command(label="方框", command=self.filter_box)
        filter_menu.add_command(label="高斯", command=self.filter_gauss)
        filter_menu.add_command(label="中值", command=self.filter_mid_value)
        filter_menu.add_command(label="双边", command=self.filter_bilateral)

        # 缩放
        scale_menu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="缩放", menu=scale_menu)
        scale_menu.add_command(label="放大PyrUp", command=self.scale_pyrup)
        scale_menu.add_command(label="缩小PyrDown", command=self.scale_pyrdown)
        scale_menu.add_command(label="放大Resize", command=self.scale_zoom_in)
        scale_menu.add_command(label="缩小Resize", command=self.scale_zoom_out)

        # 旋转
        rotate_menu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="旋转", menu=rotate_menu)
        rotate_menu.add_command(label="平移", command=self.rotate_offset)
        rotate_menu.add_command(label="仿射", command=self.rotate_affine)
        rotate_menu.add_command(label="透射", command=self.rotate_transmission)
        rotate_menu.add_command(label="顺时针-无缩放", command=self.rotate_clockwise)
        rotate_menu.add_command(label="顺时针-缩放", command=self.rotate_clockwise_zoom)
        rotate_menu.add_command(label="逆时针-缩放", command=self.rotate_anti_zoom)
        rotate_menu.add_command(label="零旋转-缩放", command=self.rotate_zero_zoom)

        # 帮助
        help_menu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="帮助", menu=help_menu)
        help_menu.add_command(label="版权", command=self.help_copyright)
        help_menu.add_command(label="关于", command=self.help_about)

        # 创建一个容器,其父容器为self.root
        self.frame_scr = ttk.LabelFrame(self.root, text="Scour image:")
        # padx  pady   该容器外围需要留出的空余空间
        self.frame_scr.place(x=80, y=30, width=250, height=250)

        # 创建一个容器,其父容器为self.root
        self.frame_des = ttk.LabelFrame(self.root, text="Destination image:")
        # padx  pady   该容器外围需要留出的空余空间
        self.frame_des.place(x=370, y=30, width=250, height=250)

        # 创建两个label
        label_scr = ttk.Label(self.root, text='源图像', font=25, foreground='blue', anchor='center')
        label_scr.place(x=150, y=280, width=100, height=50)

        label_des = ttk.Label(self.root, text='目标图像', font=25, foreground='blue', anchor='center')
        label_des.place(x=450, y=280, width=100, height=50)

        self.label_scr_image = None
        self.label_des_image = None
        self.path = ''
        self.root.mainloop()

    def open_test_file(self):
        self.path = test_file_path
        image = Image.open(self.path)
        test_image = ImageTk.PhotoImage(image)
        if (self.label_des_image != None):
            self.label_des_image.pack_forget()  # 隐藏控件
            self.label_des_image = None
        if (self.label_scr_image == None):
            self.label_scr_image = tk.Label(self.frame_scr, image=test_image)
        self.label_scr_image.configure(image=test_image)
        self.label_scr_image.pack()
        self.root.mainloop()

    def open_file(self):
        # 打开文件对话框
        open_img_path = askopenfilename(initialdir=file_path,
                                        filetypes=[("png格式", "png"), ("jpg格式", "jpg"), ("bmp格式", "bmp")],
                                        parent=self.root,
                                        title='打开自定义图片')
        if (open_img_path == ''):
            return
        else:
            if (self.label_des_image != None):
                self.label_des_image.pack_forget()  # 隐藏控件
                self.label_des_image = None
            self.path = open_img_path
            image = Image.open(self.path)
            tk_image = ImageTk.PhotoImage(image)
            if (self.label_scr_image == None):
                self.label_scr_image = tk.Label(self.frame_scr, image=tk_image)
            self.label_scr_image.configure(image=tk_image)
            self.label_scr_image.pack()  # 显示控件
            self.root.mainloop()

    def recover(self):
        if (self.path == ''):
            return
        image = Image.open(self.path)
        tk_image = ImageTk.PhotoImage(image)
        if (self.label_des_image == None):
            return
        self.label_des_image.configure(image=tk_image)
        self.label_des_image.pack()
        self.root.mainloop()

    def clear(self):
        if (self.label_scr_image != None):
            self.label_scr_image.pack_forget()  # 隐藏控件
            self.label_scr_image = None
            self.path = ''
        if (self.label_des_image != None):
            self.label_des_image.pack_forget()  # 隐藏控件
            self.label_des_image = None
            self.path = ''

    def exit_sys(self):
        quit_root = messagebox.askokcancel('提示', '真的要退出么!~')
        if (quit_root == True):
            self.root.destroy()
        return

    def flip_horizontal(self):
        if (self.path == ''):
            return
        if (self.label_scr_image == None):
            return
        image = cv2.imdecode(np.fromfile(self.path, dtype=np.uint8), 1)  # 读取图片
        b, g, r = cv2.split(image)  # 三通道分离
        image = cv2.merge([r, g, b])  # 三通道合并
        # Flipped Horizontally 水平翻转
        image_hflip = cv2.flip(image, 1)
        image_pil_hflip = Image.fromarray(image_hflip)
        tk_image = ImageTk.PhotoImage(image_pil_hflip)
        if (self.label_des_image == None):
            self.label_des_image = tk.Label(self.frame_des, image=tk_image)
        self.label_des_image.configure(image=tk_image)
        self.label_des_image.pack()
        self.root.mainloop()

    def flip_vertical(self):
        if (self.path == ''):
            return
        if (self.label_scr_image == None):
            return
        image = cv2.imdecode(np.fromfile(self.path, dtype=np.uint8), 1)  # 读取图片
        b, g, r = cv2.split(image)  # 三通道分离
        image = cv2.merge([r, g, b])  # 三通道合并
        # Flipped Horizontally 水平翻转
        image_hflip = cv2.flip(image, 0)  # 垂直翻转
        image_pil_hflip = Image.fromarray(image_hflip)
        tk_image = ImageTk.PhotoImage(image_pil_hflip)
        if (self.label_des_image == None):
            self.label_des_image = tk.Label(self.frame_des, image=tk_image)
        self.label_des_image.configure(image=tk_image)
        self.label_des_image.pack()
        self.root.mainloop()

    def flip_hor_ver(self):
        if (self.path == ''):
            return
        if (self.label_scr_image == None):
            return
        image = cv2.imdecode(np.fromfile(self.path, dtype=np.uint8), 1)  # 读取图片
        b, g, r = cv2.split(image)  # 三通道分离
        image = cv2.merge([r, g, b])  # 三通道合并
        # Flipped Horizontally 水平翻转
        image_hflip = cv2.flip(image, -1)  # 水平垂直翻转
        image_pil_hflip = Image.fromarray(image_hflip)
        tk_image = ImageTk.PhotoImage(image_pil_hflip)
        if (self.label_des_image == None):
            self.label_des_image = tk.Label(self.frame_des, image=tk_image)
        self.label_des_image.configure(image=tk_image)
        self.label_des_image.pack()
        self.root.mainloop()

    def mor_corrosion(self):
        if (self.path == ''):
            return
        if (self.label_scr_image == None):
            return
        image = cv2.imdecode(np.fromfile(self.path, dtype=np.uint8), 1)  # 读取图片
        b, g, r = cv2.split(image)  # 三通道分离
        image = cv2.merge([r, g, b])  # 三通道合并
        # kernel = np.ones((5, 5), np.uint8)# 指定核大小
        # kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))  # 矩形结构
        kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))  # 椭圆结构
        # kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (5, 5))  # 十字形结构
        img_erosion = cv2.erode(image, kernel)  # 腐蚀
        image_pil_erosion = Image.fromarray(img_erosion)
        tk_image = ImageTk.PhotoImage(image_pil_erosion)
        if (self.label_des_image == None):
            self.label_des_image = tk.Label(self.frame_des, image=tk_image)
        self.label_des_image.configure(image=tk_image)
        self.label_des_image.pack()
        self.root.mainloop()
        # 膨胀

    def mor_expand(self):
        if (self.path == ''):
            return
        if (self.label_scr_image == None):
            return
        image = cv2.imdecode(np.fromfile(self.path, dtype=np.uint8), 1)  # 读取图片
        b, g, r = cv2.split(image)  # 三通道分离
        image = cv2.merge([r, g, b])  # 三通道合并
        # kernel = np.ones((5, 5), np.uint8)# 指定核大小
        # kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))  # 矩形结构
        kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))  # 椭圆结构
        # kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (5, 5))  # 十字形结构
        img_dilation = cv2.dilate(image, kernel)  # 膨胀
        image_pil_dilation = Image.fromarray(img_dilation)
        tk_image = ImageTk.PhotoImage(image_pil_dilation)
        if (self.label_des_image == None):
            self.label_des_image = tk.Label(self.frame_des, image=tk_image)
        self.label_des_image.configure(image=tk_image)
        self.label_des_image.pack()
        self.root.mainloop()
        # 开运算

    def mor_open_operation(self):
        if (self.path == ''):
            return
        if (self.label_scr_image == None):
            return
        image = cv2.imdecode(np.fromfile(self.path, dtype=np.uint8), 1)  # 读取图片
        b, g, r = cv2.split(image)  # 三通道分离
        image = cv2.merge([r, g, b])  # 三通道合并
        # kernel = np.ones((5, 5), np.uint8)# 指定核大小
        # kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))  # 矩形结构
        kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))  # 椭圆结构
        # kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (5, 5))  # 十字形结构
        img_open_operation = cv2.morphologyEx(image, cv2.MORPH_OPEN, kernel)  # 开运算
        image_pil_open = Image.fromarray(img_open_operation)
        tk_image = ImageTk.PhotoImage(image_pil_open)
        if (self.label_des_image == None):
            self.label_des_image = tk.Label(self.frame_des, image=tk_image)
        self.label_des_image.configure(image=tk_image)
        self.label_des_image.pack()
        self.root.mainloop()
        # 闭运算

    def mor_close_operation(self):
        if (self.path == ''):
            return
        if (self.label_scr_image == None):
            return
        image = cv2.imdecode(np.fromfile(self.path, dtype=np.uint8), 1)  # 读取图片
        b, g, r = cv2.split(image)  # 三通道分离
        image = cv2.merge([r, g, b])  # 三通道合并
        # kernel = np.ones((5, 5), np.uint8)# 指定核大小
        # kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))  # 矩形结构
        kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))  # 椭圆结构
        # kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (5, 5))  # 十字形结构
        img_close_operation = cv2.morphologyEx(image, cv2.MORPH_CLOSE, kernel)  # 闭运算
        image_pil_close = Image.fromarray(img_close_operation)
        tk_image = ImageTk.PhotoImage(image_pil_close)
        if (self.label_des_image == None):
            self.label_des_image = tk.Label(self.frame_des, image=tk_image)
        self.label_des_image.configure(image=tk_image)
        self.label_des_image.pack()
        self.root.mainloop()

    # 形态学梯度:膨胀图减去腐蚀图,dilation - erosion,这样会得到物体的轮廓:
    def mor_gradient(self):
        if (self.path == ''):
            return
        if (self.label_scr_image == None):
            return
        image = cv2.imdecode(np.fromfile(self.path, dtype=np.uint8), 1)  # 读取图片
        b, g, r = cv2.split(image)  # 三通道分离
        image = cv2.merge([r, g, b])  # 三通道合并
        # kernel = np.ones((5, 5), np.uint8)# 指定核大小
        # kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))  # 矩形结构
        kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))  # 椭圆结构
        # kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (5, 5))  # 十字形结构
        img_gradient = cv2.morphologyEx(image, cv2.MORPH_GRADIENT, kernel)  # 形态学梯度
        image_pil_gradient = Image.fromarray(img_gradient)
        tk_image = ImageTk.PhotoImage(image_pil_gradient)
        if (self.label_des_image == None):
            self.label_des_image = tk.Label(self.frame_des, image=tk_image)
        self.label_des_image.configure(image=tk_image)
        self.label_des_image.pack()
        self.root.mainloop()

    # 顶帽
    def mor_top_hat(self):
        if (self.path == ''):
            return
        if (self.label_scr_image == None):
            return
        image = cv2.imdecode(np.fromfile(self.path, dtype=np.uint8), 1)  # 读取图片
        b, g, r = cv2.split(image)  # 三通道分离
        image = cv2.merge([r, g, b])  # 三通道合并
        kernel = np.ones((7, 7), np.uint8)  # 指定核大小
        # kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))  # 矩形结构
        # kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))  # 椭圆结构
        # kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (5, 5))  # 十字形结构
        img_top_hat = cv2.morphologyEx(image, cv2.MORPH_TOPHAT, kernel)  # 顶帽
        image_pil_top_hat = Image.fromarray(img_top_hat)
        tk_image = ImageTk.PhotoImage(image_pil_top_hat)
        if (self.label_des_image == None):
            self.label_des_image = tk.Label(self.frame_des, image=tk_image)
        self.label_des_image.configure(image=tk_image)
        self.label_des_image.pack()
        self.root.mainloop()

    # 黑帽
    def mor_black_hat(self):
        if (self.path == ''):
            return
        if (self.label_scr_image == None):
            return
        image = cv2.imdecode(np.fromfile(self.path, dtype=np.uint8), 1)  # 读取图片
        b, g, r = cv2.split(image)  # 三通道分离
        image = cv2.merge([r, g, b])  # 三通道合并
        kernel = np.ones((7, 7), np.uint8)  # 指定核大小
        # kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))  # 矩形结构
        # kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))  # 椭圆结构
        # kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (5, 5))  # 十字形结构
        img_black_hat = cv2.morphologyEx(image, cv2.MORPH_BLACKHAT, kernel)  # 黑帽
        image_pil_black_hat = Image.fromarray(img_black_hat)
        tk_image = ImageTk.PhotoImage(image_pil_black_hat)
        if (self.label_des_image == None):
            self.label_des_image = tk.Label(self.frame_des, image=tk_image)
        self.label_des_image.configure(image=tk_image)
        self.label_des_image.pack()
        self.root.mainloop()

    '''
    常见噪声有椒盐噪声和高斯噪声,椒盐噪声可以理解为斑点,随机出现在图像中的黑点或白点;
    高斯噪声可以理解为拍摄图片时由于光照等原因造成的噪声;这样解释并不准确,只要能简单分辨即可。
    '''

    # 均值滤波
    def filter_mean(self):
        if (self.path == ''):
            return
        if (self.label_scr_image == None):
            return
        image = cv2.imdecode(np.fromfile(self.path, dtype=np.uint8), 1)  # 读取图片
        b, g, r = cv2.split(image)  # 三通道分离
        image = cv2.merge([r, g, b])  # 三通道合并
        img_mean = cv2.blur(image, (3, 3))  # 均值滤波
        image_pil_mean = Image.fromarray(img_mean)
        tk_image = ImageTk.PhotoImage(image_pil_mean)
        if (self.label_des_image == None):
            self.label_des_image = tk.Label(self.frame_des, image=tk_image)
        self.label_des_image.configure(image=tk_image)
        self.label_des_image.pack()
        self.root.mainloop()

        # 方框滤波方框滤波跟均值滤波很像,当可选参数normalize为True的时候,方框滤波就是均值滤波,

    # 如3×3的核,a就等于1/9;normalize为False的时候,a=1,相当于求区域内的像素和。
    def filter_box(self):
        if (self.path == ''):
            return
        if (self.label_scr_image == None):
            return
        image = cv2.imdecode(np.fromfile(self.path, dtype=np.uint8), 1)  # 读取图片
        b, g, r = cv2.split(image)  # 三通道分离
        image = cv2.merge([r, g, b])  # 三通道合并
        img_box = cv2.boxFilter(image, -1, (3, 3), normalize=False)  # 方框滤波
        image_pil_box = Image.fromarray(img_box)
        tk_image = ImageTk.PhotoImage(image_pil_box)
        if (self.label_des_image == None):
            self.label_des_image = tk.Label(self.frame_des, image=tk_image)
        self.label_des_image.configure(image=tk_image)
        self.label_des_image.pack()
        self.root.mainloop()

    # 高斯滤波与两种滤波方式,卷积核内的每个值都一样,相当于图像区域中每个像素的权重也就一样。
    # 高斯滤波的卷积核权重并不相同,中间像素点权重最高,越远离中心的像素权重越小。
    # 高斯滤波相比均值滤波效率要慢,但可以有效消除高斯噪声,能保留更多的图像细节,所以经常被称为最有用的滤波器。
    def filter_gauss(self):
        if (self.path == ''):
            return
        if (self.label_scr_image == None):
            return
        image = cv2.imdecode(np.fromfile(self.path, dtype=np.uint8), 1)  # 读取图片
        b, g, r = cv2.split(image)  # 三通道分离
        image = cv2.merge([r, g, b])  # 三通道合并
        img_gauss = cv2.GaussianBlur(image, (1, 1), 1)  # 方框滤波
        image_pil_gauss = Image.fromarray(img_gauss)
        tk_image = ImageTk.PhotoImage(image_pil_gauss)
        if (self.label_des_image == None):
            self.label_des_image = tk.Label(self.frame_des, image=tk_image)
        self.label_des_image.configure(image=tk_image)
        self.label_des_image.pack()
        self.root.mainloop()

    # 中值滤波,中值又叫中位数,是所有值排序后取中间的值。
    # 中值滤波就是用区域内的中值来代替本像素值,所以那种孤立的斑点,
    # 如0或255很容易消除掉,适用于去除椒盐噪声和斑点噪声。中值是一种非线性操作,效率相比前面几种线性滤波要慢。
    # 斑点噪声图,用中值滤波显然更好:
    def filter_mid_value(self):
        if (self.path == ''):
            return
        if (self.label_scr_image == None):
            return
        image = cv2.imdecode(np.fromfile(self.path, dtype=np.uint8), 1)  # 读取图片
        b, g, r = cv2.split(image)  # 三通道分离
        image = cv2.merge([r, g, b])  # 三通道合并
        img_mid_value = cv2.medianBlur(image, 5)  # 中值滤波
        image_pil_mid_value = Image.fromarray(img_mid_value)
        tk_image = ImageTk.PhotoImage(image_pil_mid_value)
        if (self.label_des_image == None):
            self.label_des_image = tk.Label(self.frame_des, image=tk_image)
        self.label_des_image.configure(image=tk_image)
        self.label_des_image.pack()
        self.root.mainloop()

    # 双边滤波,模糊操作基本都会损失掉图像细节信息,尤其前面介绍的线性滤波器,图像的边缘信息很难保留下来。
    # 然而,边缘edge信息是图像中很重要的一个特征,所以这才有了双边滤波。
    def filter_bilateral(self):
        if (self.path == ''):
            return
        if (self.label_scr_image == None):
            return
        image = cv2.imdecode(np.fromfile(self.path, dtype=np.uint8), 1)  # 读取图片
        b, g, r = cv2.split(image)  # 三通道分离
        image = cv2.merge([r, g, b])  # 三通道合并
        img_bilateral = cv2.bilateralFilter(image, 9, 75, 75)  # 双边滤波
        image_pil_bilateral = Image.fromarray(img_bilateral)
        tk_image = ImageTk.PhotoImage(image_pil_bilateral)
        if (self.label_des_image == None):
            self.label_des_image = tk.Label(self.frame_des, image=tk_image)
        self.label_des_image.configure(image=tk_image)
        self.label_des_image.pack()
        self.root.mainloop()

    # 图像金字塔操作的将是图像的像素问题(图像变清晰了还是模糊了)
    # 图像金字塔主要有两类:高斯金字塔和拉普拉斯金字塔。
    def scale_pyrup(self):
        if (self.path == ''):
            return
        if (self.label_scr_image == None):
            return
        image = cv2.imdecode(np.fromfile(self.path, dtype=np.uint8), 1)  # 读取图片
        b, g, r = cv2.split(image)  # 三通道分离
        image = cv2.merge([r, g, b])  # 三通道合并
        img_pyrup = cv2.pyrUp(image)  # 高斯金字塔
        image_pil_pyrup = Image.fromarray(img_pyrup)
        tk_image = ImageTk.PhotoImage(image_pil_pyrup)
        if (self.label_des_image == None):
            self.label_des_image = tk.Label(self.frame_des, image=tk_image)
        self.label_des_image.configure(image=tk_image)
        self.label_des_image.pack()
        self.root.mainloop()

    def scale_pyrdown(self):
        if (self.path == ''):
            return
        if (self.label_scr_image == None):
            return
        image = cv2.imdecode(np.fromfile(self.path, dtype=np.uint8), 1)  # 读取图片
        b, g, r = cv2.split(image)  # 三通道分离
        image = cv2.merge([r, g, b])  # 三通道合并
        img_pyrdown = cv2.pyrDown(image)  # 高斯金字塔
        image_pil_pyrdown = Image.fromarray(img_pyrdown)
        tk_image = ImageTk.PhotoImage(image_pil_pyrdown)
        if (self.label_des_image == None):
            self.label_des_image = tk.Label(self.frame_des, image=tk_image)
        self.label_des_image.configure(image=tk_image)
        # self.label_des_image.place(relx=0,rely=0)# 放置组件的不同方式
        self.label_des_image.pack()
        self.root.mainloop()
        # 放大

    def scale_zoom_in(self):
        if (self.path == ''):
            return
        if (self.label_scr_image == None):
            return
        image = cv2.imdecode(np.fromfile(self.path, dtype=np.uint8), 1)  # 读取图片
        b, g, r = cv2.split(image)  # 三通道分离
        image = cv2.merge([r, g, b])  # 三通道合并
        size = (2 * image.shape[1], 2 * image.shape[0])
        img_zoom_in = cv2.resize(image, size)  # 放大
        image_pil_zoom_in = Image.fromarray(img_zoom_in)
        tk_image = ImageTk.PhotoImage(image_pil_zoom_in)
        if (self.label_des_image == None):
            self.label_des_image = tk.Label(self.frame_des, image=tk_image)
        self.label_des_image.configure(image=tk_image)
        self.label_des_image.place(x=0, y=0)  # 放置组件的不同方式与金字塔放大相比对齐方式不同显示不同
        # self.label_des_image.pack()
        self.root.mainloop()

    # 缩小
    def scale_zoom_out(self):
        if (self.path == ''):
            return
        if (self.label_scr_image == None):
            return
        image = cv2.imdecode(np.fromfile(self.path, dtype=np.uint8), 1)  # 读取图片
        b, g, r = cv2.split(image)  # 三通道分离
        image = cv2.merge([r, g, b])  # 三通道合并
        size = (int(0.3 * image.shape[1]), int(0.3 * image.shape[0]))
        img_zoom_out = cv2.resize(image, size)  # 放大
        image_pil_zoom_out = Image.fromarray(img_zoom_out)
        tk_image = ImageTk.PhotoImage(image_pil_zoom_out)
        if (self.label_des_image == None):
            self.label_des_image = tk.Label(self.frame_des, image=tk_image)
        self.label_des_image.configure(image=tk_image)
        # self.label_des_image.place(x=0, y=0)
        self.label_des_image.pack()
        self.root.mainloop()

    # 平移
    def rotate_offset(self):
        if (self.path == ''):
            return
        if (self.label_scr_image == None):
            return
        image = cv2.imdecode(np.fromfile(self.path, dtype=np.uint8), 1)  # 读取图片
        b, g, r = cv2.split(image)  # 三通道分离
        image = cv2.merge([r, g, b])  # 三通道合并
        width, height = image.shape[1], image.shape[0]
        direction = np.float32([[1, 0, 50], [0, 1, 50]])  # 沿x轴移动50,沿y轴移动50
        img_offset = cv2.warpAffine(image, direction, (width, height))
        image_pil_offset = Image.fromarray(img_offset)
        tk_image = ImageTk.PhotoImage(image_pil_offset)
        if (self.label_des_image == None):
            self.label_des_image = tk.Label(self.frame_des, image=tk_image)
        self.label_des_image.configure(image=tk_image)
        # self.label_des_image.place(x=0, y=0)
        self.label_des_image.pack()
        self.root.mainloop()

    # 仿射-需要三个点坐标
    def rotate_affine(self):
        if (self.path == ''):
            return
        if (self.label_scr_image == None):
            return
        image = cv2.imdecode(np.fromfile(self.path, dtype=np.uint8), 1)  # 读取图片
        b, g, r = cv2.split(image)  # 三通道分离
        image = cv2.merge([r, g, b])  # 三通道合并
        width, height = image.shape[1], image.shape[0]
        pts1 = np.float32([[50, 50], [200, 50], [50, 200]])
        pts2 = np.float32([[10, 100], [200, 50], [100, 250]])
        rot_mat = cv2.getAffineTransform(pts1, pts2)  # 沿x轴移动50,沿y轴移动50
        img_affine = cv2.warpAffine(image, rot_mat, (width, height))
        image_pil_affine = Image.fromarray(img_affine)
        tk_image = ImageTk.PhotoImage(image_pil_affine)
        if (self.label_des_image == None):
            self.label_des_image = tk.Label(self.frame_des, image=tk_image)
        self.label_des_image.configure(image=tk_image)
        # self.label_des_image.place(x=0, y=0)
        self.label_des_image.pack()
        self.root.mainloop()

    # 透射 -需要四个点的坐标
    def rotate_transmission(self):
        if (self.path == ''):
            return
        if (self.label_scr_image == None):
            return
        image = cv2.imdecode(np.fromfile(self.path, dtype=np.uint8), 1)  # 读取图片
        b, g, r = cv2.split(image)  # 三通道分离
        image = cv2.merge([r, g, b])  # 三通道合并
        width, height = image.shape[1], image.shape[0]
        pts1 = np.float32([[56, 65], [238, 52], [28, 237], [239, 240]])
        pts2 = np.float32([[0, 0], [250, 0], [0, 250], [250, 250]])
        rot_mat = cv2.getPerspectiveTransform(pts1, pts2)
        img_clockwise = cv2.warpPerspective(image, rot_mat, (250, 250))  # 透射与仿射的函数不一样
        image_pil_clockwise = Image.fromarray(img_clockwise)
        tk_image = ImageTk.PhotoImage(image_pil_clockwise)
        if (self.label_des_image == None):
            self.label_des_image = tk.Label(self.frame_des, image=tk_image)
        self.label_des_image.configure(image=tk_image)
        # self.label_des_image.place(x=0, y=0)
        self.label_des_image.pack()
        self.root.mainloop()

    # 顺时针无缩放
    def rotate_clockwise(self):
        if (self.path == ''):
            return
        if (self.label_scr_image == None):
            return
        image = cv2.imdecode(np.fromfile(self.path, dtype=np.uint8), 1)  # 读取图片
        b, g, r = cv2.split(image)  # 三通道分离
        image = cv2.merge([r, g, b])  # 三通道合并
        width, height = image.shape[1], image.shape[0]
        rotate_center = (width // 2, height // 2)
        rot_mat = cv2.getRotationMatrix2D(rotate_center, angle=-45, scale=1)  # 旋转中心rotate_center,角度degree, 缩放scale
        img_clockwise = cv2.warpAffine(image, rot_mat, (width, height))
        image_pil_clockwise = Image.fromarray(img_clockwise)
        tk_image = ImageTk.PhotoImage(image_pil_clockwise)
        if (self.label_des_image == None):
            self.label_des_image = tk.Label(self.frame_des, image=tk_image)
        self.label_des_image.configure(image=tk_image)
        # self.label_des_image.place(x=0, y=0)
        self.label_des_image.pack()
        self.root.mainloop()

    # 顺时针-缩放
    def rotate_clockwise_zoom(self):
        if (self.path == ''):
            return
        if (self.label_scr_image == None):
            return
        image = cv2.imdecode(np.fromfile(self.path, dtype=np.uint8), 1)  # 读取图片
        b, g, r = cv2.split(image)  # 三通道分离
        image = cv2.merge([r, g, b])  # 三通道合并
        width, height = image.shape[1], image.shape[0]
        rotate_center = (width // 2, height // 2)
        rot_mat = cv2.getRotationMatrix2D(rotate_center, angle=-45, scale=0.6)  # 旋转中心rotate_center,角度degree, 缩放scale
        img_clockwise_zoom = cv2.warpAffine(image, rot_mat, (width, height))
        image_pil_clockwise_zoom = Image.fromarray(img_clockwise_zoom)
        tk_image = ImageTk.PhotoImage(image_pil_clockwise_zoom)
        if (self.label_des_image == None):
            self.label_des_image = tk.Label(self.frame_des, image=tk_image)
        self.label_des_image.configure(image=tk_image)
        # self.label_des_image.place(x=0, y=0)
        self.label_des_image.pack()
        self.root.mainloop()

    # 逆时针-缩放
    def rotate_anti_zoom(self):
        if (self.path == ''):
            return
        if (self.label_scr_image == None):
            return
        image = cv2.imdecode(np.fromfile(self.path, dtype=np.uint8), 1)  # 读取图片
        b, g, r = cv2.split(image)  # 三通道分离
        image = cv2.merge([r, g, b])  # 三通道合并
        width, height = image.shape[1], image.shape[0]
        rotate_center = (width // 2, height // 2)
        rot_mat = cv2.getRotationMatrix2D(rotate_center, angle=45, scale=0.6)  # 旋转中心rotate_center,角度degree, 缩放scale
        img_clockwise_zoom = cv2.warpAffine(image, rot_mat, (width, height))
        image_pil_clockwise_zoom = Image.fromarray(img_clockwise_zoom)
        tk_image = ImageTk.PhotoImage(image_pil_clockwise_zoom)
        if (self.label_des_image == None):
            self.label_des_image = tk.Label(self.frame_des, image=tk_image)
        self.label_des_image.configure(image=tk_image)
        # self.label_des_image.place(x=0, y=0)
        self.label_des_image.pack()
        self.root.mainloop()

    # 零旋转-缩放
    def rotate_zero_zoom(self):
        if (self.path == ''):
            return
        if (self.label_scr_image == None):
            return
        image = cv2.imdecode(np.fromfile(self.path, dtype=np.uint8), 1)  # 读取图片
        b, g, r = cv2.split(image)  # 三通道分离
        image = cv2.merge([r, g, b])  # 三通道合并
        width, height = image.shape[1], image.shape[0]
        rotate_center = (width // 2, height // 2)
        rot_mat = cv2.getRotationMatrix2D(rotate_center, angle=0, scale=0.6)  # 旋转中心rotate_center,角度degree, 缩放scale
        img_zero_zoom = cv2.warpAffine(image, rot_mat, (width, height))
        image_pil_zero_zoom = Image.fromarray(img_zero_zoom)
        tk_image = ImageTk.PhotoImage(image_pil_zero_zoom)
        if (self.label_des_image == None):
            self.label_des_image = tk.Label(self.frame_des, image=tk_image)
        self.label_des_image.configure(image=tk_image)
        # self.label_des_image.place(x=0, y=0)
        self.label_des_image.pack()
        self.root.mainloop()

    def help_copyright(self):
        tk.messagebox.showinfo(title='版权', message='微信公众号:WdPython!~')

    def help_about(self):
        tk.messagebox.showinfo(title='关于', message='微信公众号:WdPython!~!~')


if __name__ == '__main__':
    Image_sys()

完毕!!感谢您的收看

----------★★历史博文集合★★----------

我的零基础Python教程,Python入门篇 进阶篇 视频教程 Py安装py项目 Python模块 Python爬虫 Json Xpath 正则表达式 Selenium Etree CssGui程序开发 Tkinter Pyqt5 列表元组字典数据可视化 matplotlib 词云图 Pyecharts 海龟画图 Pandas Bug处理 电脑小知识office自动化办公 编程工具 NumPy Pygame

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/768664.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

调试 hipcc 的llvm llc gpu目标代码生成模块

源码: hello_vectorAdd.hip: __global__ void vectorAdd(const float *A, const float *B, float *C) {int i blockDim.x * blockIdx.x threadIdx.x;C[i] A[i] B[i] 0.0f; } Makefile: x.O1.s: hello_vectorAdd.hip../../local_amdgpu/bin/clang ./hello_vec…

【C++】#1

关键字&#xff1a; 基本框架、多个main执行、快捷键、cout规则 基本框架&#xff1a; #include <iostream> using namespace std;int main() {//具体内容return 0; } 多个main函数可执行&#xff1a; 常用快捷键&#xff1a; cout规则&#xff1a;

eventloop 事件循环机制 (猜答案)

// eventloop 事件循环机制// console.log(555);setTimeout(() > {console.log(666);})let p new Promise((resolve,reject)>{// 同步执行console.log(111);resolve();});// promise 的回调函数是异步的微任务p.then(v > {console.log(222);}, r > {console.log(r…

pjsip环境搭建、编译源码生成.lib库

使用平台&#xff1a; windows qt(5.15.2) vs(2019)x86 pjsip版本以及第三方库使用 pjsip 2.10 ffmpeg4.2.1 sdl2.0.12pjsip源码链接&#xff1a; https://github.com/pjsip/pjproject源码环境配置 首先创建两个文件夹&#xff0c;分别是include、lib其中include放置ff…

【leetcode64-69二分查找、70-74栈、75-77堆】

二分查找[64-69] 时间复杂度O(log n)&#xff0c;要想到二分排序 35.搜索插入位置 class Solution:def searchInsert(self, nums: List[int], target: int) -> int:left 0right len(nums)-1while left < right: #左闭右闭mid (leftright)//2if nums[mid] < target…

【SpringBoot配置文件读取】无法读取yaml文件中文字符

1. yaml配置文件 注意要将该文件编码格式改为UTF-8 spring:application:name: 好好学习admin:name: 李斯age: 24books:- name: 数据结构desc: 数据书- name: 编译原理desc: 编译书2.配置实体类 Data设置get&#xff0c;set方法Component注册为BeanConfigurationProperties(p…

Android设备信息(DevInfo)

软件介绍 设备信息&#xff08;DevInfo&#xff09;一款评分非常不错的手机硬件及各种信息检测应用&#xff0c;安卓设备硬件检测工具。可以全面查看手机的各种信息、包括&#xff1a;Android系统版本的详细信息、芯片CPU处理器的详细信息、全球卫星定位、测试功能、硬件温度、…

【深度学习】Transformer

李宏毅深度学习笔记 https://blog.csdn.net/Tink1995/article/details/105080033 https://blog.csdn.net/leonardotu/article/details/135726696 https://blog.csdn.net/u012856866/article/details/129790077 Transformer 是一个基于自注意力的序列到序列模型&#xff0c;与基…

Labview绘制柱状图

废话不多说&#xff0c;直接上图 我喜欢用NXG风格&#xff0c;这里我个人选的是xy图。 点击箭头指的地方 选择直方图 插值选择第一个 直方图类型我选的是第二个效果如图。 程序部分如图。 最后吐槽一句&#xff0c;现在看CSDN好多文章都要收费了&#xff0c;哪怕一些简单的入…

比较多种msvcr110.dll丢失的解决方法,哪一种更加方便?

当遇到“msvcr110.dll丢失”这种问题时&#xff0c;这通常意味着你的系统中缺少了Microsoft Visual C 2012 Redistributable的组件。下面我将详细介绍五种解决方法&#xff0c;并对比它们的优点。 一.多种msvcr110.dll丢失的解决方法 方法 1: 重新安装Microsoft Visual C 2012…

《IT 领域准新生暑期预习指南:开启未来科技之旅》

IT专业入门&#xff0c;高考假期预习指南 高考的落幕&#xff0c;只是人生长途中的一个逗号&#xff0c;对于心怀 IT 梦想的少年们&#xff0c;新的征程已然在脚下铺展。这个七月&#xff0c;当分数尘埃落定&#xff0c;你们即将迈向新的知识殿堂&#xff0c;而这个假期&#…

DEPTHAI 2.27.0 发布!

小伙伴们大家好&#xff0c;我们发布了DepthAI 2.27.0版本&#xff0c;本次对DepthAI库有了一些小更新&#xff0c;以下是更新内容。 功能 设置DEPTHAI_ENABLE_FEEDBACK_CRASHDUMP时自动故障转储收集&#xff1b; 漏洞修补 修复深度超出ImageAlign节点时生成PointCloud的问…

安卓手机软件自动运行插件的开发流程及代码科普!

随着智能手机的普及和移动互联网的快速发展&#xff0c;安卓手机软件的需求日益旺盛&#xff0c;为了提高软件的功能性和扩展性&#xff0c;许多开发者选择通过插件的方式为软件添加新功能。 一、安卓手机软件自动运行插件的开发流程 1、明确需求与目标 在开发安卓手机自动运…

STM32——GPIO(点亮LED)

一、GPIO是什么&#xff1f; 1、GPI/O(general porpose intput output):通用输入输出端口的简称&#xff0c;通俗地说&#xff0c;就是我们所学的51单片机的IO口&#xff0c;即P0_0等。但要注意&#xff1a;并非所有的引脚都是GPIO 输出模式下可控制端口输出高低电平&#xf…

echarts-wordcloud:打造个性化词云库

前言 在当今信息爆炸的时代&#xff0c;如何从海量的文本数据中提取有用的信息成为了一项重要的任务。词云作为一种直观、易于理解的数据可视化方式&#xff0c;被广泛应用于文本分析和可视化领域。本文将介绍一种基于 echarts-wordcloud 实现的词云库&#xff0c;通过其丰富的…

uniapp + vue3 + Script Setup 写法变动 (持续更新)

一、uniapp 应用生命周期&#xff1a; https://uniapp.dcloud.net.cn/tutorial/vue3-composition-api.html 注意&#xff1a; 应用生命周期仅可在App.vue中监听&#xff0c;在其它页面监听无效。 二 、uniapp页面生命周期&#xff1a; https://uniapp.dcloud.net.cn/tutori…

【Rust入门教程】安装Rust

文章目录 前言Rust简介Rust的安装更新与卸载rust更新卸载 总结 前言 在当今的编程世界中&#xff0c;Rust语言以其独特的安全性和高效性吸引了大量开发者的关注。Rust是一种系统编程语言&#xff0c;专注于速度、内存安全和并行性。它具有现代化的特性&#xff0c;同时提供了低…

准化 | 水系统碳中和标准体系初见成效

2024年5月31日&#xff0c;中华环保联合会发布《团体标准公告 2024年第10号&#xff08;总第78号&#xff09;》&#xff0c;批准发布了由中华环保联合会提出并归口的《废水处理温室气体监测技术规程》(T/ACEF 142-2024)、《工业水系统碳排放核算方法与报告指南》(T/ACEF143-20…

解决ps暂存盘已满的问题

点击编辑->首选项->暂存盘 ps默认暂存盘使用的是c盘&#xff0c;我们改成d盘即可 然后重启ps

羊大师:自然力量,守护头皮健康

在繁忙的生活节奏中&#xff0c;我们往往忽略了与大自然最亲密的接触&#xff0c;也忘记了用自然的力量来呵护我们的每一寸肌肤&#xff0c;尤其是那细腻而脆弱的头皮。头皮&#xff0c;作为头发的根基&#xff0c;其健康直接决定了秀发的光泽与密度。 想象一下&#xff0c;清晨…