bulk-image-tagger/application/main_window.py

280 lines
12 KiB
Python
Raw Normal View History

2022-11-13 16:17:15 -07:00
# -*- coding: utf-8 -*-
import os
from glob import glob
from io import BytesIO
import cv2
import numpy as np
from PIL import Image
from PIL.ImageQt import ImageQt
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import QFileDialog, QLabel
# Form implementation generated from reading ui file 'Bulk Image Tagger qt5.ui'
#
# Created by: PyQt5 UI code generator 5.14.1
def get_folder(folder):
glob_pattern = sorted(glob(os.path.join(folder, '*')), key=os.path.getctime)
out = []
for i in range(len(glob_pattern)):
if os.path.splitext(os.path.basename(glob_pattern[i]))[-1] in ['.jpg', '.jpeg', '.png']:
out.append(glob_pattern[i])
return out
def resizeAndPad(img, size, padColor=0):
h, w = img.shape[:2]
sh, sw = size
# interpolation method
if h > sh or w > sw: # shrinking image
interp = cv2.INTER_AREA
else: # stretching image
interp = cv2.INTER_CUBIC
# aspect ratio of image
aspect = w / h # if on Python 2, you might need to cast as a float: float(w)/h
# compute scaling and pad sizing
if aspect > 1: # horizontal image
new_w = sw
new_h = np.round(new_w / aspect).astype(int)
pad_vert = (sh - new_h) / 2
pad_top, pad_bot = np.floor(pad_vert).astype(int), np.ceil(pad_vert).astype(int)
pad_left, pad_right = 0, 0
elif aspect < 1: # vertical image
new_h = sh
new_w = np.round(new_h * aspect).astype(int)
pad_horz = (sw - new_w) / 2
pad_left, pad_right = np.floor(pad_horz).astype(int), np.ceil(pad_horz).astype(int)
pad_top, pad_bot = 0, 0
else: # square image
new_h, new_w = sh, sw
pad_left, pad_right, pad_top, pad_bot = 0, 0, 0, 0
# set pad color
if len(img.shape) == 3 and not isinstance(padColor, (list, tuple, np.ndarray)): # color image but only one color provided
padColor = [padColor] * 3
# scale and pad
scaled_img = cv2.resize(img, (new_w, new_h), interpolation=interp)
scaled_img = cv2.copyMakeBorder(scaled_img, pad_top, pad_bot, pad_left, pad_right, borderType=cv2.BORDER_CONSTANT, value=padColor)
return scaled_img
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
self.folder_contents = None
self.folder_contents_i = None
MainWindow.setObjectName("MainWindow")
MainWindow.setFixedSize(632, 447)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(MainWindow.sizePolicy().hasHeightForWidth())
MainWindow.setSizePolicy(sizePolicy)
MainWindow.setAnimated(False)
MainWindow.setDocumentMode(False)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
# self.graphicsView = QtWidgets.QGraphicsView(self.centralwidget)
# self.graphicsView.setGeometry(QtCore.QRect(10, 11, 611, 311))
# self.graphicsView.setObjectName("graphicsView")
self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit.setGeometry(QtCore.QRect(10, 330, 611, 31))
self.lineEdit.setObjectName("lineEdit")
self.lineEdit.returnPressed.connect(self.write_txtbox)
self.lineEdit.setEnabled(False)
self.comboBox = QtWidgets.QComboBox(self.centralwidget)
self.comboBox.setGeometry(QtCore.QRect(10, 370, 181, 25))
self.comboBox.setObjectName("comboBox")
self.comboBox.addItem("")
self.comboBox.addItem("")
self.comboBox.setEnabled(False)
self.save_button = QtWidgets.QPushButton(self.centralwidget)
self.save_button.setGeometry(QtCore.QRect(530, 370, 89, 25))
self.save_button.setObjectName("save_button")
self.save_button.clicked.connect(self.write_txtbox)
self.save_button.setEnabled(False)
self.next_button = QtWidgets.QPushButton(self.centralwidget)
self.next_button.setGeometry(QtCore.QRect(400, 370, 31, 25))
self.next_button.setObjectName("next_button")
self.next_button.clicked.connect(self.next_image)
self.next_button.setEnabled(False)
self.last_button = QtWidgets.QPushButton(self.centralwidget)
self.last_button.setGeometry(QtCore.QRect(360, 370, 31, 25))
self.last_button.setObjectName("last_button")
self.last_button.clicked.connect(self.prev_image)
self.last_button.setEnabled(False)
self.delete_button = QtWidgets.QPushButton(self.centralwidget)
self.delete_button.setGeometry(QtCore.QRect(440, 370, 89, 25))
self.delete_button.setObjectName("delete_button")
self.delete_button.clicked.connect(self.delete_image)
self.delete_button.setEnabled(False)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 632, 22))
self.menubar.setObjectName("menubar")
self.menuFile = QtWidgets.QMenu(self.menubar)
self.actionQuit = QtWidgets.QAction(MainWindow)
MainWindow.setMenuBar(self.menubar)
self.statusBar = QtWidgets.QStatusBar(MainWindow)
self.statusBar.setSizeGripEnabled(False)
self.statusBar.setObjectName("statusBar")
MainWindow.setStatusBar(self.statusBar)
self.actionQuit.setObjectName("actionQuit")
self.actionQuit.triggered.connect(self.close)
self.actionSave = QtWidgets.QAction(MainWindow)
self.actionSave.setObjectName("actionSave")
self.actionSave.triggered.connect(self.write_txtbox)
self.actionNext = QtWidgets.QAction(MainWindow)
self.actionNext.setObjectName("actionNext")
self.actionNext.triggered.connect(self.prev_image)
self.actionOpen = QtWidgets.QAction(MainWindow)
self.actionOpen.setObjectName("actionOpen")
self.actionOpen.triggered.connect(self.folder_open)
self.actionNext = QtWidgets.QAction(MainWindow)
self.actionNext.setObjectName("actionNext")
self.actionNext.triggered.connect(self.next_image)
self.actionDelete = QtWidgets.QAction(MainWindow)
self.actionDelete.setObjectName("actionDelete")
self.actionDelete.triggered.connect(self.delete_image)
self.menuFile.addAction(self.actionOpen)
self.menuFile.addAction(self.actionQuit)
self.menuFile.addSeparator()
self.menuFile.addAction(self.actionNext)
self.menuFile.addAction(self.actionNext)
self.menuFile.addAction(self.actionDelete)
self.menuFile.addAction(self.actionSave)
self.menubar.addAction(self.menuFile.menuAction())
self.label = QLabel(self)
self.label.setGeometry(QtCore.QRect(10, 30, 611, 311))
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "Bulk Image Tagger"))
self.lineEdit.setPlaceholderText(_translate("MainWindow", "Enter prompt here"))
self.comboBox.setItemText(0, _translate("MainWindow", "Premade Prompts"))
self.comboBox.setItemText(1, _translate("MainWindow", "example1"))
self.save_button.setText(_translate("MainWindow", "Save"))
self.next_button.setText(_translate("MainWindow", ""))
self.last_button.setText(_translate("MainWindow", ""))
self.delete_button.setText(_translate("MainWindow", "Delete"))
self.menuFile.setTitle(_translate("MainWindow", "File"))
self.actionQuit.setText(_translate("MainWindow", "Quit"))
self.actionQuit.setShortcut(_translate("MainWindow", "Ctrl+Q"))
self.actionSave.setText(_translate("MainWindow", "&Save"))
self.actionSave.setShortcut(_translate("MainWindow", "Ctrl+S"))
self.actionNext.setText(_translate("MainWindow", "Previous"))
2023-05-31 11:26:48 -06:00
self.actionNext.setShortcut(_translate("MainWindow", "Right"))
2022-11-13 16:17:15 -07:00
self.actionOpen.setText(_translate("MainWindow", "Open Folder"))
self.actionOpen.setShortcut(_translate("MainWindow", "Ctrl+O"))
self.actionDelete.setText(_translate("MainWindow", "&Delete"))
self.actionDelete.setShortcut(_translate("MainWindow", "Ctrl+D"))
def folder_open(self):
self.user_dir = QFileDialog.getExistingDirectory(
self, "Open Directory",
"",
QFileDialog.ShowDirsOnly | QFileDialog.DontResolveSymlinks,
)
self.folder_contents = get_folder(self.user_dir)
self.folder_contents_i = 0
self.last_button.setEnabled(False)
if len(self.folder_contents) > 0:
self.load_image(self.folder_contents[self.folder_contents_i])
self.enable(True)
else:
self.statusBar.showMessage('No images found!')
def load_image(self, image_path):
self.lineEdit.clear()
if os.path.isfile(image_path):
im = cv2.imread(image_path) # square image
im_resize = resizeAndPad(im, (311, 311), 311)
is_success, im_buf_arr = cv2.imencode(".png", im_resize)
im = Image.open(BytesIO(im_buf_arr.tobytes()))
im.tobytes('raw', 'RGB')
qim = ImageQt(im)
pixmap = QPixmap.fromImage(qim)
self.label.setPixmap(pixmap)
self.label.show()
self.statusBar.showMessage(os.path.split(self.folder_contents[self.folder_contents_i])[-1])
def next_image(self):
if self.folder_contents is not None:
if self.folder_contents_i + 1 < len(self.folder_contents):
self.folder_contents_i += 1
self.load_image(self.folder_contents[self.folder_contents_i])
else:
self.next_button.setEnabled(False)
if self.folder_contents_i - 1 < len(self.folder_contents):
self.last_button.setEnabled(True)
def prev_image(self):
if self.folder_contents is not None:
if self.folder_contents_i - 1 >= 0:
self.folder_contents_i -= 1
self.load_image(self.folder_contents[self.folder_contents_i])
elif self.folder_contents_i - 1 < len(self.folder_contents):
self.last_button.setEnabled(False)
if self.folder_contents_i + 1 < len(self.folder_contents):
self.next_button.setEnabled(True)
def write_txtbox(self):
if self.folder_contents is not None:
textbox_content = self.lineEdit.text()
if len(textbox_content) > 0:
f = open(f'{self.folder_contents[self.folder_contents_i]}.txt', 'w')
f.write(textbox_content)
f.close()
self.lineEdit.clear()
self.next_image()
def delete_image(self):
if self.folder_contents is not None and len(self.folder_contents) > 0:
self.label.hide()
try:
os.remove(self.folder_contents[self.folder_contents_i])
except:
print(self.folder_contents, self.folder_contents_i)
if os.path.exists(f'{self.folder_contents[self.folder_contents_i]}.txt'):
os.remove(f'{self.folder_contents[self.folder_contents_i]}.txt')
self.statusBar.showMessage(f'Deleted {os.path.split(self.folder_contents[self.folder_contents_i])[-1]}')
del self.folder_contents[self.folder_contents_i]
self.folder_contents_i -= 1
if len(self.folder_contents) > 0:
self.next_image()
else:
self.enable(False)
def enable(self, action):
self.save_button.setEnabled(action)
self.next_button.setEnabled(action)
self.last_button.setEnabled(action)
self.delete_button.setEnabled(action)
self.lineEdit.setEnabled(action)
self.comboBox.setEnabled(action)