当前位置: 首页 > news >正文

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 npfile_path = os.path.dirname(__file__)
test_file_path = file_path + os.sep + 'example.png'WIN_WIDTH = 700
WIN_HEIGHT = 400class 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.rootself.frame_scr = ttk.LabelFrame(self.root, text="Scour image:")# padx  pady   该容器外围需要留出的空余空间self.frame_scr.place(x=80, y=30, width=250, height=250)# 创建一个容器,其父容器为self.rootself.frame_des = ttk.LabelFrame(self.root, text="Destination image:")# padx  pady   该容器外围需要留出的空余空间self.frame_des.place(x=370, y=30, width=250, height=250)# 创建两个labellabel_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 = Noneself.label_des_image = Noneself.path = ''self.root.mainloop()def open_test_file(self):self.path = test_file_pathimage = 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 = Noneif (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 == ''):returnelse:if (self.label_des_image != None):self.label_des_image.pack_forget()  # 隐藏控件self.label_des_image = Noneself.path = open_img_pathimage = 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 == ''):returnimage = Image.open(self.path)tk_image = ImageTk.PhotoImage(image)if (self.label_des_image == None):returnself.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 = Noneself.path = ''if (self.label_des_image != None):self.label_des_image.pack_forget()  # 隐藏控件self.label_des_image = Noneself.path = ''def exit_sys(self):quit_root = messagebox.askokcancel('提示', '真的要退出么!~')if (quit_root == True):self.root.destroy()returndef flip_horizontal(self):if (self.path == ''):returnif (self.label_scr_image == None):returnimage = 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 == ''):returnif (self.label_scr_image == None):returnimage = 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 == ''):returnif (self.label_scr_image == None):returnimage = 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 == ''):returnif (self.label_scr_image == None):returnimage = 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 == ''):returnif (self.label_scr_image == None):returnimage = 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 == ''):returnif (self.label_scr_image == None):returnimage = 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 == ''):returnif (self.label_scr_image == None):returnimage = 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 == ''):returnif (self.label_scr_image == None):returnimage = 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 == ''):returnif (self.label_scr_image == None):returnimage = 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 == ''):returnif (self.label_scr_image == None):returnimage = 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 == ''):returnif (self.label_scr_image == None):returnimage = 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 == ''):returnif (self.label_scr_image == None):returnimage = 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 == ''):returnif (self.label_scr_image == None):returnimage = 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 == ''):returnif (self.label_scr_image == None):returnimage = 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 == ''):returnif (self.label_scr_image == None):returnimage = 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 == ''):returnif (self.label_scr_image == None):returnimage = 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 == ''):returnif (self.label_scr_image == None):returnimage = 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 == ''):returnif (self.label_scr_image == None):returnimage = 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 == ''):returnif (self.label_scr_image == None):returnimage = 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 == ''):returnif (self.label_scr_image == None):returnimage = 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轴移动50img_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 == ''):returnif (self.label_scr_image == None):returnimage = 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轴移动50img_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 == ''):returnif (self.label_scr_image == None):returnimage = 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 == ''):returnif (self.label_scr_image == None):returnimage = 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, 缩放scaleimg_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 == ''):returnif (self.label_scr_image == None):returnimage = 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, 缩放scaleimg_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 == ''):returnif (self.label_scr_image == None):returnimage = 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, 缩放scaleimg_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 == ''):returnif (self.label_scr_image == None):returnimage = 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, 缩放scaleimg_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

相关文章:

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

-------------OpenCV教程集合------------- Python教程99:一起来初识OpenCV(一个跨平台的计算机视觉库) OpenCV教程01:图像的操作(读取显示保存属性获取和修改像素值) OpenCV教程02:图像处理…...

人工智能在招投标领域的运用---监控视频连续性检测

作者:舒城县公共交易中心 zhu_min726126.com 原创,转载请注明出处。 摘要 随着人工智能(AI)技术的飞速发展,其在各个领域的应用日益广泛。本文旨在探讨人工智能在招投标领域的运营,重点介绍AI对视频完整…...

加装德国进口高精度主轴 智能手机壳「高质量高效率」钻孔铣槽

在当前高度智能化的社会背景下,智能手机早已成为人们生活、工作的必备品,智能手机壳作市场需求量巨大。智能手机壳的加工过程涉及多个环节,包括钻孔和铣槽等。钻孔要求精度高、孔位准确,而铣槽则需要保证槽位规整、深度适宜。这些…...

Java Stream API 常用操作技巧

Java 8 引入的 Stream API 为集合操作提供了一种声明式编程模型,极大地简化了数据处理的复杂性。本文将介绍 Java Stream API 的几种常用操作方式,帮助开发者更高效地处理集合数据。 1. 过滤(Filtering) 过滤是选择集合中满足特…...

SwiftData 模型对象的多个实例在 SwiftUI 中不能及时同步的解决

概览 我们已经知道,用 CoreData 在背后默默支持的 SwiftUI 视图在使用 @FetchRequest 来查询托管对象集合时,若查询结果中的托管对象在别处被改变将不会在 FetchedResults 中得到及时的刷新。 那么这一“囧境”在 SwiftData 里是否也会“卷土重来”呢?空说无益,就让我们在…...

Android 系统网络、时间服务器配置修改

1.修改wifi 是否可用的检测地址: 由于编译的源码用的是谷歌的检测url,国内访问不了,系统会认为wifi网络受限,所以改成国内的地址 adb shell settings delete global captive_portal_https_urladb shell settings delete global captive_por…...

类和对象深入理解

目录 static成员概念静态成员变量面试题补充代码1代码2代码3如何访问private中的成员变量 静态成员函数静态成员函数没有this指针 特性 友元友元函数友元类 内部类特性1特性2 匿名对象拷贝对象时的一些编译器优化 感谢各位大佬对我的支持,如果我的文章对你有用,欢迎点击以下链接…...

在postgres数据库中的几个简单用法

1、例如表中coord_str的字段数据是121.12334 31.3435这样的字符串,如何将对应的数据转换成geometry数据,实现如下 UPDATE coordinates SET geom ST_GeomFromText(POINT( || split_part(coord_str, , 1) || || split_part(coord_str, , 2) || ), 43…...

SQLServer Manager Studio扩展开发从入门到弃坑

Visualstudio的已经开发好了,可这个就是不行,直接运行点这些按钮加载失败,而我直接不调试模式,则直接什么都没有,调试 发现是根本没触发逻辑的。 文档资料太少, 我换了几个ssms.exe都不行,18-20…...

ComfyUI预处理器ControlNet简单介绍与使用(附件工作流)

简介 ControlNet 是一个很强的插件,提供了很多种图片的控制方式,有的可以控制画面的结构,有的可以控制人物的姿势,还有的可以控制图片的画风,这对于提高AI绘画的质量特别有用。接下来就演示几种热门常用的控制方式 1…...

【篇三】在vue3上实现阿里云oss文件直传

之前写了两篇关于文件上传的文章 【篇一】使用springbootvue实现阿里云oss上传 【篇二】使用springbootvue实现阿里云oss文件直传,解决大文件分片上传问题 今天介绍一下在vue3中实现阿里云oss文件直传,主要是基于篇二中的源码进行修改,看具体…...

OceanBase v4.2 特性解析:对Json与Xml的扩展支持

1. 背景 OceanBase的Oracle模式当前已实现对XMLType类型的支持,不仅包含了基本的构造、查询、更新以及格式转换功能,还支持使用Xpath查询从XML数据中提取特定值。在V 4.2.2 版本中,我们进一步扩展了Oracle模式下对XMLType的支持,…...

《框架封装 · 统一异常处理和返回值包装》

📢 大家好,我是 【战神刘玉栋】,有10多年的研发经验,致力于前后端技术栈的知识沉淀和传播。 💗 🌻 CSDN入驻不久,希望大家多多支持,后续会继续提升文章质量,绝不滥竽充数…...

深入WebKit:揭秘复杂文档的高效渲染之道

深入WebKit:揭秘复杂文档的高效渲染之道 在当今信息爆炸的时代,网页不再仅仅是简单的文本和图片的集合,而是充满了复杂布局和丰富媒体内容的交互式平台。WebKit 作为众多流行浏览器的心脏,其布局引擎承担着将 HTML、CSS 代码转换…...

进程的控制-孤儿进程和僵尸进程

孤儿进程 : 一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被 init 进程( 进程号为 1) 所收养,并由 init 进程对它们完成状态收集工作 为了释放子进程的占用的系统资源: …...

【Unity navigation面板】

【Unity navigation面板】 Unity的Navigation面板是一个集成在Unity编辑器中的界面,它允许开发者对导航网格(NavMesh)进行配置和管理。 Unity Navigation面板的一些关键特性和功能: 导航网格代理(NavMesh Agent&…...

二刷算法训练营Day53 | 动态规划(14/17)

目录 详细布置: 1. 392. 判断子序列 2. 115. 不同的子序列 详细布置: 1. 392. 判断子序列 给定字符串 s 和 t ,判断 s 是否为 t 的子序列。 字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余…...

将缓冲文件写到磁盘中的命令sync

将缓冲文件写到磁盘中的命令sync There is no nutrition in the blog content. After reading it, you will not only suffer from malnutrition, but also impotence. The blog content is all parallel goods. Those who are worried about being cheated should leave quick…...

灵活视图变换器:为扩散模型设计的革新图像生成架构

在自然界中,图像的分辨率是无限的,而现有的图像生成模型在跨任意分辨率泛化方面存在困难。虽然扩散变换器(DiT)在特定分辨率范围内表现出色,但在处理不同分辨率的图像时却力不从心。为了克服这一限制,来自上…...

[终端安全]-1 总体介绍

有朋友一直在和笔者研讨智驾安全这个热门话题,笔者十多年工作从不离终端安全这个核心话题(芯片安全、操作系统安全、应用安全),近来也一直在梳理终端安全体系;手机、汽车皆是我们生活中应用最普遍的智能终端&#xff0…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)

2025年能源电力系统与流体力学国际会议(EPSFD 2025)将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会,EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

Linux简单的操作

ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢

随着互联网技术的飞速发展,消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁,不仅优化了客户体验,还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用,并…...

MySQL中【正则表达式】用法

MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...

vue3+vite项目中使用.env文件环境变量方法

vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

Web 架构之 CDN 加速原理与落地实践

文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 &#xf…...

技术栈RabbitMq的介绍和使用

目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...

Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)

引言 在人工智能飞速发展的今天,大语言模型(Large Language Models, LLMs)已成为技术领域的焦点。从智能写作到代码生成,LLM 的应用场景不断扩展,深刻改变了我们的工作和生活方式。然而,理解这些模型的内部…...

淘宝扭蛋机小程序系统开发:打造互动性强的购物平台

淘宝扭蛋机小程序系统的开发,旨在打造一个互动性强的购物平台,让用户在购物的同时,能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机,实现旋转、抽拉等动作,增…...

comfyui 工作流中 图生视频 如何增加视频的长度到5秒

comfyUI 工作流怎么可以生成更长的视频。除了硬件显存要求之外还有别的方法吗? 在ComfyUI中实现图生视频并延长到5秒,需要结合多个扩展和技巧。以下是完整解决方案: 核心工作流配置(24fps下5秒120帧) #mermaid-svg-yP…...