python opencv+tkinter 使用tkinter实现交互式图像处理工具

这篇具有很好参考价值的文章主要介绍了python opencv+tkinter 使用tkinter实现交互式图像处理工具。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

tkinter 基本控件与使用

我们将学习如何使用Tkinter包编写一些图形用户界面程序。Tkinter是Python的一个标准包,因此我们并不需要安装它。我们将从创建一个窗口开始,然后我们在其之上加入一些小组件,比如按钮,复选框等,并使用它们的一些属性。话不多说,让我们开始吧!
from tkinter import *

tkinter基本控件

Button按钮控件

普通的按钮是非常简单易用的。你所需要做的就是指定 Button 的内容(文本、位图或者图片),并且关联当按钮被按下时应该调用的函数或方法:

def callback():
	print("你点击了按钮")

window=Tk()#创建一个窗口
buttion1=Button(window, text='press', command=callback)#如果command还没有实现好功能,可以先填入'disabled'
buttion1.pack()#打包组件

window.mainloop()#维持窗口直至手动关闭

python opencv+tkinter 使用tkinter实现交互式图像处理工具
你得到了一个小家伙,但后面我们会遇到棘手的大家伙的!

实现了简单的按钮之后,你可能会不满足于此。的确,每个人都希望他的window可以大小适中,按钮也符合规律的排布。下面的代码实现了你渴望的功能——

def callback():
    print("点赞,关注,投币,评论,转发")
win = Tk()
win.title('一个大小合适的窗口')
win.geometry('800x600')  # size
win['bg'] = 'pink'  # background color
win.attributes('-alpha', 0.9)  # 虚化
button = Button(win,text='这是一个按钮',
                padx=100,pady=100,command=callback)
#,height=2,width=50,command=callback)
button.grid(row=1, column=11)
win.mainloop()

canvas

canvas画布为tkinter的图像绘制提供了基础。canvas是一个高度灵活的组件,可以用来绘制图形和图表,创建图形编辑器,实现各种自定义小部件。
我们话不多说,演示如下代码查看结果:

win=Tk()
win.geometry('800x600')
w=Canvas(win,width=100,height=300)
w.pack()
w.create_line(0, 50, 200, 50, fill = "yellow")
#画一条红色的竖线(虚线)
w.create_line(100, 0, 100, 100, fill = "red", dash = (4, 4))
#中间画一个蓝色的矩形
w.create_rectangle(50, 25, 150, 75, fill = "blue")
win.mainloop()

Label

相信聪明的小伙伴应该知道下面的代码怎么用啦

Label(标签)组件用于在屏幕上显示文本或图像。Label 组件仅能显示单一字体的文本,但文本可以跨越多行。另外,还可以为其中的个别字符加上下划线(例如用于表示键盘快捷键)。

一个基础示例

w=Label(win,text='这只是这个label的文本').pack()

一个换行实例

longtext = """
Label 可以显示多行文本,你可以直接使用换行符
或使用 wraplength 选项来实现。当文本换行的时
候,你可以使用 anchor 和 justify 选项来使得
文本如你所希望的显示出来。
"""
w = Label(master, text=longtext, anchor="w", justify="left")

一个展示图片实例
下面这个程序需要你输入图片地址(不可以是jpg)

win=Tk()
#from PIL import ImageTk
#img=Image.open('pics/1.jpg')
#photo=ImageTk.PhotoImage(img)
#a=Label(win,image=photo).pack()
photo = PhotoImage(file="python.gif")
w = Label(win, image=photo)
w.pack()
win.mainloop()

看了上面的代码,聪明的同学已经知道怎么使得输入变成jpg了
emm可能你比较懒,ok我们这里还有一份可以运行的不用修改的最最最关键的是对jpg文件有效的
聪明的小伙伴已经在修改窗口大小以验证下面某行代码的必要性啦

win=Tk()
img=Image.open('pics/1.jpg')
size=img.size
win.geometry('{}x{}'.format(size[0]+100,size[1]+100))#没错就是我,我就是这行
photo=ImageTk.PhotoImage(img)
a=Label(win,image=photo).pack()
win.mainloop()

好啦,你已经学了这么多知识了,是时候再再再补充一点知识啦——

补充知识

这一部分我会慢慢完善的

布局管理器grid

grid 管理器可以说是 Tkinter 这三个布局管理器中最灵活多变的。如果你只希望学习使用一个布局管理器,那么 grid 绝对是首选。当你在设计对话框的时候,使用 gird 尤其便捷。如果你此前一直在用 pack 构造窗口布局,那么学习完 grid 你会悔恨当初为啥不早学它。使用一个 grid 就可以简单的实现你用很多个框架和 pack 搭建起来的效果。

细心的读者可能已经发现了,在button控件中,我们使用了两种不同的布局方式:pack, grid

使用 grid 排列组件,只需告诉它你想要将组件放置的位置(行/列,row 选项指定行,cloumn 选项指定列)。此外,你并不用提前指出网格(grid 分布给组件的位置称为网格)的尺寸,因为管理器会自动计算。

root = Tk()
 
# column 默认值是 0
tk.Label(root, text="用户名").grid(row=0)
tk.Label(root, text="密码").grid(row=1)
#tk.Label(root, text="用户名").grid(row=0, sticky="w") #细心的读者可以用下面的代码块代替上面两行
#tk.Label(root, text="密码").grid(row=1, sticky="w")
tk.Entry(root).grid(row=0, column=1)
tk.Entry(root, show="*").grid(row=1, column=1)
#photo = tk.PhotoImage(file="logo.gif")
#tk.Label(root, image=photo).grid(row=0, column=2, rowspan=2, padx=5, pady=5) #rowspan=2 跨两行
tk.Button(text="提交", width=10).grid(row=2, columnspan=3, pady=5) #columnspan=3 跨三列
root.mainloop()

使用tkinter+opencv 制作交互式程序

小试牛刀

ok,现在你真的学了很多知识了,让我们开始第一部:
制作一个界面,使得用户可以打开指定图片并展示

阿这,你们肯定想,这么简单的东西还用我教么!
好的,那我们直接下一个部分——

不过~
写代码切忌眼高手低啊!

win=Tk()
win.geometry('100x80')
global message
message=0
def getpathandshow():
    global message
    global a
    message=input('please input a pic path')
    print(message)
    if len(message)>0:
#         assert os.path.exists(message), '路径不存在'
        img=Image.open(message)
        size=img.size
        win.geometry('{}x{}'.format(size[0]+100,size[1]+100))
        photo=ImageTk.PhotoImage(img)
        if a==None:
            a=Label(win,image=photo)
            a.image=photo
            a.pack()
        else:
            a.configure(image=photo)
            a.image=photo
a=None
b=Button(win,text='点击输入图片路径',command=getpathandshow).pack()
win.mainloop()

为了更好的选择图片,我们使用了filedialog包
获取path修改为:
path=filedialog.askopenfilename()
ok,相信你应该明白该把这句话修改在何处,聪明的读者。

下面我们更加仔细,更加美观地实现了上面所述功能

from tkinter import *
import time
import os
from PIL import Image, ImageTk
import cv2 as cv
from tkinter import filedialog


def button2():
    global lab1
    path = entry1.get()
    print(path)
    if len(path) > 0:
        img = Image.open(path)
        size = img.size
        if size[0] > 800 or size[1] > 600:
            rate = max(size[0] / 800, size[1] / 600)
            rsize = (int(size[0] / rate), int(size[1] / rate))
            img = img.resize(rsize)
        # win.geometry('{}x{}'.format(size[0] + 100, size[1] + 100))
        photo = ImageTk.PhotoImage(img)
        if lab1 == None:
            lab1 = Label(win, image=photo)
            lab1.image = photo
            lab1.grid(row=3, columnspan=5)
        else:
            lab1.configure(image=photo)
            lab1.image = photo


def button1():
    global lab1
    # message='pics/1.jpg'#input('please input a pic path')
    path = filedialog.askopenfilename()
    print(path)
    if len(path) > 0:
        img = Image.open(path)
        size = img.size
        if size[0] > 800 or size[1] > 600:
            rate = max(size[0] / 800, size[1] / 600)
            rsize = (int(size[0] / rate), int(size[1] / rate))
            img = img.resize(rsize)
        # win.geometry('{}x{}'.format(size[0] + 100, size[1] + 100))
        photo = ImageTk.PhotoImage(img)
        if lab1 == None:
            lab1 = Label(win, image=photo)
            lab1.image = photo
            lab1.grid(row=3, columnspan=5)
        else:
            lab1.configure(image=photo)
            lab1.image = photo


win = Tk()
win.geometry('800x650')
global lab1
lab1 = None

entry1 = Entry(win, width=20)
entry1.grid(row=0, column=1)
lab2 = Label(win, text='输入图片路径', width=20).grid(row=0, column=0)
lab2 = Label(win, text='手动选择路劲', width=20).grid(row=0, column=3)
b1 = Button(win, text='选择路径', command=button1, width=20).grid(row=0, column=4)
b2 = Button(win, text='确认路径', command=button2, width=20).grid(row=0, column=2)

win.mainloop()

利用滑块旋转图片,提供保存按钮

ok,相信你已经学到了很多,并且跃跃欲试——
现在!开始尝试并实现一下功能:

#打开,保存,退出,转灰度
#几何变换:镜像,平移,剪切,旋转,缩放

下面的这段代码实现了打开指定路径下的图片,并实现旋转操作
(其实是我写好了怕以后出bug无处参考哈哈)

#测试旋转框函数的可行性

#     l1.configure(image=img1)
a=tk.Tk()
global path
img=Image.open(path)
img=ImageTk.PhotoImage(img)
#这次我们换一个思路,先加最关键的控件

#最终画布
l1=tk.Label(a,image=img)
l1.grid(row=3,columnspan=2)

#角度
agl=tk.IntVar()
agl.set(0)

#定义setangle函数,为滑块提供反馈
def setangle(value):
    agl.set(value)
    
#滑块
scale24=tk.Scale(a,from_=0,to=360,orient=tk.HORIZONTAL,showvalue=0,tickinterval=45,
                resolution=1,command=setangle)
scale24.grid(row=2,columnspan=2,stick=tk.EW)

#按钮函数组件1:旋转图像函数
def rotimg():
    #angle.path
    img=cv.imread(path)
    angle=agl.get()
    (h,w)=img.shape[:2]
    center=(w//2,h//2)
    M=cv.getRotationMatrix2D(center,angle,1.0)
    rotedimg=cv.warpAffine(img,M,(w,h))
    rgb_img=cv.cvtColor(rotedimg,cv.COLOR_BGR2RGB)
    img=Image.fromarray(rgb_img)
    return img

#利用组件函数,构建按钮函数
def button24():
    img=rotimg()
    #img.show()
    img=ImageTk.PhotoImage(img)
    l1.configure(image=img)
    a.mainloop()

#按钮控件
b1=tk.Button(a,width=20,command=button24,text='显示旋转图')
b1.grid(row=1,column=1,stick=tk.EW)

#角度显示盘
la=tk.Label(a,textvariable=str(agl),bg='pink')
la.grid(row=1,column=0,stick=tk.EW)

#好的,既然我们实现了困难的部分,下面开始实现简单的部分,保存路径输入框entry
entry01=tk.Entry(a)
entry01.grid(row=0,column=0,stick=tk.EW)

#下面的部分是保存图片的按钮,会利用到之前的rotimg函数,和之前一样,先写按钮函数
def button02():
    path=entry01.get()
    if len(path) == 0:
        print('保存失败')
        return 0
    img=rotimg()
    img.save(path)
    #保存成功我们希望有个弹窗
    winmessage=tk.Toplevel(a)
    winmessage.geometry('300x200')
    tk.Message(winmessage,text='恭喜你,或者说恭喜这个熬了很久的猿,你们保存成功了').grid(sticky=tk.NSEW)
    
    
#这里就是保存图片按钮了
b02=tk.Button(a,text='左侧输入,点此保存',command=button02)
b02.grid(row=0,column=1,stick=tk.EW)


a.mainloop()

一个实现好的作品

我懒了,懒得写了,下面是我的一个完成品,界面简洁,功能也实现了不少。文章来源地址https://www.toymoban.com/news/detail-498158.html

import tkinter as tk
import os
from PIL import Image, ImageTk
import cv2 as cv
from tkinter import filedialog
import numpy as np
from functools import partial
from tools import *
# 下面的是为了直方图均衡化

from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import NavigationToolbar2Tk, FigureCanvasTkAgg


# 打开,保存,退出,转灰度
# 几何变换:镜像,平移,剪切,旋转,缩放
# 空间滤波:平滑处理,锐化处理

# 直方图,计算,显示,均衡化
# 频域变换:Fourier变换,离散余弦变换,反变换(显示频谱图)
# 频域滤波:低通滤波,高通滤波

# 以颜色直方图为特征,搜索本地图片,反馈相似图片并排序

def buttonSaveImg(img, entry):
    path = entry.get()
    # try:
    img.save(path)
    win22 = tk.Toplevel()
    win22.rowconfigure(0, weight=1)
    win22.columnconfigure(0, weight=1)
    win22.geometry('200x200')
    tk.Message(win22, text='保存成功').grid()
    # except:
    #     win22 = tk.Toplevel()
    #     win22.geometry('200x200')
    #     tk.Message(win22, text='图片路径无效').grid()
    #     win22.mainloop()


def gsnoise():
    global path
    if len(path) > 0:
        img = getimg(path)[1]
        size = img.shape
        noise = np.array(np.random.randint(20, size=size[0:-1]) - 10, dtype=np.uint8)
        noise = noise.reshape(size[0], size[1], 1)
        img = img + noise
        img = Image.fromarray(img)
        wings = tk.Toplevel()
        photo = ImageTk.PhotoImage(img)
        tk.Label(wings, image=photo).grid()
        wings.mainloop()


def button1():
    global lab1, path
    path = filedialog.askopenfilename()
    if len(path) > 0:
        img = getimg(path)[0]
        photo = ImageTk.PhotoImage(img)
        if lab1 == None:
            lab1 = tk.Label(win, image=photo)
            lab1.image = photo
            # lab1.rowconfigure()
            lab1.grid(row=3, columnspan=5,sticky=tk.NSEW)
        else:
            lab1.configure(image=photo)
            lab1.image = photo


def button2():
    global lab1, path
    path = entry1.get()
    print(path)
    if len(path) > 0:
        img = getimg(path)[0]
        photo = ImageTk.PhotoImage(img)
        if lab1 == None:
            lab1 = tk.Label(win, image=photo)
            lab1.image = photo
            lab1.grid(row=3, columnspan=5,sticky=tk.NSEW)
        else:
            lab1.configure(image=photo)
            lab1.image = photo


def button21():  # 参考faster rcnn RandomHorizontalFlip
    global path
    if len(path) == 0:
        return 0
    img = getimg(path)[1]  # Image.fromarray
    img = np.flip(img, axis=1)
    img = Image.fromarray(img)

    win21 = tk.Toplevel()  # 此处不能写Tk()因为根部窗口只能有一个

    win21.rowconfigure((1), weight=1)
    win21.columnconfigure((0, 1,2), weight=1)
    tk.Label(win21, text='输入图片保存路径', width=20).grid(row=0, column=0,sticky=tk.EW)
    entry21 = tk.Entry(win21)
    entry21.grid(row=0, column=1,sticky=tk.EW)
    tk.Button(win21, width=20, text='保存', command=partial(buttonSaveImg, img, entry21)).grid(row=0, column=2,sticky=tk.EW)
    photo21 = ImageTk.PhotoImage(img)
    tk.Label(win21, image=photo21).grid(row=1, columnspan=3,sticky=tk.NSEW)

    win21.mainloop()


def button22():
    if len(path) > 0:
        win22 = tk.Toplevel()
        win22.rowconfigure(0, weight=1)
        win22.columnconfigure(0, weight=1)
        win22.geometry('200x200')
        tk.Message(win22, text='想象一下,已经平移了,只不过我们以它的中心为参照点').grid()
        win22.mainloop()


def button23():
    # 剪切这个功能因为需要获取图片的坐标,实现鼠标拖动剪切,实际上很不好做”
    pass

    # l1.update()

    # w.update()


def button24():  # 旋转——做出拖动条
    global path
    if len(path)==0:
        return 0
    # 测试旋转框函数的可行性

    #     l1.configure(image=img1)
    a = tk.Toplevel(win)
    a.rowconfigure(3, weight=1)
    a.columnconfigure((0, 1), weight=1)
    img = Image.open(path)
    img = ImageTk.PhotoImage(img)
    # 这次我们换一个思路,先加最关键的控件

    # 最终画布
    l1 = tk.Label(a, image=img)
    l1.grid(row=3, columnspan=2,sticky=tk.NSEW)

    # 角度
    agl = tk.IntVar()
    agl.set(0)

    # 定义setangle函数,为滑块提供反馈
    def setangle(value):
        agl.set(value)

    # 滑块
    scale24 = tk.Scale(a, from_=0, to=360, orient=tk.HORIZONTAL, showvalue=0, tickinterval=45,
                       resolution=1, command=setangle)
    scale24.grid(row=2, columnspan=2, sticky=tk.EW)

    # 按钮函数组件1:旋转图像函数
    def rotimg():
        # angle.path
        img = cv.imread(path)
        angle = agl.get()
        (h, w) = img.shape[:2]
        center = (w // 2, h // 2)
        M = cv.getRotationMatrix2D(center, angle, 1.0)
        rotedimg = cv.warpAffine(img, M, (w, h))
        rgb_img = cv.cvtColor(rotedimg, cv.COLOR_BGR2RGB)
        img = Image.fromarray(rgb_img)
        return img

    # 利用组件函数,构建按钮函数
    def button24():
        img = rotimg()
        # img.show()
        img = ImageTk.PhotoImage(img)
        l1.configure(image=img)
        a.mainloop()

    # 按钮控件
    b1 = tk.Button(a, width=20, command=button24, text='显示旋转图')
    b1.grid(row=1, column=1, sticky=tk.EW)

    # 角度显示盘
    la = tk.Label(a, textvariable=str(agl), bg='pink')
    la.grid(row=1, column=0, sticky=tk.EW)

    # 好的,既然我们实现了困难的部分,下面开始实现简单的部分,保存路径输入框entry
    entry01 = tk.Entry(a)
    entry01.grid(row=0, column=0, sticky=tk.EW)

    # 下面的部分是保存图片的按钮,会利用到之前的rotimg函数,和之前一样,先写按钮函数
    def button02():
        path = entry01.get()
        if len(path) == 0:
            print('保存失败')
            return 0
        img = rotimg()
        img.save(path)
        # 保存成功我们希望有个弹窗
        winmessage = tk.Toplevel(a)
        winmessage.rowconfigure(0, weight=1)
        winmessage.columnconfigure(0, weight=1)
        winmessage.geometry('300x200')
        tk.Message(winmessage, text='恭喜你,或者说恭喜这个熬了很久的猿,你们保存成功了').grid(sticky=tk.NSEW)

    # 这里就是保存图片按钮了
    b02 = tk.Button(a, text='左侧输入,点此保存', command=button02, bg='pink')
    b02.grid(row=0, column=1, sticky=tk.EW)

    a.mainloop()


def button25():    # 缩放,我们希望设置两个方法——输入缩放比或者做成可视化的那种拖动条
    global path
    if len(path)==0:
        return 0
    # 缩放功能
    a = tk.Toplevel()
    a.rowconfigure(3, weight=1)
    a.columnconfigure((0, 1), weight=1)
    img = Image.open(path)
    img = ImageTk.PhotoImage(img)

    # 显而易见,当我们已经可以实现旋转功能时,缩放就不在话下了
    # 第一步:定义图片展示窗口(毕竟咱是按照逻辑顺序)

    # 最终画布
    l31 = tk.Label(a, image=img)
    l31.grid(row=3, columnspan=2,sticky=tk.NSEW)

    # 比例
    rate = tk.DoubleVar()
    rate.set(1.0)

    # 定义setangle函数,为滑块提供反馈
    def setangle(value):
        rate.set(value)

    # 滑块
    scale24 = tk.Scale(a, from_=1, to=5, orient=tk.HORIZONTAL, showvalue=1, tickinterval=1,
                       resolution=0.1, command=setangle)
    scale24.grid(row=2, columnspan=2, sticky=tk.EW)

    # 定义组件函数,实现缩放功能
    def shrink():
        # 收缩比例,路径
        r = rate.get()
        img = Image.open(path)
        size = img.size
        #     print(size)
        img2 = img.resize((int(size[0] / r), int(size[1] / r)))
        return img2

    def button22():
        img = shrink()
        #     img.show()
        img = ImageTk.PhotoImage(img)
        l31.configure(image=img)
        a.mainloop()

    # 按钮控件
    b22 = tk.Button(a, width=20, command=button22, text='显示缩放图')
    b22.grid(row=1, column=1, sticky=tk.EW)

    # 角度显示盘
    l21 = tk.Label(a, textvariable=str(rate), bg='pink')
    l21.grid(row=1, column=0, sticky=tk.EW)

    # 好的,既然我们实现了困难的部分,下面开始实现简单的部分,保存路径输入框entry
    entry01 = tk.Entry(a)
    entry01.grid(row=0, column=0, sticky=tk.EW)

    # 下面的部分是保存图片的按钮,会利用到之前的rotimg函数,和之前一样,先写按钮函数
    def button02():
        path = entry01.get()
        if len(path) == 0:
            print('保存失败')
            return 0
        img = shrink()
        img.save(path)
        # 保存成功我们希望有个弹窗
        winmessage = tk.Toplevel(a)
        winmessage.rowconfigure(0, weight=1)
        winmessage.columnconfigure(0, weight=1)
        winmessage.geometry('300x200')
        tk.Message(winmessage, text='恭喜你,或者说恭喜这个熬了很久的猿,你们保存成功了').grid(sticky=tk.NSEW)

    # 这里就是保存图片按钮了
    b02 = tk.Button(a, text='左侧输入,点此保存', command=button02, bg='pink')
    b02.grid(row=0, column=1, sticky=tk.EW)

    a.mainloop()

    # 至此,缩放功能实现完毕button25


def button31():  # 平滑(模糊)
    # 平滑功能
    global path
    if len(path) is 0:
        return 0
    a = tk.Toplevel()
    a.rowconfigure(3, weight=1)
    a.columnconfigure((0, 1), weight=1)

    img = Image.open(path)
    img = ImageTk.PhotoImage(img)

    # 显而易见,当我们已经可以实现旋转功能时,缩放就不在话下了
    # 第一步:定义图片展示窗口(毕竟咱是按照逻辑顺序)
    kernels = [np.ones((i, i), np.float32) / (i * i) for i in range(1, 11)]
    # 最终画布
    l31 = tk.Label(a, image=img)
    l31.grid(row=3, columnspan=2,sticky=tk.NSEW)

    # 卷积核的大小比例
    rate = tk.IntVar()
    rate.set(1)

    # 定义setangle函数,为滑块提供反馈
    def setkernel(value):
        rate.set(value)

    # 滑块
    scale31 = tk.Scale(a, from_=1, to=11, orient=tk.HORIZONTAL, showvalue=1, tickinterval=2,
                       command=setkernel)
    scale31.grid(row=2, columnspan=2, sticky=tk.EW)

    # 定义组件函数,实现缩放功能
    def averaging():
        # 核大小,图片
        r = (rate.get() - 1) // 2
        img = cv.imread(path)
        kernel = kernels[r]
        avgimg = cv.filter2D(img, -1, kernel)
        rgb_img = cv.cvtColor(avgimg, cv.COLOR_BGR2RGB)
        img = Image.fromarray(rgb_img)
        return img

    def button22():
        img = averaging()
        img = ImageTk.PhotoImage(img)
        l31.configure(image=img)
        a.mainloop()

    # 按钮控件
    b22 = tk.Button(a, width=20, command=button22, text='显示缩放图')
    b22.grid(row=1, column=1, sticky=tk.EW)

    # 显示盘
    l21 = tk.Label(a, textvariable=str(rate), bg='pink')
    l21.grid(row=1, column=0, sticky=tk.EW)

    # 好的,既然我们实现了困难的部分,下面开始实现简单的部分,保存路径输入框entry
    entry01 = tk.Entry(a)
    entry01.grid(row=0, column=0, sticky=tk.EW)

    # 下面的部分是保存图片的按钮,会利用到之前的rotimg函数,和之前一样,先写按钮函数
    def button02():
        path = entry01.get()
        if len(path) == 0:
            print('保存失败')
            return 0
        img = averaging()
        img.save(path)
        # 保存成功我们希望有个弹窗
        winmessage = tk.Toplevel(a)
        winmessage.rowconfigure(0, weight=1)
        winmessage.columnconfigure(0, weight=1)
        winmessage.geometry('300x200')
        tk.Message(winmessage, text='恭喜你,或者说恭喜这个熬了很久的猿,你们保存成功了').grid(sticky=tk.NSEW)

    # 这里就是保存图片按钮了
    b02 = tk.Button(a, text='左侧输入,点此保存', command=button02)
    b02.grid(row=0, column=1, sticky=tk.EW)

    a.mainloop()

    # 至此,平滑功能实现完毕


def button32():  # 锐化
    # 锐化功能
    global path
    if len(path) is 0:
        return 0
    a = tk.Toplevel()
    a.rowconfigure(3,weight=1)
    a.columnconfigure((0, 1), weight=1)
    # global path
    img = Image.open(path)
    img = ImageTk.PhotoImage(img)

    # 显而易见,当我们已经可以实现旋转功能时,缩放就不在话下了
    # 第一步:定义高通滤波核
    kernel0 = -np.ones((3, 3), np.float32)
    kernel0[1, 1] += 9
    kernel1 = -np.ones((5, 5), np.float32)
    kernel1[1:4, 1:4] = -kernel0
    kernel1[2, 2] = 8
    kernel2 = -np.ones((5, 5), np.float32)
    kernel2[2, 2] += 25
    kernels = [kernel0, kernel1, kernel2]

    # 最终画布
    l31 = tk.Label(a, image=img)
    l31.grid(row=3, columnspan=2,sticky=tk.NSEW)

    # 卷积核的大小比例
    rate = tk.IntVar()
    rate.set(1)

    # 定义setangle函数,为滑块提供反馈
    def setkernel(value):
        rate.set(value)

    # 滑块
    scale31 = tk.Scale(a, from_=1, to=3, orient=tk.HORIZONTAL, showvalue=1, tickinterval=1,
                       resolution=1, command=setkernel)
    scale31.grid(row=2, columnspan=2, sticky=tk.EW)

    # 定义组件函数,实现缩放功能
    def averaging():
        # 核大小,图片
        r = rate.get() - 1
        img = cv.imread(path)
        kernel = kernels[r]
        avgimg = cv.filter2D(img, -1, kernel)
        rgb_img = cv.cvtColor(avgimg, cv.COLOR_BGR2RGB)
        img = Image.fromarray(rgb_img)
        return img

    def button22():
        img = averaging()
        img = ImageTk.PhotoImage(img)
        l31.configure(image=img)
        a.mainloop()

    # 按钮控件
    b22 = tk.Button(a, width=20, command=button22, text='显示缩放图')
    b22.grid(row=1, column=1, sticky=tk.EW)

    # 显示盘
    l21 = tk.Label(a, textvariable=str(rate), bg='pink')
    l21.grid(row=1, column=0, sticky=tk.EW)

    # 好的,既然我们实现了困难的部分,下面开始实现简单的部分,保存路径输入框entry
    entry01 = tk.Entry(a)
    entry01.grid(row=0, column=0, sticky=tk.EW)

    # 下面的部分是保存图片的按钮
    def button02():
        path = entry01.get()
        if len(path) == 0:
            print('保存失败')
            return 0
        img = averaging()
        img.save(path)
        # 保存成功我们希望有个弹窗
        winmessage = tk.Toplevel(a)
        winmessage.rowconfigure(0, weight=1)
        winmessage.columnconfigure(0, weight=1)
        winmessage.geometry('300x200')
        tk.Message(winmessage, text='恭喜你,或者说恭喜这个熬了很久的猿,你们保存成功了').grid(sticky=tk.NSEW)

    # 这里就是保存图片按钮了
    b02 = tk.Button(a, text='左侧输入,点此保存', command=button02)
    b02.grid(row=0, column=1, sticky=tk.EW)

    a.mainloop()

    # 至此,锐化功能实现完毕


def button23():  # 直方图均衡化
    global path
    if len(path) is 0:
        return 0
    # 利用cv内置工具获得直方图,已经均衡化后的图像
    img_ori=cv.imread(path)
    for i in range(3):
        im=img_ori[:,:,i]
        equ=cv.equalizeHist(im)
        try:
            im_box.append(equ)
        except:
            im_box=[equ]
    im_box=np.stack((im_box[2],im_box[1],im_box[0]),axis=2)
    #获得直方图三尺度均衡化后的图片
    rgb_im=Image.fromarray(im_box)
    #rgb_im.show()
    img = cv.imread(path, 0)
    hist = cv.calcHist([img], [0], None, [256], [0, 256])
    equ = cv.equalizeHist(img)
    histequ = cv.calcHist([equ], [0], None, [256], [0, 256])

    # 第二步,把这些图像放到一个figure上
    f = Figure(figsize=(10, 8), dpi=100)
    a11 = f.add_subplot(221)  # 添加子图:1行1列第1个
    # a11.title='原图像素值直方图'
    x = np.arange(256)
    y = hist
    a11.plot(x, y)

    a12 = f.add_subplot(222)
    # a12.title='原图灰度图'
    rgb_img = cv.cvtColor(img, cv.COLOR_BGR2RGB)
    a12.imshow(rgb_img)

    a21 = f.add_subplot(223)
    # a21.title('均衡化后的直方图')
    y = histequ
    a21.plot(x, y)

    a22 = f.add_subplot(224)
    # a22.title('均衡化后的图像')
    rgb_equ = cv.cvtColor(equ, cv.COLOR_BGR2RGB)
    a22.imshow(rgb_equ)

    # 第三步,建立和tkinter的联系,提供保存方法
    #显示均衡化的彩图
    def button10():
        img=rgb_im
        aa=tk.Toplevel()
        img=ImageTk.PhotoImage(img)
        aal=tk.Label(aa,image=img)
        aal.grid()
        aa.mainloop()

    #保存均衡化彩图
    def button11():
        path = entry00.get()
        rgb_im.save(path)
        winmessage = tk.Toplevel(a)
        winmessage.geometry('300x200')
        tk.Message(winmessage, text='恭喜你,或者说恭喜这个熬了很久的猿,你们保存成功了').grid(sticky=tk.NSEW)

    a = tk.Toplevel()
    a.rowconfigure((2),weight=1)
    a.columnconfigure((0,1),weight=1)
    img_real=ImageTk.PhotoImage(rgb_im)
    b = tk.Frame(a)
    canvas1 = FigureCanvasTkAgg(f, b)
    canvas1.draw()
    canvas1.get_tk_widget().grid()
    b.grid(row=2, columnspan=2, sticky=tk.NSEW)
    b10=tk.Button(a,text='展示均衡化彩图',command=button10).grid(row=1,column=0,sticky=tk.EW)
    b11=tk.Button(a,text='保存均衡化彩图',command=button11).grid(row=1,column=1,sticky=tk.EW)
    # 提供保存方法
    def button01():
        path = entry00.get()
        cv.imwrite(path, equ)
        winmessage = tk.Toplevel(a)
        winmessage.rowconfigure(0, weight=1)
        winmessage.columnconfigure(0, weight=1)
        winmessage.geometry('300x200')
        tk.Message(winmessage, text='恭喜你,或者说恭喜这个熬了很久的猿,你们保存成功了').grid(sticky=tk.NSEW)

    entry00 = tk.Entry(a)
    entry00.grid(row=0, column=0, sticky=tk.EW)
    b01 = tk.Button(a, text='点此保存均衡化的图片', command=button01)
    b01.grid(row=0, column=1,sticky=tk.EW)
    a.mainloop()

def button33():#低通滤波
    '''低通滤波,基本组件:

        文字框,保存图片按钮

        滑块数值展示,展示图片

        滑块

        图片'''
    # 判断函数
    if len(path) is 0:
        return 0
    if path.endswith('.jpg') is not True:
        return 0
    # 读取图片
    a = tk.Toplevel()
    img = Image.open(path)
    img = ImageTk.PhotoImage(img)

    # 可以调节界面
    a.rowconfigure(3, weight=1)
    for j in range(2):
        a.columnconfigure(j, weight=1)
    # 画布
    l30 = tk.Label(a, image=img)
    l30.grid(row=3, columnspan=2, sticky=tk.NSEW)

    # 定义一个变量
    kernelwidth = tk.IntVar()
    kernelwidth.set(1)

    # 定义滑块函数
    def setwidth(value):
        kernelwidth.set(value)

    # 定义滑块
    scale20 = tk.Scale(a, from_=1, to=5, orient=tk.HORIZONTAL, showvalue=1,
                       resolution=1, tickinterval=1, command=setwidth)
    scale20.grid(row=2, columnspan=2, sticky=tk.EW)

    # 滑块数值显示器
    l10 = tk.Label(a, textvariable='滤波核宽度为' + str(kernelwidth.get() * 20), bg='pink')
    l10.grid(row=1, column=0, sticky=tk.EW)

    # 按钮函数组件1:低通滤波器
    def low_filter():
        width = kernelwidth.get() * 10
        img = cv.imread(path)
        rows, cols = img.shape[:2]
        mask = np.zeros((rows,cols), np.uint8)
        mask[(rows // 2 - width):(rows // 2 + width)][:, (cols // 2 - width):(cols // 2 + width)] = 1
        img_l = [1, 2, 3]
        for i in range(3):
            f1 = np.fft.fft2(img[:, :, i])
            f1shift = np.fft.fftshift(f1) * mask
            f2shift = np.fft.ifftshift(f1shift)
            img_new = np.fft.ifft2(f2shift)
            img_new = np.abs(img_new)
            img_new = (img_new - np.amin(img_new)) / (np.amax(img_new) - np.amin(img_new))
            img_new *= 255
            img_l[i] = np.array(img_new, np.uint8)
        img = np.stack((img_l[0], img_l[1], img_l[2]), axis=2)
        img = cv.cvtColor(img, cv.COLOR_BGR2RGB)
        img = Image.fromarray(img)
        return img

    def button11():
        img = low_filter()
        img = ImageTk.PhotoImage(img)
        l30.configure(image=img)
        a.mainloop()

    b11 = tk.Button(a, text='点此展示滤波效果', command=button11)
    b11.grid(row=1, column=1, sticky=tk.EW)

    # 保存
    entry01 = tk.Entry(a)
    entry01.grid(row=0, column=0, sticky=tk.EW)

    # 下面的部分是保存图片的按钮,会利用到之前的rotimg函数,和之前一样,先写按钮函数
    def button02():
        path = entry01.get()
        if len(path) == 0:
            print('保存失败')
            return 0
        img = low_filter()
        img.save(path)
        # 保存成功我们希望有个弹窗
        winmessage = tk.Toplevel(a)
        winmessage.rowconfigure(0, weight=1)
        winmessage.columnconfigure(0, weight=1)
        winmessage.geometry('300x200')
        tk.Message(winmessage, text='恭喜你,或者说恭喜这个熬了很久的猿,你们保存成功了').grid(sticky=tk.NSEW)

    # 这里就是保存图片按钮了
    b02 = tk.Button(a, text='左侧输入,点此保存', command=button02)
    b02.grid(row=0, column=1, sticky=tk.EW)

    a.mainloop()
def button35():#低通滤波
    # 判断函数
    if len(path) is 0:
        return 0
    if path.endswith('.jpg') is not True:
        return 0
    # 读取图片
    a = tk.Toplevel()
    img = Image.open(path)
    img = ImageTk.PhotoImage(img)

    # 可以调节界面

    a.rowconfigure(3, weight=1)
    for j in range(2):
        a.columnconfigure(j, weight=1)
    # 画布
    l30 = tk.Label(a, image=img)
    l30.grid(row=3, columnspan=2, sticky=tk.NSEW)

    # 定义一个变量
    kernelwidth = tk.IntVar()
    kernelwidth.set(1)

    # 定义滑块函数
    def setwidth(value):
        kernelwidth.set(value)

    # 定义滑块
    scale20 = tk.Scale(a, from_=1, to=5, orient=tk.HORIZONTAL, showvalue=1,
                       resolution=1, tickinterval=1, command=setwidth)
    scale20.grid(row=2, columnspan=2, sticky=tk.EW)

    # 滑块数值显示器
    l10 = tk.Label(a, textvariable='滤波核宽度为' + str(kernelwidth.get() * 20), bg='pink')
    l10.grid(row=1, column=0, sticky=tk.EW)

    # 按钮函数组件1:低通滤波器
    def low_filter():
        width = kernelwidth.get() * 10
        img = cv.imread(path)
        rows, cols = img.shape[:2]
        mask = np.ones((rows,cols), np.uint8)
        mask[(rows // 2 - width):(rows // 2 + width)][:, (cols // 2 - width):(cols // 2 + width)] = 0
        img_l = [1, 2, 3]
        for i in range(3):
            f1 = np.fft.fft2(img[:, :, i])
            f1shift = np.fft.fftshift(f1) * mask
            f2shift = np.fft.ifftshift(f1shift)
            img_new = np.fft.ifft2(f2shift)
            img_new = np.abs(img_new)
            img_new = (img_new - np.amin(img_new)) / (np.amax(img_new) - np.amin(img_new))
            img_new *= 255
            img_l[i] = np.array(img_new, np.uint8)
        img = np.stack((img_l[0], img_l[1], img_l[2]), axis=2)
        img = cv.cvtColor(img, cv.COLOR_BGR2RGB)
        img = Image.fromarray(img)
        return img

    def button11():
        img = low_filter()
        img = ImageTk.PhotoImage(img)
        l30.configure(image=img)
        a.mainloop()

    b11 = tk.Button(a, text='点此展示滤波效果', command=button11)
    b11.grid(row=1, column=1, sticky=tk.EW)

    # 保存
    entry01 = tk.Entry(a)
    entry01.grid(row=0, column=0, sticky=tk.EW)

    # 下面的部分是保存图片的按钮,会利用到之前的rotimg函数,和之前一样,先写按钮函数
    def button02():
        path = entry01.get()
        if len(path) == 0:
            print('保存失败')
            return 0
        img = low_filter()
        img.save(path)
        # 保存成功我们希望有个弹窗
        winmessage = tk.Toplevel(a)
        winmessage.rowconfigure(0, weight=1)
        winmessage.columnconfigure(0, weight=1)
        winmessage.geometry('300x200')
        tk.Message(winmessage, text='恭喜你,或者说恭喜这个熬了很久的猿,你们保存成功了').grid(sticky=tk.NSEW)

    # 这里就是保存图片按钮了
    b02 = tk.Button(a, text='左侧输入,点此保存', command=button02)
    b02.grid(row=0, column=1, sticky=tk.EW)

    a.mainloop()

win = tk.Tk()
win.rowconfigure((3),weight=1)
win.columnconfigure((0,1,2,3,4),weight=1)
path = ''
lab1 = tk.Label(win,width=30,height=30).grid(row=3,column=0,sticky=tk.NSEW,columnspan=5)

entry1 = tk.Entry(win, width=20)
entry1.grid(row=0, column=1, sticky=tk.EW)
lab2 = tk.Label(win, text='输入图片路径', width=20).grid(row=0, column=0,sticky=tk.EW)
lab2 = tk.Label(win, text='手动选择路劲', width=20).grid(row=0, column=3,sticky=tk.EW)

b1 = tk.Button(win, text='选择路径', command=button1, width=20).grid(row=0, column=4,sticky=tk.EW)
b2 = tk.Button(win, text='确认路径', command=button2, width=20).grid(row=0, column=2,sticky=tk.EW)

b21 = tk.Button(win, text='镜像', command=button21, width=20).grid(row=1, column=0,sticky=tk.EW)
b22 = tk.Button(win, text='平移', command=button22, width=20).grid(row=1, column=1,sticky=tk.EW)
b23 = tk.Button(win, text='直方图均衡化', command=button23, width=20).grid(row=1, column=2,sticky=tk.EW)
b24 = tk.Button(win, text='顺时针旋转', command=button24, width=20).grid(row=1, column=3,sticky=tk.EW)
b25 = tk.Button(win, text='缩放', command=button25, width=20).grid(row=1, column=4,sticky=tk.EW)

b31 = tk.Button(win, text='图像平滑', command=button31, width=20).grid(row=2, column=0,sticky=tk.EW)
b32 = tk.Button(win, text='图像锐化', command=button32, width=20).grid(row=2, column=1,sticky=tk.EW)
b33 = tk.Button(win, text='低通滤波', command=button33, width=20).grid(row=2, column=2,sticky=tk.EW)
b34 = tk.Button(win, text='高斯噪声', command=gsnoise, width=20).grid(row=2, column=3,sticky=tk.EW)
b35 = tk.Button(win, text='高通滤波', command=button35, width=20).grid(row=2, column=4,sticky=tk.EW)
win.mainloop()

到了这里,关于python opencv+tkinter 使用tkinter实现交互式图像处理工具的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • OpenCV构建交互式图像距离测量工具

    在计算机视觉和图形学应用中,准确测量图像上的点之间距离是一项常见且重要的任务。本篇技术博客将详细介绍如何利用Python编程语言和OpenCV库构建一个交互式的图像距离测量工具。我们将通过编写一个名为ImageProcessor的类,让用户能够在图像上点击选取点,并实时显示两

    2024年04月14日
    浏览(33)
  • OpenCV4图像处理-图像交互式分割-GrabCut

    本文将实现一个与人(鼠标)交互从而分割背景的程序。 用户指定前景的大体区域,剩下为背景区域,还可以明确指出某些地方为前景或者背景,GrabCut算法采用分段迭代的方法分析前景物体形成模型树,最后根据权重决定某个像素是前景还是背景。 算法:GrabCut(img, mask, re

    2024年02月16日
    浏览(37)
  • 基于python下selenium库实现交互式图片保存操作(批量保存浏览器中的图片)

    Selenium是最广泛使用的开源Web UI(用户界面)自动化测试套件之一,可以通过编程与浏览量的交互式操作对网页进行自动化控制。基于这种操作进行数据保存操作,尤其是在图像数据的批量保存上占据优势。本博文基于selenium 与jupyterlab实现批量保存浏览器搜索到的图片。 Se

    2024年01月24日
    浏览(48)
  • OpenCV中的图像处理 —— 霍夫线 / 圈变换 + 图像分割(分水岭算法) + 交互式前景提取(GrabCut算法)

    🌎上一节我们介绍了OpenCV中傅里叶变换和模板匹配,这一部分我们来聊一聊霍夫线/圈变换的原理和应用、使用分水岭算法实现图像分割和使用GrabCut算法实现交互式前景提取 🏠哈喽大家好,这里是ErrorError!,一枚某高校大二本科在读的♂同学,希望未来在机器视觉领域能够有

    2023年04月08日
    浏览(32)
  • 如何用python做交互式界面?五分钟教会你。

    之前写了一个用Python制作的登陆界面的文章,这次教大家实现一个简单的注册界面,跟登陆相比,注册界面新增了一个上传头像的功能,以及将注册信息保存到本地txt文件中的功能,最终实现的效果是这样的   在导入必要的库之后,我们先创建一个宽度为350,高度为220的窗口

    2024年02月05日
    浏览(36)
  • 使用 htmx 构建交互式 Web 应用

    学习目标:了解htmx的基本概念、特点和用法,并能够运用htmx来创建交互式的Web应用程序。 学习内容: 1. 什么是htmx?    - htmx是一种用于构建交互式Web应用程序的JavaScript库。    - 它通过将HTML扩展为一种声明性的交互式语言,使得开发人员可以使用简单的HTML标记来实现动态

    2024年02月10日
    浏览(38)
  • 使用Gradio库创建交互式散点图

    ❤️觉得内容不错的话,欢迎点赞收藏加关注😊😊😊,后续会继续输入更多优质内容❤️ 👉有问题欢迎大家加关注私戳或者评论(包括但不限于NLP算法相关,linux学习相关,读研读博相关......)👈 博主原文链接:https://www.yourmetaverse.cn/nlp/424/ (封面图由文心一格生成)

    2024年02月16日
    浏览(38)
  • Python+turtle交互式绘图:可以用鼠标拖动的小海龟

    功能描述:代码运行后,在窗口上显示3个小海龟,使用鼠标拖动小海龟时可以动态改变窗口颜色,如下图所示。 说明:本例代码主体部分来自turtle Demo,我稍微修改了一下,重点增加了注释,方便阅读和理解。 参考代码: ----------相关阅读---------- 教学课件 1900页Python系列P

    2023年04月08日
    浏览(37)
  • 使用Gradio Interface构建交互式机器学习演示

    ❤️觉得内容不错的话,欢迎点赞收藏加关注😊😊😊,后续会继续输入更多优质内容❤️ 👉有问题欢迎大家加关注私戳或者评论(包括但不限于NLP算法相关,linux学习相关,读研读博相关......)👈 博主原文链接:https://www.yourmetaverse.cn/nlp/231/ (封面图由文心一格生成) 在

    2024年02月09日
    浏览(54)
  • 世界顶级的交互式反汇编工具——ida的使用详解

    IDA Pro是一款世界顶级的交互式反汇编工具,IDA Pro全名Interactive Disassembler Professional(交互式反汇编器专业版),是Hex-Rays公司的旗舰产品,目前最新版为IDA Pro7.0。主要用在反汇编和动态调试等方面,支持对多种处理器的不同类型的可执行模块进行反汇编处理,具有方便直观的操

    2023年04月08日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包