日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

pythontkinter图片_Python tkinter实现图片标注功能(完整代码)

發布時間:2024/1/8 python 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 pythontkinter图片_Python tkinter实现图片标注功能(完整代码) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

.tkinter

tkinter是Python下面向tk的圖形界面接口庫,可以方便地進行圖形界面設計和交互操作編程。tkinter的優點是簡單易用、與Python的結合度好。tkinter在Python 3.x下默認集成,不需要額外的安裝操作;不足之處為缺少合適的可視化界面設計工具,需要通過代碼來完成窗口設計和元素布局。

Python tkinter實現圖片標注代碼,代碼如下所述:

#!/usr/bin/python

# -*- coding: UTF-8 -*-

import os

import sys

if sys.version_info < (3, 0):

import Tkinter as tk # 導入 Tkinter 庫

from tkFileDialog import askopenfilename, asksaveasfilename

else :

import tkinter as tk # 導入 Tkinter 庫

from tkinter.filedialog import askopenfilename, asksaveasfilename

from PIL import Image, ImageTk, ImageDraw

from time import sleep

import numpy as np

import cv2 as cv

DEF_WIDTH = 1080

DEF_HEIGHT = 720

IMAGE_HEIGHT = 720

FRAME_LEFT_WIDTH = 360

# 太小的選定區域我們需要丟棄,防止誤操作

MINI_RECT_AREA = 20

class RawImageEditor:

def __init__(self, win, img, rects):

#變量X和Y用來記錄鼠標左鍵按下的位置

self.X = tk.IntVar(value=0)

self.Y = tk.IntVar(value=0)

self.sel = False

self.lastDraw = None

self.lastDraws = []

self.imageScale = 1.0

self.dispWidth = DEF_WIDTH # 圖片顯示區域的最大高度,寬度

self.dispHeight = DEF_HEIGHT

self.rawImage = img

self.calcImageScale(self.rawImage)

self.dispWidth = int(self.imageScale * self.rawImage.width)

self.dispHeight = int(self.imageScale * self.rawImage.height)

# 圖片縮放

self.dispImage = self.rawImage.resize((self.dispWidth, self.dispHeight))

# 選擇區域

self.selPositions = []

for r in rects :

self.selPositions.append((r[0] * self.imageScale, r[1] * self.imageScale, r[2] * self.imageScale, r[3] * self.imageScale))

#創建頂級組件容器

self.top = tk.Toplevel(win, width=self.dispWidth, height=self.dispHeight)

#不顯示最大化、最小化按鈕

self.top.overrideredirect(True)

# Make topLevelWindow remain on top until destroyed, or attribute changes.

self.top.attributes('-topmost', 'true')

self.canvas = tk.Canvas(self.top, bg='white', width=self.dispWidth, height=self.dispHeight)

self.tkImage = ImageTk.PhotoImage(self.dispImage)

self.canvas.create_image(self.dispWidth//2, self.dispHeight//2, image=self.tkImage)

for r in self.selPositions :

draw = self.canvas.create_rectangle(r[0], r[1], r[2], r[3], outline='green')

self.lastDraws.append(draw)

#鼠標左鍵按下的位置

def onLeftButtonDown(event):

self.X.set(event.x)

self.Y.set(event.y)

#開始截圖

self.sel = True

#重新繪制已經選擇的區域

for draw in self.lastDraws :

self.canvas.delete(draw)

self.lastDraws = []

for r in self.selPositions :

draw = self.canvas.create_rectangle(r[0], r[1], r[2], r[3], outline='green')

self.lastDraws.append(draw)

self.canvas.bind('', onLeftButtonDown)

#鼠標左鍵移動,顯示選取的區域

def onLeftButtonMove(event):

if not self.sel:

return

try:

#刪除剛畫完的圖形,要不然鼠標移動的時候是黑乎乎的一片矩形

self.canvas.delete(self.lastDraw)

except Exception as e:

pass

self.lastDraw = self.canvas.create_rectangle(self.X.get(), self.Y.get(), event.x, event.y, outline='green')

self.canvas.bind('', onLeftButtonMove)

#獲取鼠標左鍵抬起的位置,保存區域截圖

def onLeftButtonUp(event):

self.sel = False

sleep(0.1)

#考慮鼠標左鍵從右下方按下而從左上方抬起的截圖

left, right = sorted([self.X.get(), event.x])

top, bottom = sorted([self.Y.get(), event.y])

if (right - left) * (bottom - top) > MINI_RECT_AREA :

self.selPositions.append((left,top,right,bottom))

#self.top.destroy()

#鼠標右鍵按下

def onRightButtonDown(event):

self.sel = False

self.top.destroy()

self.canvas.bind('', onRightButtonDown)

self.canvas.bind('', onLeftButtonUp)

self.canvas.pack(fill=tk.BOTH, expand=tk.YES)

def calcImageScale(self, image) :

w = image.width

h = image.height

self.imageScale = 1.0

# 計算最小的縮放比例,保證原始寬高比

if w > self.dispWidth and h > self.dispHeight :

ws = self.dispWidth * 1.0 / w

hs = self.dispHeight * 1.0 / h

if ws < hs :

self.imageScale = ws

else :

self.imageScale = hs

elif w > self.dispWidth and h < self.dispHeight :

self.imageScale = self.dispWidth * 1.0 / w

elif w < self.dispWidth and h > self.dispHeight :

self.imageScale = self.dispHeight * 1.0 / h

def waitForWindow(self, win) :

win.wait_window(self.top)

def selectedPositions(self) :

# 轉換為原始像素位置

realPos = []

for r in self.selPositions :

realPos.append((r[0] / self.imageScale, r[1] / self.imageScale, r[2] / self.imageScale, r[3] / self.imageScale))

return realPos

class MainWin(tk.Tk):

def __init__(self):

if sys.version_info >= (3, 0):

super().__init__()

else :

tk.Tk.__init__(self)

self.title('圖像處理工具')

self.geometry('{}x{}'.format(DEF_WIDTH, DEF_HEIGHT))

self.rawImagePath = ''

self.rawImage = None # self.rawImage 原始圖像,未經過縮放處理

self.transRawImage = None # self.transRawImage 經過轉換處理之后的原始圖像,沒有經過縮放處理

self.dispImage = None # self.dispImage 顯示圖像,可能經過縮放處理

self.imageScale = 1.0 # 圖片縮放比例,根據縮放比例進行顯示的時候的縮放處理,后期選擇區域的時候,需要進行縮放還原

self.leftFrameWidth = FRAME_LEFT_WIDTH

self.frameDispHeight = DEF_HEIGHT # 整個窗口的高度

self.labelTextHeight = 20 # 文本標簽的高度

self.btnHeight = 40 # 按鈕的高度

self.imageDispWidth = IMAGE_HEIGHT # 圖片顯示區域的最大高度,寬度

self.imageDispHeight = self.frameDispHeight / 2 - self.labelTextHeight * 2

# 選擇區域

self.liRect = []

self.rawImageEditor = None

self.setupUI()

def scaleDisplayImage(self, image) :

w = image.width

h = image.height

self.imageScale = 1.0

# 計算最小的縮放比例,保證原始寬高比

if w > self.imageDispWidth and h > self.imageDispHeight :

ws = self.imageDispWidth * 1.0 / w

hs = self.imageDispHeight * 1.0 / h

if ws < hs :

self.imageScale = ws

else :

self.imageScale = hs

elif w > self.imageDispWidth and h < self.imageDispHeight :

self.imageScale = self.imageDispWidth * 1.0 / w

elif w < self.imageDispWidth and h > self.imageDispHeight :

self.imageScale = self.imageDispHeight * 1.0 / h

# 圖片縮放

return image.resize((int(self.imageScale * w), int(self.imageScale * h)))

# 打開圖片時使用,傳值(圖)給展示函數

def openAndDisplayImage(self):

self.rawImagePath = self.selectImageFile()

if '' != self.rawImagePath :

self.rawImage = Image.open(self.rawImagePath)

self.rawImage = self.rawImage.convert('RGBA')

self.drawRawImageDisp()

def drawListBox(self):

self.l_box.delete(0,tk.END)

for item in self.liRect:

r = '{},{},{},{}'.format(round(item[0],1), round(item[1],1), round(item[2],1), round(item[3],1))

self.l_box.insert(0, r)

def drawRawImageDisp(self, selItems=[]):

self.dispImage = self.scaleDisplayImage(self.rawImage)

self.dispImage = self.dispImage.convert('RGB')

draw = ImageDraw.Draw(self.dispImage)

for i in range(len(self.liRect)) :

r = self.liRect[i]

if i in selItems :

draw.rectangle((r[0] * self.imageScale, r[1] * self.imageScale, r[2] * self.imageScale, r[3] * self.imageScale), outline = "red")

else :

draw.rectangle((r[0] * self.imageScale, r[1] * self.imageScale, r[2] * self.imageScale, r[3] * self.imageScale), outline = "green")

img = ImageTk.PhotoImage(self.dispImage)

self.image_l_raw.config(image=img)

self.image_l_raw.image = img

def deleteSelectedItemFromListBox(self):

#print(self.l_box.get(self.l_box.curselection()))

idx = self.l_box.curselection()

if len(idx) > 0 :

kp = []

for v in range(len(self.liRect)) :

if v not in idx :

kp.append(self.liRect[v])

self.liRect = kp

self.drawListBox()

self.drawRawImageDisp()

# 打開圖片時使用,獲得地址

def selectImageFile(self):

path = tk.StringVar()

file_entry = tk.Entry(self, state='readonly', text=path)

path_ = askopenfilename()

path.set(path_)

return file_entry.get()

def rawImageLabelClicked(self, event):

if None != self.rawImage :

if None == self.rawImageEditor :

self.rawImageEditor = RawImageEditor(self, self.rawImage, self.liRect)

self.rawImageEditor.waitForWindow(self.image_l_raw)

self.liRect = self.rawImageEditor.selectedPositions()

self.rawImageEditor = None

self.drawListBox()

self.drawRawImageDisp()

def onRectListboxSelect(self, event):

idx = self.l_box.curselection()

if len(idx) > 0 :

self.drawRawImageDisp(idx)

def drawTransImageDisp(self):

transImage = self.scaleDisplayImage(self.transRawImage)

transImage = transImage.convert('L')

img = ImageTk.PhotoImage(transImage)

self.image_l_trans.config(image=img)

self.image_l_trans.image = img

def doTransRawImage(self):

self.transRawImage = Image.new('L', (self.rawImage.width, self.rawImage.height))

for r in self.liRect :

im = self.rawImage.crop(r)

cv_im = cv.cvtColor(np.asarray(im), cv.COLOR_RGB2BGR)

hsv = cv.cvtColor(cv_im, cv.COLOR_BGR2HSV)

_, _, v = cv.split(hsv)

avg = np.average(v.flatten())

pixels = im.load()

for j in range(im.height) :

for i in range(im.width) :

hv = v[j,i]

if hv < avg * 1.2:

#im.putpixel((i, j), 0) # slow

pixels[i, j] = 0

'''else :

im.putpixel((i, j), (255, 255, 255, 255))'''

self.transRawImage.paste(im, (int(r[0]),int(r[1])), mask = None)

self.drawTransImageDisp()

def onTransRawImageBtnClicked(self):

if None != self.rawImage :

self.doTransRawImage()

def onSaveTransRawImageBtnClicked(self):

if None != self.transRawImage :

ext = os.path.splitext(self.rawImagePath)[-1]

(path,name) = os.path.split(self.rawImagePath)

filename = asksaveasfilename(title = '保存圖片', initialfile = name, filetypes = (("jpeg files","*{}".format(ext)), ("all files","*.*")))

if '' != filename :

self.transRawImage.save(filename)

def setupUI(self):

# 左邊菜單欄

left_f = tk.Frame(self, height=self.frameDispHeight, width=self.leftFrameWidth)

left_f.pack(side=tk.LEFT)

# 各種功能按鈕名稱及位置

btnOpen = tk.Button(left_f, text='打開圖像', command=self.openAndDisplayImage)

btnOpen.place(y=25, x=30, width=300, height=self.btnHeight)

btnTrans = tk.Button(left_f, text='處理圖像', command=self.onTransRawImageBtnClicked)

btnTrans.place(y=85, x=30, width=300, height=self.btnHeight)

l_selRect = tk.Label(left_f, text = '鼠標選定區域')

l_selRect.place(x=0, y=165, width=self.leftFrameWidth, height=self.labelTextHeight)

'''列表'''

self.l_box = tk.Listbox(left_f) # 創建兩個列表組件

self.l_box.place(x=0, y=165+self.labelTextHeight, width=self.leftFrameWidth, height=270)

self.l_box.bind('<>', self.onRectListboxSelect)

self.drawListBox()

# 刪除選定項

btnDel = tk.Button(left_f, text='刪除選定項', command=self.deleteSelectedItemFromListBox)

btnDel.place(y=460, x=30, width=300, height=self.btnHeight)

btnSave = tk.Button(left_f, text='保存結果', command=self.onSaveTransRawImageBtnClicked)

btnSave.place(y=550, x=30, width=300, height=self.btnHeight)

# 右側圖像顯示欄

right_f = tk.Frame(self, height=self.frameDispHeight, width=self.imageDispWidth)

right_f.pack(side=tk.RIGHT)

l_rawT = tk.Label(right_f, text = '原始圖片')

l_rawT.place(x=0, y=0, width=self.imageDispWidth, height=self.labelTextHeight)

self.image_l_raw = tk.Label(right_f, relief='ridge')

self.image_l_raw.place(x=0, y=self.labelTextHeight, width=self.imageDispWidth, height=self.imageDispHeight)

self.image_l_raw.bind("",self.rawImageLabelClicked)

l_transT = tk.Label(right_f, text = '處理后圖片')

l_transT.place(x=0, y=self.labelTextHeight + self.imageDispHeight, width=self.imageDispWidth, height=self.labelTextHeight)

self.image_l_trans = tk.Label(right_f, relief='ridge')

self.image_l_trans.place(x=0, y=self.labelTextHeight + self.imageDispHeight + self.labelTextHeight, width=self.imageDispWidth, height=self.imageDispHeight)

if __name__ == '__main__' :

win = MainWin()

# 進入消息循環

win.mainloop()

總結

以上所述是小編給大家介紹的Python tkinter實現圖片標注功能,希望對大家有所幫助,如果大家有任何疑問歡迎給我留言,小編會及時回復大家的!

總結

以上是生活随笔為你收集整理的pythontkinter图片_Python tkinter实现图片标注功能(完整代码)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。