Python tkinter 实现本地打开图片进行标注

需求:

写一个软件,要求本地打开一张图片显示出来,并可以进行选框标注,自动生成坐标,同时给出输入框,可以手动输入内容,并保存成json文件 。

输入: 本地打开一张图片
操作: 鼠标进行选框标注,并输入选框内的文字
输出: 坐标值: x、y、w、h,json文件。 json文件包含 x、y、w、h和文字内容。

选工具

对python比较熟悉 ,Tkinter工具使用过,首选吧。 tkinter的文档比较少,但是做的过程中遇到的一些问题还是不能解决。

打开文件 并显示图片

#-*- coding:utf-8 -*-
import tkinter
from tkinter import *
from PIL import Image,ImageTk
from tkinter.filedialog import askopenfilename
import time

root = Tk()
root.geometry('500x500')
root.title('图片处理')

def choosepic():
    path_ = askopenfilename()
    path.set(path_)
    img_open = Image.open(file_entry.get())
    img = ImageTk.PhotoImage(img_open)
    image_label.config(image=img)
    image_label.image = img  # keep a reference


path = StringVar()
Button(root, text='选择图片', command=choosepic).pack()
file_entry = Entry(root, state='readonly', text=path)
#file_entry.pack() 
image_label = Label(root)
image_label.pack()
root.mainloop()

打开图片并刷新label显示,我自己写的代码一直没有成功,label打开后总是不能成功。以上代码参考下面连接。
python如何在tkinter中动态显示label图片

直接上全部代码吧

# -*- coding:utf-8 -*-
import tkinter
import tkinter.filedialog
import os
from PIL import ImageGrab
from time import sleep
from tkinter import *

from PIL import Image,ImageTk
from tkinter.filedialog import askopenfilename
import json
import codecs

# 创建tkinter主窗口
root = tkinter.Tk()
root.title('图片处理')

# 指定主窗口位置与大小
root.geometry('800x600+100+50')   # width x height + widthoffset + heightoffset

# 不允许改变窗口大小
root.resizable(False, False)
root.focusmodel()

class MyCapture:
    def __init__(self, png):

        # 变量X和Y用来记录鼠标左键按下的位置
        self.X = tkinter.IntVar(value=0)
        self.Y = tkinter.IntVar(value=0)
        self.selectPosition = None

        # 屏幕尺寸
        screenWidth = root.winfo_screenwidth()
        screenHeight = root.winfo_screenheight()

        # 创建顶级组件容器
        self.top = tkinter.Toplevel(root, width=screenWidth, height=screenWidth)

        # 不显示最大化、最小化按钮
        self.top.overrideredirect(True)
        self.canvas = tkinter.Canvas(self.top, bg='white', width=screenWidth, height=screenWidth)

        # 显示全屏截图,在全屏截图上进行区域截图
        self.image = tkinter.PhotoImage(file=png)
        self.canvas.create_image(screenWidth // 2, screenHeight // 2, image=self.image)

        # 鼠标左键按下的位置
        def onLeftButtonDown(event):
            self.X.set(event.x)
            self.Y.set(event.y)
            # 开始截图
            self.sel = True

        self.canvas.bind('<Button-1>', onLeftButtonDown)

        # 鼠标左键移动,显示选取的区域
        def onLeftButtonMove(event):
            if not self.sel:
                return
            global lastDraw
            try:
                # 删除刚画完的图形,要不然鼠标移动的时候是黑乎乎的一片矩形
                self.canvas.delete(lastDraw)
            except Exception as e:
                pass
            lastDraw = self.canvas.create_rectangle(self.X.get(), self.Y.get(), event.x, event.y, outline='red')

        self.canvas.bind('<B1-Motion>', onLeftButtonMove)

        # 获取鼠标左键抬起的位置,保存区域截图
        def onLeftButtonUp(event):
            self.sel = False
            try:
                self.canvas.delete(lastDraw)
            except Exception as e:
                pass
            sleep(0.1)

            # 更新主窗口位置坐标
            root.update()
            x = root.winfo_x()
            y = root.winfo_y()

            #考虑鼠标左键从右下方按下而从左上方抬起的截图
            myleft, myright = sorted([self.X.get(), event.x])
            mytop, mybottom = sorted([self.Y.get(), event.y])

            # Position : x , y, w, h
            self.selectPosition = (myleft-x,  mytop-y-30, myright-x,mybottom-y-30)
            print (myleft, myright)
            self.top.destroy()
            print ("destroy")
        self.canvas.bind('<ButtonRelease-1>', onLeftButtonUp)
        self.canvas.pack(fill=tkinter.BOTH, expand=tkinter.YES)
        # 开始截图

#设置截取坐标全局变量, 元组类型
CapturePosition = ()

def buttonCaptureClick():
    filename = 'temp.png'
    im = ImageGrab.grab()
    im.save(filename)
    im.close()

    # 显示全屏幕截图
    w = MyCapture(filename)
    buttonCapture.wait_window(w.top)

    xy_text.set(str(w.selectPosition))
    global  CapturePosition
    CapturePosition = w.selectPosition

    root.state('normal')
    os.remove(filename)

#获取输入的标注内容
def getstr():
    if input_valueText.get() != '':
        words = input_valueText.get()
        get_label["text"] = words


def save_jsonfile():
    json_content = {}
    #获取坐标
    json_content['x'] = CapturePosition[0]
    json_content['y'] = CapturePosition[1]
    json_content['w'] = CapturePosition[2]
    json_content['h'] = CapturePosition[3]

    # 获取输入内容
    value = get_label["text"]
    json_content['value'] = value

    # 存入json文件
    final_json = json.dumps(json_content, ensure_ascii=False)
    with codecs.open ("d:\\data_json.json",'a','utf-8') as file:
          file.write(final_json)


# 定义坐标显示位置
xy_text = StringVar()


#打开图片文件并显示
def choosepic():
    path_ = askopenfilename()
    path.set(path_)
    img_open = Image.open(file_entry.get())
    img = ImageTk.PhotoImage(img_open)
    image_label.config(image=img)
    image_label.image = img  # keep a reference

path = StringVar()
tkinter.Button(root, text = '打开文件' ,command=choosepic).place(x = 100, y = 530,w = 150, h = 40)
file_entry = Entry(root, state='readonly', text=path)
file_entry.pack()
image_label = Label(root, bg = 'gray')
image_label.place(x=0, y=0,width = 500, height = 500)


#添加截图按钮功能
buttonCapture = tkinter.Button(root, text='标注', command=buttonCaptureClick)

#坐标名称及显示坐标
label_xytitle = tkinter.Label(root,text ='标注位置坐标x, y, w, h :')
label_xytitle.place(x=520, y=50)
label = tkinter.Label(root, textvariable=xy_text,fg = 'blue')
label.place(x=520, y=70)


# 输入标注内容
input_valueTitle = StringVar()
input_valueTitle.set('请输入内容:')
label_inputTitle = tkinter.Label(root, textvariable=input_valueTitle)
label_inputTitle.place(x=520, y=90)
#输入框
input_valueText = tkinter.Entry(root,width=12)
input_valueText.place(x =520 , y=120,width = 250, height=40,anchor = NW)

#获取输入内容
comand = tkinter.Button(root, text="获取内容" ,command=getstr, width=10, height=2)
comand.place(x =520 , y=150,width = 250, height=40,anchor = NW)
get_label = tkinter.Label(root, fg = 'blue')
get_label.place(x =520 , y=200)

buttonCapture.place(x=300, y=530, width=150, height=40)

#保存数据
save = tkinter.Button(root, text="保存数据", command=save_jsonfile, width=10, height=2)
save.place(x =500 , y=530,width = 150, height=40,anchor = NW)

# 启动消息主循环
root.update()
root.mainloop()

需要整理下,看时间吧。 先记录一下。
遗留问题: 鼠标画框后,没有能把线画出来。 用canvas试了下,总有这样那样的问题。 待解决。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容

  • 用到的组件 1、通过CocoaPods安装 2、第三方类库安装 3、第三方服务 友盟社会化分享组件 友盟用户反馈 ...
    SunnyLeong阅读 14,499评论 1 180
  • 【导师】王玉印 【分舵】天地会 【舵主】王雅叶 【导图解说】本导图立意就一家企业进行分析整理,掌握基本信息。整理完...
    田丽清阅读 183评论 3 0
  • 很多夫妻会经常性的发生冷战,那夫妻冷战怎么解决?夫妻发生冷战时,不能只是一味的要求对方妥协,积极主动的沟通才是和谐...
    432c57ca314e阅读 1,110评论 0 1
  • 深夜里又想起了刘瑜说过的那段话。 有些人注定是你生命里的癌症,而有些人却只是一个喷嚏,这和你们相差的时间无关,距离...
    银调心烧阅读 382评论 0 1
  • SVN版本:1.5 及更新版本 名词说明: WC:Working Copy 你的工作区 Versioned:受控的...
    日风和阅读 4,219评论 1 23