批量操作图像:自定义显示图像组数
import os from PyQt5 import QtGui, QtCore from PyQt5 import QtWidgets from PyQt5.QtWidgets import * from PyQt5.QtGui import * import cv2 import numpy as np import qdarkstyle from PIL import Image import glob from ViewerThread import ImageBuffer, ThumbnailThread from QtCanvas import SugarGraphicsView from ThumbnailLoader import ThumbnailLoader import shutil
class ScrollThumbnail(QScrollArea): def init(self, main_win, group_size=1): super(ScrollThumbnail, self).init() self.group_size = group_size self.thumbnail = ThumbnailLoader(self, main_win) self.setWidget(self.thumbnail) self.setFixedHeight(self.thumbnail.image_height + 20) self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) self.bar: QScrollBar = self.horizontalScrollBar() self.bar.valueChanged.connect(self.sync_func) self.main_win = main_win self.setFocusPolicy(QtCore.Qt.NoFocus)
def sync_func(self):
pos = self.mapTo(self.main_win, self.thumbnail.get_item(0).pos())
self.thumbnail.set_view_x(self.bar.value())
def set_group_size(self, group_size):
self.group_size = group_size
def set_f_list(self, f_list):
self.thumbnail.set_f_list(f_list)
from SideViewer import Sidebar class ImageThumbnail(QWidget): save_history = {} def init(self, parent, src_button, group_size=1): super(ImageThumbnail, self).init() self.win = SugarGraphicsView(None, parent) self.win.setFocusPolicy(QtCore.Qt.StrongFocus) self.sider = Sidebar(src_button) self.sider.setFixedWidth(320) self.scroll = ScrollThumbnail(parent, group_size) self.main_win = parent self.layout = QVBoxLayout()
image_layout = QHBoxLayout()
image_layout.addWidget(self.win)
image_layout.addWidget(self.sider)
self.layout.addLayout(image_layout)
self.layout.addWidget(self.scroll)
self.setLayout(self.layout)
self.keyPressEvent = self.on_key_press_event
def on_key_press_event(self, event):
key = event.text().upper()
save_dir = self.sider.get_category_dir(key)
if save_dir is None:
print('No such category: ' + key)
else:
color = self.sider.get_color(key)
for src_path in self.main_win.f_list[self.main_win.index:self.main_win.index+self.scroll.group_size]:
filename = os.path.basename(src_path)
filepath = os.path.join(save_dir, filename)
if src_path not in self.save_history:
print(src_path + 'Save to ' + filepath)
self.sider.process(src_path, filepath)
self.scroll.thumbnail.view[src_path].set_color(color)
self.save_history[src_path] = filepath
elif os.path.exists(self.save_history[src_path]):
msg_box = QMessageBox()
msg_box.setWindowTitle('Move File')
msg_box.setText(f'该文件已经被放置在[{self.save_history[src_path]}],是否将它移至[{filepath}]?')
msg_box.setStandardButtons(QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel)
msg_box.setDefaultButton(QMessageBox.Cancel)
result = msg_box.exec_()
if result == QMessageBox.Yes:
print(self.save_history[src_path] + 'move to ' + filepath)
self.scroll.thumbnail.view[src_path].set_color(color)
shutil.move(self.save_history[src_path], filepath)
self.save_history[src_path] = filepath
elif result == QMessageBox.No:
if os.path.exists(src_path):
print(src_path + 'Save to ' + filepath)
self.scroll.thumbnail.view[src_path].set_color(color)
self.sider.process(src_path, filepath)
self.save_history[src_path] = filepath
else:
print(src_path + '文件已经被移动,本次操作视为无效')
else:
print('Operation canceled.')
def set_f_list(self, f_list):
self.scroll.thumbnail.set_f_list(f_list)
def set_data(self, data):
self.win.set_data(data)
self.win.reset()
class Window(QMainWindow): def init(self, win_w=2300, win_h=1250): super(Window, self).init() app.setStyleSheet(qdarkstyle.load_stylesheet_pyqt5()) self.label_right = QLabel()
self.src_folder_button = QPushButton('打开源文件夹')
self.src_folder_button.clicked.connect(self.openCall)
self.src_folder_edit = QLineEdit()
self.image_view = ImageThumbnail(self, (self.src_folder_edit, self.src_folder_button))
self.setWindowTitle('FilterViewer')
self.verticalLayout = QtWidgets.QVBoxLayout()
self.setCentralWidget(self.image_view)
self.status_bar = self.statusBar()
self.status_bar.showMessage('ready')
self.f_list = None
self.image_buffer_thread = None
self.setGeometry(0, 0, win_w, win_h)
self.index = 0
self.num = -1
self.setMouseTracking(True)
openAction = QAction(QIcon('open.png'), '&打开', self)
openAction.setStatusTip('Open document')
openAction.triggered.connect(self.openCall)
saveAction = QAction(QIcon('open.png'), '&Save', self)
saveAction.setShortcut('Ctrl+O')
saveAction.setStatusTip('Save document')
saveAction.triggered.connect(self.saveCall)
menuBar = self.menuBar()
MenuFile = menuBar.addMenu('&文件夹')
MenuFile.addAction(openAction)
MenuFile.addAction(saveAction)
def keyPressEvent(self, a0: QtGui.QKeyEvent) -> None:
self.image_view.on_key_press_event(a0)
def put_text(self, t=None):
num_str = str(self.num) if self.num > 0 else '∞'
file_num = '[%d / %s]' % (self.index, num_str)
if t is None:
if self.f_list is not None:
t = '当前文件: ' + str(self.f_list[self.index])
else:
t = ''
self.status_bar.showMessage(file_num + t)
def set_index(self, index):
self.index = index
self.set_data()
def __add__(self, other):
self.index += other
if self.f_list is not None:
num = len(self.f_list) - 1
else:
num = 0
self.index = min(num, self.index)
self.index = max(0, self.index)
self.set_data()
return self
def set_scale_label(self, scale):
self.label_right.setText('%d%% ' % int(scale * 100))
def convertQImageToMat(self, incomingImage):
incomingImage = incomingImage.convertToFormat(4)
width = incomingImage.width()
height = incomingImage.height()
ptr = incomingImage.bits()
ptr.setsize(incomingImage.byteCount())
arr = np.array(ptr).reshape(height, width, 4)
return cv2.cvtColor(arr, cv2.COLOR_BGR2GRAY)
def convertCv2ToQimage(self, im):
im = cv2.cvtColor(im, cv2.COLOR_BGR2RGB)
qim = QImage()
if im is None:
return qim
if im.dtype == np.uint8:
if len(im.shape) == 2:
qim = QImage(im.data, im.shape[1], im.shape[0], im.strides[0], QImage.Format_Indexed8)
qim.setColorTable([qRgb(i, i, i) for i in range(256)])
elif len(im.shape) == 3:
if im.shape[2] == 3:
qim = QImage(im.data, im.shape[1], im.shape[0], im.strides[0], QImage.Format_RGB888)
elif im.shape[2] == 4:
qim = QImage(im.data, im.shape[1], im.shape[0], im.strides[0], QImage.Format_ARGB32)
return qim
def saveCall(self):
rgb = Image.fromarray(self.cv2Image, mode=None)
path = QFileDialog.getSaveFileName(self, 'Save File')
if path:
print(path)
rgb.save(path[0])
def openCall(self):
dlg = QFileDialog()
dir_path = dlg.getExistingDirectory()
print('获得文件夹路径:', dir_path)
if dir_path is None or len(dir_path) == 0:
return
f_list = glob.glob(os.path.join(dir_path, '*.*'))
self.f_list = []
for file in sorted(f_list):
if '.' == os.path.basename(file)[0]:
continue
if file.lower().endswith(('.jpg', '.jpeg', '.png', '.bmp')):
file_path = file
self.f_list.append(file_path)
self.num = len(self.f_list)
print('文件夹中存在图片:', self.num)
self.image_buffer_thread = ImageBuffer(self.f_list)
print('主窗口图像开始载入')
self.image_buffer_thread.start()
print('发送文件列表给缩略图')
self.image_view.set_f_list(self.f_list)
self.set_data()
def set_data(self):
if self.image_buffer_thread is None:
return
self.image = self.convertCv2ToQimage(self.image_buffer_thread[self.index])
self.image_view.set_data(self.image)
self.put_text()
if name == 'main': import sys app = QApplication(sys.argv) window = Window() window.show() sys.exit(app.exec_())
原文地址: https://www.cveoy.top/t/topic/S5z 著作权归作者所有。请勿转载和采集!