| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642 |
- # pip install pillow
- import tkinter as tk
- from tkinter import filedialog, messagebox
- from PIL import Image, ImageTk
- import sqlite3
- import datetime
- import os
- # Подключение к бд
- conn = sqlite3.connect('sqlite.db')
- cursor = conn.cursor()
- cursor.execute('''
- CREATE TABLE IF NOT EXISTS annotations (
- id INTEGER PRIMARY KEY AUTOINCREMENT,
- filename TEXT NOT NULL,
- image_width INTEGER,
- image_height INTEGER,
- x1 INTEGER,
- y1 INTEGER,
- x2 INTEGER,
- y2 INTEGER,
- rectangle_width INTEGER,
- rectangle_height INTEGER,
- image_left INTEGER,
- image_bottom INTEGER,
- image_top INTEGER,
- image_right INTEGER,
- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
- )
- ''')
- conn.commit()
- root = tk.Tk()
- root.title("Image Annotation Tool")
- root.state('zoomed')
- root.configure(bg='#2b2b2b')
- bg_color = '#2b2b2b'
- frame_color = '#3c3c3c'
- text_color = '#ffffff'
- accent_color = '#4a90d9'
- panel = tk.Frame(root, width=200, height=600, bg=frame_color)
- panel.pack(side='right', fill='y')
- panel.pack_propagate(False)
- zagolovok = tk.Label(panel, text="Координаты \nизображения:",
- font=("Arial", 12, "bold"), bg=frame_color, fg=accent_color)
- zagolovok.pack(pady=20)
- levo_metka = tk.Label(panel, text="Left: 0", font=("Arial", 10), bg=frame_color, fg=text_color)
- levo_metka.pack(pady=8)
- niz_metka = tk.Label(panel, text="Bottom: 0", font=("Arial", 10), bg=frame_color, fg=text_color)
- niz_metka.pack(pady=8)
- verh_metka = tk.Label(panel, text="Top: 0", font=("Arial", 10), bg=frame_color, fg=text_color)
- verh_metka.pack(pady=8)
- pravo_metka = tk.Label(panel, text="Right: 0", font=("Arial", 10), bg=frame_color, fg=text_color)
- pravo_metka.pack(pady=8)
- razdelitel = tk.Frame(panel, height=2, bg=accent_color)
- razdelitel.pack(fill='x', padx=20, pady=20)
- ramka_pryam = tk.Frame(panel, bg=frame_color)
- ramka_pryam.pack(pady=10)
- metka_pryam = tk.Label(ramka_pryam, text="Координаты прямоугольника:",
- font=("Arial", 10, "bold"), bg=frame_color, fg=accent_color)
- metka_pryam.pack(pady=5)
- vvod_koord = {}
- metki_koord = ["X1:", "Y1:", "X2:", "Y2:"]
- znach_po_umolch = ["100", "100", "300", "300"]
- for i, metka in enumerate(metki_koord):
- ramochka = tk.Frame(ramka_pryam, bg=frame_color)
- ramochka.pack(pady=2)
- tk.Label(ramochka, text=metka, font=("Arial", 9), bg=frame_color, fg=text_color, width=4).pack(side='left')
- pole = tk.Entry(ramochka, width=8, font=("Arial", 9))
- pole.insert(0, znach_po_umolch[i])
- pole.pack(side='left')
- vvod_koord[metka.replace(":", "")] = pole
- peremesh_aktivno = False
- ugol_dlya_peremesh = None
- nach_koord_peremesh = None
- tekush_pryam = None
- tekush_izobr = None
- poz_izobr = None
- tekush_put_k_file = None
- pil_izobr_obj = None
- def obnovit_poly_vvoda():
- if tekush_pryam and poz_izobr:
- koord = holst.coords(tekush_pryam)
- if koord and len(koord) >= 4:
- img_x, img_y = poz_izobr
- vvod_koord["X1"].delete(0, tk.END)
- vvod_koord["X1"].insert(0, str(int(koord[0] - img_x)))
- vvod_koord["Y1"].delete(0, tk.END)
- vvod_koord["Y1"].insert(0, str(int(koord[1] - img_y)))
- vvod_koord["X2"].delete(0, tk.END)
- vvod_koord["X2"].insert(0, str(int(koord[2] - img_x)))
- vvod_koord["Y2"].delete(0, tk.END)
- vvod_koord["Y2"].insert(0, str(int(koord[3] - img_y)))
- def narisovat_pryam():
- global tekush_pryam
- try:
- x1 = int(vvod_koord["X1"].get())
- y1 = int(vvod_koord["Y1"].get())
- x2 = int(vvod_koord["X2"].get())
- y2 = int(vvod_koord["Y2"].get())
-
- holst.delete("pryamougolnik")
- holst.delete("ugol")
-
- if poz_izobr:
- img_x, img_y = poz_izobr
- abs_x1 = img_x + x1
- abs_y1 = img_y + y1
- abs_x2 = img_x + x2
- abs_y2 = img_y + y2
-
- if abs_x1 > abs_x2:
- abs_x1, abs_x2 = abs_x2, abs_x1
- if abs_y1 > abs_y2:
- abs_y1, abs_y2 = abs_y2, abs_y1
-
- tekush_pryam = holst.create_rectangle(
- abs_x1, abs_y1, abs_x2, abs_y2,
- outline="red", width=2, tags="pryamougolnik",
- dash=(5, 2)
- )
-
- narisovat_uglovye_markery(abs_x1, abs_y1, abs_x2, abs_y2)
- sohranit_koord_pryam(abs_x1, abs_y1, abs_x2, abs_y2)
-
- except ValueError:
- pass
- def sohranit_koord_pryam(x1, y1, x2, y2):
- global sohran_koord_pryam
- sohran_koord_pryam = [x1, y1, x2, y2]
- def narisovat_uglovye_markery(x1, y1, x2, y2):
- razmer_markera = 8
-
- # Левый верхний
- holst.create_oval(
- x1 - razmer_markera, y1 - razmer_markera,
- x1 + razmer_markera, y1 + razmer_markera,
- fill="red", outline="white", width=1, tags="ugol"
- )
-
- # Правый верхний
- holst.create_oval(
- x2 - razmer_markera, y1 - razmer_markera,
- x2 + razmer_markera, y1 + razmer_markera,
- fill="red", outline="white", width=1, tags="ugol"
- )
-
- # Левый нижний
- holst.create_oval(
- x1 - razmer_markera, y2 - razmer_markera,
- x1 + razmer_markera, y2 + razmer_markera,
- fill="red", outline="white", width=1, tags="ugol"
- )
-
- # Правый нижний
- holst.create_oval(
- x2 - razmer_markera, y2 - razmer_markera,
- x2 + razmer_markera, y2 + razmer_markera,
- fill="red", outline="white", width=1, tags="ugol"
- )
- def ochistit_pryam():
- global tekush_pryam
- holst.delete("pryamougolnik")
- holst.delete("ugol")
- tekush_pryam = None
- def nachalo_peremesh(event):
- global peremesh_aktivno, ugol_dlya_peremesh, nach_koord_peremesh
-
- if not tekush_pryam:
- return
-
- x, y = event.x, event.y
- koord_pryam = holst.coords(tekush_pryam)
-
- if not koord_pryam:
- return
-
- tolshina_klika = 15
-
- ugli = [
- (koord_pryam[0], koord_pryam[1], "levyy_verhniy"),
- (koord_pryam[2], koord_pryam[1], "pravyy_verhniy"),
- (koord_pryam[0], koord_pryam[3], "levyy_nizhniy"),
- (koord_pryam[2], koord_pryam[3], "pravyy_nizhniy")
- ]
-
- for ugol_x, ugol_y, tip_ugla in ugli:
- if abs(x - ugol_x) <= tolshina_klika and abs(y - ugol_y) <= tolshina_klika:
- peremesh_aktivno = True
- ugol_dlya_peremesh = tip_ugla
- nach_koord_peremesh = (x, y, koord_pryam[0], koord_pryam[1], koord_pryam[2], koord_pryam[3])
- holst.config(cursor="crosshair")
- return
- def peremeshchenie(event):
- global peremesh_aktivno, ugol_dlya_peremesh, nach_koord_peremesh
-
- if not peremesh_aktivno or not tekush_pryam:
- return
-
- x, y = event.x, event.y
- nach_x, nach_y, x1, y1, x2, y2 = nach_koord_peremesh
-
- dx = x - nach_x
- dy = y - nach_y
-
- x = max(0, min(x, holst.winfo_width()))
- y = max(0, min(y, holst.winfo_height()))
-
- if ugol_dlya_peremesh == "levyy_verhniy":
- nov_koord = [x, y, x2, y2]
- if nov_koord[2] - nov_koord[0] < 10:
- nov_koord[0] = nov_koord[2] - 10
- if nov_koord[3] - nov_koord[1] < 10:
- nov_koord[1] = nov_koord[3] - 10
- elif ugol_dlya_peremesh == "pravyy_verhniy":
- nov_koord = [x1, y, x, y2]
- if nov_koord[2] - nov_koord[0] < 10:
- nov_koord[2] = nov_koord[0] + 10
- if nov_koord[3] - nov_koord[1] < 10:
- nov_koord[1] = nov_koord[3] - 10
- elif ugol_dlya_peremesh == "levyy_nizhniy":
- nov_koord = [x, y1, x2, y]
- if nov_koord[2] - nov_koord[0] < 10:
- nov_koord[0] = nov_koord[2] - 10
- if nov_koord[3] - nov_koord[1] < 10:
- nov_koord[3] = nov_koord[1] + 10
- elif ugol_dlya_peremesh == "pravyy_nizhniy":
- nov_koord = [x1, y1, x, y]
- if nov_koord[2] - nov_koord[0] < 10:
- nov_koord[2] = nov_koord[0] + 10
- if nov_koord[3] - nov_koord[1] < 10:
- nov_koord[3] = nov_koord[1] + 10
- else:
- return
-
- holst.coords(tekush_pryam, *nov_koord)
- holst.delete("ugol")
- narisovat_uglovye_markery(*nov_koord)
- obnovit_poly_vvoda()
- sohranit_koord_pryam(*nov_koord)
- def konets_peremesh(event):
- global peremesh_aktivno, ugol_dlya_peremesh, nach_koord_peremesh
-
- if peremesh_aktivno:
- peremesh_aktivno = False
- ugol_dlya_peremesh = None
- nach_koord_peremesh = None
- holst.config(cursor="")
- def sohranit_v_bazu():
- if not tekush_put_k_file or not tekush_pryam:
- messagebox.showwarning("Нет данных", "Нет изображения или прямоугольника для сохранения")
- return
-
- try:
- koord = holst.coords(tekush_pryam)
- if not koord or len(koord) < 4:
- messagebox.showwarning("Ошибка", "Нет координат прямоугольника")
- return
-
- if poz_izobr:
- img_x, img_y = poz_izobr
- x1 = int(koord[0] - img_x)
- y1 = int(koord[1] - img_y)
- x2 = int(koord[2] - img_x)
- y2 = int(koord[3] - img_y)
-
- rect_width = abs(x2 - x1)
- rect_height = abs(y2 - y1)
-
- img_width = pil_izobr_obj.width if pil_izobr_obj else 0
- img_height = pil_izobr_obj.height if pil_izobr_obj else 0
-
- cursor.execute('''
- INSERT INTO annotations
- (filename, image_width, image_height, x1, y1, x2, y2,
- rectangle_width, rectangle_height, image_left, image_bottom,
- image_top, image_right, created_at)
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
- ''', (
- os.path.basename(tekush_put_k_file),
- img_width,
- img_height,
- x1,
- y1,
- x2,
- y2,
- rect_width,
- rect_height,
- int(levo_metka.cget("text").split(": ")[1]) if "Left: " in levo_metka.cget("text") else 0,
- int(niz_metka.cget("text").split(": ")[1]) if "Bottom: " in niz_metka.cget("text") else 0,
- int(verh_metka.cget("text").split(": ")[1]) if "Top: " in verh_metka.cget("text") else 0,
- int(pravo_metka.cget("text").split(": ")[1]) if "Right: " in pravo_metka.cget("text") else 0,
- datetime.datetime.now()
- ))
-
- conn.commit()
- messagebox.showinfo("Успех", "Данные успешно сохранены!")
-
- except Exception as e:
- messagebox.showerror("Ошибка", f"Не удалось сохранить данные: {str(e)}")
- def zagruzit_iz_istorii(id_zapisi):
- """Загрузить изображение и прямоугольник из записи истории"""
- try:
- cursor.execute("SELECT * FROM annotations WHERE id = ?", (id_zapisi,))
- record = cursor.fetchone()
-
- if not record:
- messagebox.showwarning("Ошибка", "Запись не найдена")
- return
-
- id_num, filename, img_w, img_h, x1, y1, x2, y2, rect_w, rect_h, img_l, img_b, img_t, img_r, created_at = record
-
- # Ищем файл изображения
- file_found = False
- possible_paths = [
- os.path.join(os.path.dirname(tekush_put_k_file) if tekush_put_k_file else "", filename),
- filename,
- os.path.join("images", filename),
- os.path.join(os.getcwd(), filename)
- ]
-
- for path in possible_paths:
- if os.path.exists(path):
- # Загружаем изображение
- zagruzit(path)
-
- # Ждем пока изображение загрузится
- root.update()
-
- # Устанавливаем координаты изображения
- levo_metka.config(text=f"Left: {img_l}")
- niz_metka.config(text=f"Bottom: {img_b}")
- verh_metka.config(text=f"Top: {img_t}")
- pravo_metka.config(text=f"Right: {img_r}")
-
- # Устанавливаем координаты прямоугольника
- vvod_koord["X1"].delete(0, tk.END)
- vvod_koord["X1"].insert(0, str(x1))
- vvod_koord["Y1"].delete(0, tk.END)
- vvod_koord["Y1"].insert(0, str(y1))
- vvod_koord["X2"].delete(0, tk.END)
- vvod_koord["X2"].insert(0, str(x2))
- vvod_koord["Y2"].delete(0, tk.END)
- vvod_koord["Y2"].insert(0, str(y2))
-
- # Рисуем прямоугольник
- narisovat_pryam()
-
- file_found = True
- messagebox.showinfo("Успех", f"Загружена запись ID: {id_num}\nФайл: {filename}")
- break
-
- if not file_found:
- messagebox.showwarning("Файл не найден",
- f"Не удалось найти файл: {filename}\n\n"
- f"Пожалуйста, выберите файл вручную.")
- # Открываем диалог выбора файла
- put_k_file = filedialog.askopenfilename(
- title=f"Найдите файл: {filename}",
- filetypes=[("Image files", "*.png *.jpg *.jpeg *.gif *.bmp")]
- )
- if put_k_file:
- zagruzit(put_k_file)
- # Повторно применяем параметры
- zagruzit_iz_istorii(id_zapisi)
-
- except Exception as e:
- messagebox.showerror("Ошибка", f"Не удалось загрузить данные: {str(e)}")
- def pokazat_istoriju():
- try:
- cursor.execute("SELECT * FROM annotations ORDER BY id DESC")
- records = cursor.fetchall()
-
- if not records:
- messagebox.showinfo("История", "База данных пуста")
- return
-
- history_window = tk.Toplevel(root)
- history_window.title("История")
- history_window.geometry("1000x550")
- history_window.configure(bg=bg_color)
-
- text_frame = tk.Frame(history_window, bg=bg_color)
- text_frame.pack(fill='both', expand=True, padx=10, pady=10)
-
- text_widget = tk.Text(text_frame, bg='#1e1e1e', fg=text_color,
- font=("Courier", 10), wrap='none')
- scrollbar_y = tk.Scrollbar(text_frame, orient='vertical', command=text_widget.yview)
- scrollbar_x = tk.Scrollbar(text_frame, orient='horizontal', command=text_widget.xview)
- text_widget.configure(yscrollcommand=scrollbar_y.set, xscrollcommand=scrollbar_x.set)
-
- text_widget.grid(row=0, column=0, sticky='nsew')
- scrollbar_y.grid(row=0, column=1, sticky='ns')
- scrollbar_x.grid(row=1, column=0, sticky='ew')
-
- text_frame.grid_rowconfigure(0, weight=1)
- text_frame.grid_columnconfigure(0, weight=1)
-
- col_widths = {'id': 4, 'filename': 25, 'img_size': 20, 'rect_coords': 25, 'rect_size': 20, 'date': 20}
-
- header_format = "{:>{id_width}} | {:<{filename_width}} | {:^{img_size_width}} | {:<{rect_coords_width}} | {:^{rect_size_width}} | {:<{date_width}} | {:^15}"
-
- headers = header_format.format(
- "ID", "Файл", "Размер изображения", "Прямоугольник", "Размер прямоуг.", "Дата создания", "Действия",
- id_width=col_widths['id'],
- filename_width=col_widths['filename'],
- img_size_width=col_widths['img_size'],
- rect_coords_width=col_widths['rect_coords'],
- rect_size_width=col_widths['rect_size'],
- date_width=col_widths['date']
- )
-
- text_widget.insert('end', headers + "\n")
- text_widget.insert('end', "-" * len(headers) + "\n")
-
- record_format = "{:>{id_width}} | {:<{filename_width}.{filename_width}} | {:^{img_size_width}} | {:<{rect_coords_width}} | {:^{rect_size_width}} | {:<{date_width}}"
-
- for record in records:
- id_num, filename, img_w, img_h, x1, y1, x2, y2, rect_w, rect_h, img_l, img_b, img_t, img_r, created_at = record
- img_size = f"{img_w}x{img_h}"
- rect_coords = f"({x1},{y1})-({x2},{y2})"
- rect_size = f"{rect_w}x{rect_h}"
- date_str = created_at[:19] if isinstance(created_at, str) else str(created_at)[:19]
-
- line = record_format.format(
- id_num, filename, img_size, rect_coords, rect_size, date_str,
- id_width=col_widths['id'],
- filename_width=col_widths['filename'],
- img_size_width=col_widths['img_size'],
- rect_coords_width=col_widths['rect_coords'],
- rect_size_width=col_widths['rect_size'],
- date_width=col_widths['date']
- )
-
- line_with_id = line + f" | ID:{id_num:>5}"
- text_widget.insert('end', line_with_id + "\n")
-
- text_widget.config(state='disabled')
-
- button_frame = tk.Frame(history_window, bg=bg_color)
- button_frame.pack(pady=10)
-
- id_frame = tk.Frame(button_frame, bg=bg_color)
- id_frame.pack(pady=5)
-
- tk.Label(id_frame, text="ID записи:", bg=bg_color, fg=text_color).pack(side='left', padx=5)
- entry_id = tk.Entry(id_frame, width=10, font=("Arial", 10))
- entry_id.pack(side='left', padx=5)
-
- def zagruzit_po_id():
- try:
- id_zapisi = int(entry_id.get())
- zagruzit_iz_istorii(id_zapisi)
- history_window.destroy() # Закрываем окно истории
- except ValueError:
- messagebox.showwarning("Ошибка", "Введите корректный ID записи")
-
- btn_open = tk.Button(button_frame, text="Загрузить выбранную запись",
- command=zagruzit_po_id,
- bg=accent_color, fg=text_color,
- font=("Arial", 10), relief='flat', padx=10, pady=5)
- btn_open.pack(pady=5)
-
- btn_close = tk.Button(button_frame, text="Закрыть",
- command=history_window.destroy,
- bg='#d94a4a', fg=text_color,
- font=("Arial", 10), relief='flat', padx=10, pady=5)
- btn_close.pack(pady=5)
-
- except Exception as e:
- messagebox.showerror("Ошибка", f"Не удалось загрузить историю: {str(e)}")
- ramka_knopok = tk.Frame(ramka_pryam, bg=frame_color)
- ramka_knopok.pack(pady=10)
- knopka_ris = tk.Button(ramka_knopok, text="Нарисовать",
- command=narisovat_pryam, bg=accent_color, fg=text_color,
- font=("Arial", 9), relief='flat', padx=5, pady=3)
- knopka_ris.pack(side='left', padx=5)
- knopka_ochist = tk.Button(ramka_knopok, text="Очистить",
- command=ochistit_pryam, bg='#d94a4a', fg=text_color,
- font=("Arial", 9), relief='flat', padx=5, pady=3)
- knopka_ochist.pack(side='left', padx=5)
- razdelitel2 = tk.Frame(panel, height=2, bg=accent_color)
- razdelitel2.pack(fill='x', padx=20, pady=20)
- def vibor():
- global tekush_put_k_file, pil_izobr_obj
- put_k_file = filedialog.askopenfilename(
- title="Выберите изображение",
- filetypes=[("Image files", "*.png *.jpg *.jpeg *.gif *.bmp")]
- )
- if put_k_file:
- tekush_put_k_file = put_k_file
- zagruzit(put_k_file)
- knopka_vibor = tk.Button(panel, text="Выбрать изображение",
- command=vibor, bg=accent_color, fg=text_color,
- font=("Arial", 10), relief='flat', padx=10, pady=5)
- knopka_vibor.pack(pady=10)
- knopka_sohranit = tk.Button(panel, text="Сохранить в базу данных",
- command=sohranit_v_bazu, bg='#2ecc71', fg=text_color,
- font=("Arial", 10, "bold"), relief='flat', padx=10, pady=5)
- knopka_sohranit.pack(pady=10)
- knopka_istorija = tk.Button(panel, text="Показать историю",
- command=pokazat_istoriju, bg='#9b59b6', fg=text_color,
- font=("Arial", 10), relief='flat', padx=10, pady=5)
- knopka_istorija.pack(pady=10)
- holst = tk.Canvas(root, bg='#1e1e1e', width=600, height=600, highlightthickness=0)
- holst.pack(side='left', fill='both', expand=True)
- holst.bind("<Button-1>", nachalo_peremesh)
- holst.bind("<B1-Motion>", peremeshchenie)
- holst.bind("<ButtonRelease-1>", konets_peremesh)
- def zagruzit(put_k_file):
- global tekush_izobr, poz_izobr, tekush_pryam, pil_izobr_obj
-
- try:
- pil_izobr_obj = Image.open(put_k_file)
-
- holst.delete("all")
- tekush_pryam = None
-
- shir_holst = holst.winfo_width()
- vys_holst = holst.winfo_height()
-
- img_width = pil_izobr_obj.width
- img_height = pil_izobr_obj.height
-
- scale_w = shir_holst / img_width
- scale_h = vys_holst / img_height
- scale = min(scale_w, scale_h, 1.0)
-
- new_width = int(img_width * scale)
- new_height = int(img_height * scale)
-
- pil_izobr_obj = pil_izobr_obj.resize((new_width, new_height), Image.Resampling.LANCZOS)
- tekush_izobr = ImageTk.PhotoImage(pil_izobr_obj)
-
- x_centr = (shir_holst - new_width) // 2
- y_centr = (vys_holst - new_height) // 2
-
- id_izobr = holst.create_image(x_centr, y_centr, anchor='nw', image=tekush_izobr)
- koord_izobr = holst.bbox(id_izobr)
-
- poz_izobr = (koord_izobr[0], koord_izobr[1])
-
- levo_metka.config(text=f"Left: {koord_izobr[0]}")
- niz_metka.config(text=f"Bottom: {koord_izobr[1]}")
- verh_metka.config(text=f"Top: {koord_izobr[2]}")
- pravo_metka.config(text=f"Right: {koord_izobr[3]}")
-
- for i, metka in enumerate(metki_koord):
- vvod_koord[metka.replace(":", "")].delete(0, tk.END)
- vvod_koord[metka.replace(":", "")].insert(0, znach_po_umolch[i])
-
- except Exception as e:
- holst.delete("all")
- holst.create_text(
- 300, 300, text="Ошибка загрузки изображения",
- fill=text_color, font=("Arial", 12), anchor='center'
- )
- def obnovit(event=None):
- if tekush_izobr and pil_izobr_obj:
- holst.delete("all")
- tekush_pryam = None
-
- shir_holst = holst.winfo_width()
- vys_holst = holst.winfo_height()
-
- if shir_holst <= 1 or vys_holst <= 1:
- return
-
- img_width = pil_izobr_obj.width
- img_height = pil_izobr_obj.height
-
- scale_w = shir_holst / img_width
- scale_h = vys_holst / img_height
- scale = min(scale_w, scale_h, 1.0)
-
- new_width = int(img_width * scale)
- new_height = int(img_height * scale)
-
- resized_img = pil_izobr_obj.resize((new_width, new_height), Image.Resampling.LANCZOS)
- tekush_izobr = ImageTk.PhotoImage(resized_img)
-
- x_centr = (shir_holst - new_width) // 2
- y_centr = (vys_holst - new_height) // 2
-
- id_izobr = holst.create_image(x_centr, y_centr, anchor='nw', image=tekush_izobr)
- koord_izobr = holst.bbox(id_izobr)
-
- poz_izobr = (koord_izobr[0], koord_izobr[1])
-
- levo_metka.config(text=f"Left: {koord_izobr[0]}")
- niz_metka.config(text=f"Bottom: {koord_izobr[1]}")
- verh_metka.config(text=f"Top: {koord_izobr[2]}")
- pravo_metka.config(text=f"Right: {koord_izobr[3]}")
- holst.bind("<Configure>", obnovit)
- holst.create_text(
- 300, 300,
- text="Нажмите 'Выбрать изображение'\nчтобы загрузить картинку",
- fill=text_color, font=("Arial", 12), anchor='center', justify='center'
- )
- def zakryt_bazu():
- conn.close()
- root.destroy()
- root.protocol("WM_DELETE_WINDOW", zakryt_bazu)
- root.mainloop()
|