import configparser import math import os import sys import numpy as np import cv2 from PyQt5 import QtWidgets from PyQt5.QtCore import QThread, pyqtSignal from PyQt5.QtWidgets import QApplication, QHeaderView, QTableWidgetItem, QFileDialog from Creat_Window import Ui_MainWindow class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): def __init__(self): QtWidgets.QMainWindow.__init__(self) # 創建主界面對象 self.setupUi(self) self.database_create = Database_Create() self.database_create.Created_Signal.connect(self.Created) self.messages_Finish_count = 0 self.tableWidget.setColumnCount(3) self.tableWidget.setRowCount(16) self.tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) self.tableWidget.horizontalHeader().setSectionResizeMode(0, QHeaderView.Interactive) self.comboBox_ClassNames.addItems(folder_name for folder_name in os.listdir(self.database_create.input_folder)) self.comboBox_IncreaseMultiplier.addItems([str(i) for i in range(1, 80)]) config = configparser.ConfigParser() config.read('Creat_Config.ini') self.label_InputFilePath.setText(config['FilePathInformation']['inputfilepath']) self.label_OutputFilePath.setText(config['FilePathInformation']['outputfilepath']) self.initTableWidget() self.iniGuiEvent() def iniGuiEvent(self): self.comboBox_ClassNames.currentIndexChanged.connect(self.ValueChange_ClassNames) self.comboBox_IncreaseMultiplier.currentIndexChanged.connect(self.ValueChange_IncreaseMultiplier) self.pushButton.clicked.connect(self.Creating) self.pushButton_ChangeInputFilePath.clicked.connect(self.ChangeFilePath) self.pushButton_ChangeOutputFilePath.clicked.connect(self.ChangeFilePath) def Creating(self): self.database_create.start() def Created(self, classname): item = QTableWidgetItem(str(len(os.listdir(os.path.join(self.database_create.output_folder, classname))))) self.tableWidget.setItem([cn for cn in self.database_create.ClassNameAndQuantity.keys()].index(classname.lower()), 2, item) def initTableWidget(self): self.tableWidget.clear() row = 0 for key in self.database_create.Config_dic.keys(): # Write the value to the current (row, col) position in the TableWidget item = QTableWidgetItem(key) self.tableWidget.setItem(row, 0, item) item = QTableWidgetItem(str(self.database_create.Config_dic[key])) self.tableWidget.setItem(row, 1, item) if self.database_create.OutputFileFolderAmountList == []: item = QTableWidgetItem('None') else: item = QTableWidgetItem(str(self.database_create.OutputFileFolderAmountList[row])) self.tableWidget.setItem(row, 2, item) row += 1 def ValueChange_ClassNames(self): self.comboBox_IncreaseMultiplier.setCurrentIndex(int(self.database_create.Config_dic[self.comboBox_ClassNames.currentText().lower()])-1) def ValueChange_IncreaseMultiplier(self): self.database_create.Config_dic[self.comboBox_ClassNames.currentText().lower()] = int(self.comboBox_IncreaseMultiplier.currentText()) self.initTableWidget() def ChangeFilePath(self): sender = self.sender() # Get the button that was clicked name = sender.accessibleName() # Get the accessibleName property print(f"Clicked button name: {name}") dir = QFileDialog.getExistingDirectory(self, "Open Directory", './', QFileDialog.ShowDirsOnly | QFileDialog.DontResolveSymlinks) if dir is not '': config = configparser.ConfigParser() config.read('Creat_Config.ini') if name == 'In': self.label_InputFilePath.setText(dir) self.database_create.input_folder = dir config.set('FilePathInformation', "inputfilepath", dir) config.write(open('Creat_Config.ini', "r+")) # r+模式 elif name == 'Out': self.label_OutputFilePath.setText(dir) self.database_create.output_folder = dir config.set('FilePathInformation', "outputfilepath", dir) config.write(open('Creat_Config.ini', "r+")) # r+模式 else: print('dir is None') class Database_Create(QThread): Created_Signal = pyqtSignal(str) def __init__(self): super().__init__() self.input_folder = '' self.output_folder = '' self.ScaleROI_Data = [] # self.ReadScaleROI_Data() self.Config_dic = {} self.ClassNameAndQuantity = {} self.OutputFileFolderAmountList = [] self.ReadINI() self.GettingClassInformation() self.Calculating() self.readOutputFilefolderAmonut() def Unsharpen(self, inputimage): # USM锐化增强方法(Unsharpen Mask) # 先对原图高斯模糊,用原图减去系数x高斯模糊的图像 # 再把值Scale到0~255的RGB像素范围 # 优点:可以去除一些细小细节的干扰和噪声,比卷积更真实 # (原图像-w*高斯模糊)/(1-w);w表示权重(0.1~0.9),默认0.6 # sigma = 5、15、25 blur_img = cv2.GaussianBlur(inputimage, (0, 0), 5) usm = cv2.addWeighted(inputimage, 1.5, blur_img, -0.5, 0) # cv.addWeighted(图1,权重1, 图2, 权重2, gamma修正系数, dst可选参数, dtype可选参数) h, w = inputimage.shape[:2] result = np.zeros([h, w * 2], dtype=inputimage.dtype) result[0:h, 0:w] = inputimage result[0:h, w:2 * w] = usm # cv.putText(图像名,标题,(x坐标,y坐标),字体,字的大小,颜色,字的粗细) return usm def ReadScaleROI_Data(self): with open(r"C:\Users\user\Desktop\ROI\Config\0_rotate_and_mirror.txt", 'r') as file: lines = file.readlines() for line in lines: line_data = line.strip().split(' ') if len(line_data) == 5: # 确保每行都有5个数据项 line_data[1] = int(float(line_data[1]) * 3400) line_data[2] = int(float(line_data[2]) * 1852) self.ScaleROI_Data.append(tuple(map(int, line_data[0:3]))) def ReadINI(self): config = configparser.ConfigParser() config.read('Creat_Config.ini') self.input_folder = config['FilePathInformation']['inputfilepath'] self.output_folder = config['FilePathInformation']['outputfilepath'] def GettingClassInformation(self): file_list = os.listdir(self.input_folder) for className in file_list: self.ClassNameAndQuantity[className.lower()] = len((os.listdir(os.path.join(self.input_folder, className)))) def Calculating(self): for className in self.ClassNameAndQuantity.keys(): self.Config_dic[className] = 1 if round(1250/(self.ClassNameAndQuantity[className]*8))==0 else round(1250/(self.ClassNameAndQuantity[className]*8)) def WriteINI(self): config = configparser.ConfigParser() config['Multiple'] = {} for key in self.Config_dic.keys(): config['Multiple'][key] = str(self.Config_dic[str(key).lower()]) with open('Creat_Config.ini', 'w') as f: config.write(f) def CaculateRoateAngle(self, forder_name): value = self.Config_dic[forder_name.lower()] print(f'int(value){int(value)}') angle = 360 / int(value) return angle def run(self): self.new_creat() # self.creat() def creat(self): folder_counter = 0 for folder_name in os.listdir(self.output_folder): folder_path = os.path.join(self.output_folder, folder_name) Angle = self.CaculateRoateAngle(folder_name) if os.path.isdir(folder_path): output_subfolder = os.path.join(self.output_folder, folder_name) os.makedirs(output_subfolder, exist_ok=True) print(f"Reading images from folder: {folder_path}") for file_name in os.listdir(folder_path): file_path = os.path.join(folder_path, file_name) if os.path.isfile(file_path) and file_name.endswith(('.jpg', '.png', '.jpeg')): image = cv2.imread(file_path) center = (image.shape[1] // 2, image.shape[0] // 2) for angle in range(int(Angle), 360, int(Angle)): print(int(angle)) rotation_matrix = cv2.getRotationMatrix2D(center, angle, 1.0) rotated_image = cv2.warpAffine(image, rotation_matrix, (image.shape[1], image.shape[0])) resized_image = cv2.resize(rotated_image, (224, 224)) new_file_name = f"{folder_counter}_rotated_{angle}_{file_name}" new_file_path = os.path.join(output_subfolder, new_file_name) # if file_name == '12_Phillips_1' or file_name == '13_Phillips_2': resized_image = self.Unsharpen(resized_image) cv2.imwrite(new_file_path, resized_image) print(f"Saved rotated image: {new_file_path}") self.Created_Signal.emit(folder_name) folder_counter += 1 # self.WriteINI() print('end') def new_creat(self): folder_counter = 0 for folder_name in os.listdir(self.input_folder): folder_path = os.path.join(self.input_folder, folder_name) if os.path.isdir(folder_path): output_subfolder = os.path.join(self.output_folder, folder_name) os.makedirs(output_subfolder, exist_ok=True) print(f"Reading images from folder: {folder_path}") for file_name in os.listdir(folder_path): file_path = os.path.join(folder_path, file_name) if os.path.isfile(file_path) and file_name.endswith(('.jpg', '.png', '.jpeg')): image = cv2.imread(file_path) center = (image.shape[1] // 2, image.shape[0] // 2) for angle in range(0, 360, 90): rotation_matrix = cv2.getRotationMatrix2D(center, angle, 1.0) rotated_image = cv2.warpAffine(image, rotation_matrix, (image.shape[1], image.shape[0])) resized_image = cv2.resize(rotated_image, (224, 224)) new_file_name = f"{folder_counter}_rotated_{angle}_{file_name}" new_file_path = os.path.join(output_subfolder, new_file_name) cv2.imwrite(new_file_path, resized_image) new_file_name = f"{folder_counter}_rotated_{angle}_flipx_{file_name}" new_file_path = os.path.join(output_subfolder, new_file_name) cv2.imwrite(new_file_path, cv2.flip(resized_image, 0)) self.Created_Signal.emit(folder_name) folder_counter += 1 # self.WriteINI() print('end') def readOutputFilefolderAmonut(self): parent_folder = self.output_folder # Initialize an empty list to store the folder names and file counts file_counts = [] # Iterate through entries (files and folders) in the parent folder if os.path.exists(parent_folder): for entry in os.scandir(parent_folder): if entry.is_dir(): folder_name = entry.name # List all files in the child folder files_in_child_folder = [f.name for f in os.scandir(entry.path) if f.is_file()] # Get the count of files in the child folder and append it to the list file_count = len(files_in_child_folder) file_counts.append(file_count) self.OutputFileFolderAmountList = file_counts if __name__ == '__main__': app = QApplication(sys.argv) # 固定的,PyQt5程式都需要QApplication對象。sys.argv是命令列參數清單,確保程式可以按兩下運行 MyWindow = MainWindow() # 初始化 MyWindow.show() # 將視窗控制項顯示在螢幕上 sys.exit(app.exec_()) # 程式運行,sys.exit方法確保程式完整退出