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

news2024/10/6 18:21:51

-------------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.coloradmin.cn/o/1890556.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

272. 最长公共上升子序列

Powered by:NEFU AB-IN Link 文章目录 272. 最长公共上升子序列题意思路代码 272. 最长公共上升子序列 题意 如题 思路 若按这个思路的话&#xff0c;代码为 O ( n 3 ) O(n^3) O(n3) for (int i 1; i < n; i ) {for (int j 1; j < n; j ){f[i][j] f[i - 1][j];…

CoAtNet(NeurIPS 2023, Google)论文解读

paper&#xff1a;CoAtNet: Marrying Convolution and Attention for All Data Sizes third-party implementation&#xff1a;https://github.com/huggingface/pytorch-image-models/blob/main/timm/models/maxxvit.py 背景 自AlexNet以来&#xff0c;ConvNets一直是计算机…

antfu/ni 在 Windows 下的安装

问题 全局安装 ni 之后&#xff0c;第一次使用会有这个问题 解决 在 powershell 中输入 Remove-Item Alias:ni -Force -ErrorAction Ignore之后再次运行 ni Windows 11 下的 Powershell 环境配置 可以参考 https://github.com/antfu-collective/ni?tabreadme-ov-file#how …

登录功能和校验

基础版 controller package com.web.management.controller;import com.web.management.pojo.Emp; import com.web.management.pojo.Result; import com.web.management.service.EmpService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.anno…

STM32F1+HAL库+FreeTOTS学习4——任务挂起与恢复

STM32F1HAL库FreeTOTS学习4——任务挂起与恢复 任务挂起和恢复的API介绍代码实现 上一期我们学习了FreeRTOS中任务创建的两种方法&#xff0c;这一期我们学习任务的挂起和恢复。 任务挂起和恢复的API介绍 在 &#xff1a;STM32F1HAL库FreeTOTS学习1——FreeRTOS入门 的学习中&…

Webpack: 核心流程之Init、Make、Seal

概述 在前文中&#xff0c;我们了解了 Webpack 的基本应用、性能优化、Loader 与 Plugin 组件开发方方面面的知识&#xff0c;相信学习过这些内容之后&#xff0c;你已经对 Webpack 有相当深入的理解了&#xff0c;可以开始从更底层的视角&#xff0c;自底向上重新审视 Webpac…

R可视化数据必要格式——长格式

一、引言 我们在对数据进行可视化时遇到最头疼、最常见的问题是什么&#xff1f;数据问题。 因为我们往往不会从零自己编程进行可视化&#xff0c;往往是现有模板或积累&#xff0c;而正确的数据格式对应正确的图形包要求&#xff0c;一定会正确出图&#xff0c;所以只有一个问…

uniapp H5页面设置跨域请求

记录一下本地服务在uniapp H5页面访问请求报跨域的错误 这是我在本地起的服务端口号为8088 ip大家可打开cmd 输入ipconfig 查看 第一种方法 在源码视图中配置 "devServer": {"https": false, // 是否启用 https 协议&#xff0c;默认false"port&q…

AI与大模型工程师证书研修班报名啦!

人工智能大模型是指拥有超大规模参数&#xff08;通常在十亿个以上&#xff09;、超强计算资源的机器学习模型&#xff0c;能够处理海量数据&#xff0c;完成各种复杂任务&#xff0c;如自然语言处理、图像识别等。计算机硬件性能不断提升&#xff0c;深度学习算法快速优化&…

【笔记】太久不用redis忘记怎么后台登陆了

&#xff01;首先启动虚拟机linux的centos7 2.启动finalshell 我的redis启动在根目录用 redis-server redis.conf --启动 systemctl status redis --查看redis状态 是否active redis-cli -h centos的ip地址 -p 你要用的redis端口号&#xff08;默认为6379&#xff09; -a 你…

基于xilinx FPGA的GTX/GTH/GTY位置信息查看方式(如X0Y0在bank几)

目录 1 概述2 参考文档3 查看方式4查询总结&#xff1a; 1 概述 本文用于介绍如何查看xilinx fpga GTX得位置信息&#xff08;如X0Y0在哪个BANK/Quad&#xff09;。 2 参考文档 《ug476_7Series_Transceivers》 《pg156-ultrascale-pcie-gen3-en-us-4.4》 3 查看方式 通过…

动态住宅代理IP的优势是什么?什么地方用到?

在大数据时代的背景下&#xff0c;代理IP成为了很多企业顺利开展的重要工具。代理IP地址可以分为住宅代理IP地址和数据中心代理IP地址。选择住宅代理IP的好处是可以实现真正的高匿名性&#xff0c;而使用数据中心代理IP可能会暴露自己使用代理的情况。 住宅代理IP是指互联网服务…

NSSCTF-Web题目22(弱比较、数组绕过)

目录 [鹤城杯 2021]Middle magic 1、题目 2、知识点 3、思路 [WUSTCTF 2020]朴实无华 4、题目 5、知识点 6、思路 [鹤城杯 2021]Middle magic 1、题目 2、知识点 代码审计&#xff0c;弱比较、数组绕过 3、思路 打开题目&#xff0c;出现源代码&#xff0c;我们进行审…

探讨命令模式及其应用

目录 命令模式命令模式结构命令模式适用场景命令模式优缺点练手题目题目描述输入描述输出描述题解 命令模式 命令模式是一种行为设计模式&#xff0c; 它可将请求转换为一个包含与请求相关的所有信息的独立对象。 该转换让你能根据不同的请求将方法参数化、 延迟请求执行或将其…

昂科烧录器支持MindMotion灵动微电子的32位微控制器MM32L052NT

芯片烧录行业领导者-昂科技术近日发布最新的烧录软件更新及新增支持的芯片型号列表&#xff0c;其中MindMotion灵动微电子的32位微控制器MM32L052NT已经被昂科的通用烧录平台AP8000所支持。 MM32L052NT使用高性能的ARM Cortex-M0为内核的32位微控制器&#xff0c;最高工作频率…

助力游戏实现应用内运营闭环,融云游戏社交方案升级!

通信能力在所有应用场景都是必备组件&#xff0c;这源于社交属性带给应用的增长神话。 在游戏场景&#xff0c;玩家从少数核心向大众用户泛化扩展的过程&#xff0c;就是游戏深度融合社交能力的过程。 从单机到联机&#xff0c;游戏乐趣的升级 1996 年&#xff0c;游戏界顶流…

cesium楼层分户分析

文章目录 1. 区域绘制2. 户型切分3. 楼房分层4. 编辑房户信息5. 查看房户信息6. 数据库6.1. 楼栋数据库6.2. 单位数据库 7. 房户数据库 1. 区域绘制 点击绘制图形&#xff0c;激活画笔&#xff0c;右键结束绘制。 输入框可以更换地址前缀。 分户坐标是由绘制的多个点组成的&…

自动化任务工具 -- zTasker v1.94 绿色版

软件简介 zTasker 是一款功能强大的自动化任务管理软件&#xff0c;以其简洁易用、一键式操作而著称。软件体积小巧&#xff0c;启动迅速&#xff0c;提供了超过100种任务类型和30多种定时/条件执行方法&#xff0c;能够满足用户在自动化方面的多样化需求。 zTasker 支持定时任…

js学习--制作选项卡

选项卡制作 <!DOCTYPE html> <html lang"zh"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><style>.text_one {width: 11.4%;height: 200px…

gdbserver 指南

文章目录 1. 前言2. gdbserver 远程调试2.1 准备工作2.1.1 准备 客户端 gdb 程序2.1.2 准备 服务端 gdbserver2.1.3 准备 被调试程序 2.2 调试2.2.1 通过网络远程调试2.2.1.1 通过 gdbserver 直接启动程序调试2.2.1.2 通过 gdbserver 挂接到已运行程序调试 2.2.2 通过串口远程调…