From b0b054aff543fec9b041e783defdbb22a1da2313 Mon Sep 17 00:00:00 2001 From: deeppomf Date: Wed, 9 Oct 2019 01:20:28 -0400 Subject: [PATCH] Add message box for decensoring --- config.py | 3 ++ decensor.py | 93 +++++++++++++++++++++++++++++++++++------------------ main.py | 45 ++++++++++++++++++-------- 3 files changed, 96 insertions(+), 45 deletions(-) diff --git a/config.py b/config.py index e72ac86..7e10789 100755 --- a/config.py +++ b/config.py @@ -32,6 +32,9 @@ def get_args(): parser.add_argument('--is_mosaic', type=str2bool, default='False', help='true if image has mosaic censoring, false otherwise') parser.add_argument('--variations', type=int, choices=[1, 2, 4], default=1, help='number of decensor variations to be generated') + #Other settings + parser.add_argument('--ui_mode', default=False, help='true if you want ui mode, false if you want command line interface') + args = parser.parse_args() return args diff --git a/decensor.py b/decensor.py index b617e11..dcb63b5 100755 --- a/decensor.py +++ b/decensor.py @@ -4,20 +4,28 @@ try: import numpy as np from PIL import Image - import os + import os, logging, sys from copy import deepcopy import config import file from model import InpaintNN from libs.utils import * + except ImportError as e: print("Error when importing libraries: ", e) print("Some Python libraries are missing. You can install all required libraries by running in the command line 'pip install -r requirements.txt' ") exit(1) +# #signals to the ui to print out +# class EmittingStream(QtCore.QObject): +# textWritten = QtCore.pyqtSignal(str) + +# def write(self, text): +# self.textWritten.emit(str(text)) + class Decensor: - def __init__(self): + def __init__(self, text_edit = None, text_cursor = None, ui_mode = None): args = config.get_args() self.is_mosaic = args.is_mosaic self.variations = args.variations @@ -25,10 +33,20 @@ class Decensor: self.decensor_input_path = args.decensor_input_path self.decensor_input_original_path = args.decensor_input_original_path self.decensor_output_path = args.decensor_output_path + + if ui_mode is not None: + self.ui_mode = ui_mode + else: + self.ui_mode = args.ui_mode if not os.path.exists(self.decensor_output_path): os.makedirs(self.decensor_output_path) + if self.ui_mode: + self.text_edit = text_edit + self.text_cursor = text_cursor + self.ui_mode = True + def find_mask(self, colored): mask = np.ones(colored.shape, np.uint8) i, j = np.where(np.all(colored[0] == self.mask_color, axis=-1)) @@ -60,12 +78,12 @@ class Decensor: color_file_path = os.path.join(input_color_dir, file_name) color_basename, color_ext = os.path.splitext(file_name) if os.path.isfile(color_file_path) and color_ext.casefold() == ".png": - print("--------------------------------------------------------------------------") - print("Decensoring the image {}".format(color_file_path)) + self.custom_print("--------------------------------------------------------------------------") + self.custom_print("Decensoring the image {}".format(color_file_path)) try : colored_img = Image.open(color_file_path) except: - print("Cannot identify image file (" +str(color_file_path)+")") + self.custom_print("Cannot identify image file (" +str(color_file_path)+")") self.files_removed.append((color_file_path,3)) # incase of abnormal file format change (ex : text.txt -> text.png) continue @@ -86,18 +104,18 @@ class Decensor: self.decensor_image_variations(ori_img, colored_img, file_name) break else: #for...else, i.e if the loop finished without encountering break - print("Corresponding original, uncolored image not found in {}".format(color_file_path)) - print("Check if it exists and is in the PNG or JPG format.") + self.custom_print("Corresponding original, uncolored image not found in {}".format(color_file_path)) + self.custom_print("Check if it exists and is in the PNG or JPG format.") #if we are doing a bar decensor else: self.decensor_image_variations(colored_img, colored_img, file_name) else: - print("--------------------------------------------------------------------------") - print("Image can't be found: "+str(color_file_path)) - print("--------------------------------------------------------------------------") + self.custom_print("--------------------------------------------------------------------------") + self.custom_print("Image can't be found: "+str(color_file_path)) + self.custom_print("--------------------------------------------------------------------------") if self.files_removed is not None: file.error_messages(None, self.files_removed) - print("\nDecensoring complete!") + self.custom_print("\nDecensoring complete!") def decensor_image_variations(self, ori, colored, file_name=None): for i in range(self.variations): @@ -134,7 +152,7 @@ class Decensor: if self.is_mosaic: #if mosaic decensor, mask is empty # mask = np.ones(ori_array.shape, np.uint8) - # print(mask.shape) + # self.custom_print(mask.shape) colored = colored.convert('RGB') color_array = image_to_array(colored) color_array = np.expand_dims(color_array, axis = 0) @@ -148,10 +166,10 @@ class Decensor: #colored image is only used for finding the regions regions = find_regions(colored.convert('RGB'), [v*255 for v in self.mask_color]) - print("Found {region_count} censored regions in this image!".format(region_count = len(regions))) + self.custom_print("Found {region_count} censored regions in this image!".format(region_count = len(regions))) if len(regions) == 0 and not self.is_mosaic: - print("No green regions detected! Make sure you're using exactly the right color.") + self.custom_print("No green regions detected! Make sure you're using exactly the right color.") return output_img_array = ori_array[0].copy() @@ -179,11 +197,11 @@ class Decensor: if not self.is_mosaic: a, b = np.where(np.all(mask_array == 0, axis = -1)) - # print(a,b) - # print(crop_img_array[a,b]) - # print(crop_img_array[a,b,0]) - # print(crop_img_array.shape) - # print(type(crop_img_array[0,0])) + # self.custom_print(a,b) + # self.custom_print(crop_img_array[a,b]) + # self.custom_print(crop_img_array[a,b,0]) + # self.custom_print(crop_img_array.shape) + # self.custom_print(type(crop_img_array[0,0])) crop_img_array[a,b,:] = 0. # temp = Image.fromarray((crop_img_array * 255.0).astype('uint8')) # temp.show() @@ -191,15 +209,15 @@ class Decensor: crop_img_array = np.expand_dims(crop_img_array, axis = 0) mask_array = np.expand_dims(mask_array, axis = 0) - # print(np.amax(crop_img_array)) - # print(np.amax(mask_array)) - # print(np.amax(masked)) + # self.custom_print(np.amax(crop_img_array)) + # self.custom_print(np.amax(mask_array)) + # self.custom_print(np.amax(masked)) - # print(np.amin(crop_img_array)) - # print(np.amin(mask_array)) - # print(np.amin(masked)) + # self.custom_print(np.amin(crop_img_array)) + # self.custom_print(np.amin(mask_array)) + # self.custom_print(np.amin(masked)) - # print(mask_array) + # self.custom_print(mask_array) crop_img_array = crop_img_array * 2.0 - 1 # mask_array = mask_array / 255.0 @@ -215,8 +233,8 @@ class Decensor: bounding_height = bounding_box[3]-bounding_box[1] #convert np array to image - # print(bounding_width,bounding_height) - # print(pred_img_array.shape) + # self.custom_print(bounding_width,bounding_height) + # self.custom_print(pred_img_array.shape) pred_img = Image.fromarray(pred_img_array.astype('uint8')) # pred_img.show() @@ -225,7 +243,7 @@ class Decensor: pred_img_array = image_to_array(pred_img) - # print(pred_img_array.shape) + # self.custom_print(pred_img_array.shape) pred_img_array = np.expand_dims(pred_img_array, axis = 0) # copy the decensored regions into the output image @@ -236,7 +254,7 @@ class Decensor: bounding_height_index = row + bounding_box[1] if (bounding_width_index, bounding_height_index) in region: output_img_array[bounding_height_index][bounding_width_index] = pred_img_array[i,:,:,:][row][col] - print("{region_counter} out of {region_count} regions decensored.".format(region_counter=region_counter, region_count=len(regions))) + self.custom_print("{region_counter} out of {region_count} regions decensored.".format(region_counter=region_counter, region_count=len(regions))) output_img_array = output_img_array * 255.0 @@ -254,12 +272,23 @@ class Decensor: save_path = os.path.join(self.decensor_output_path, file_name) output_img.save(save_path) - print("Decensored image saved to {save_path}!".format(save_path=save_path)) + self.custom_print("Decensored image saved to {save_path}!".format(save_path=save_path)) return else: - print("Decensored image. Returning it.") + self.custom_print("Decensored image. Returning it.") return output_img + #there are better ways to do this, but im sleepy + def custom_print(self, text): + if self.ui_mode: + from PySide2.QtGui import QTextCursor + + self.text_cursor.insertText(text) + self.text_cursor.insertText("\n") + self.text_edit.moveCursor(QTextCursor.End) + else: + print(text) + if __name__ == '__main__': decensor = Decensor() decensor.decensor_all_images_in_folder() diff --git a/main.py b/main.py index 9acedab..14dc7e1 100644 --- a/main.py +++ b/main.py @@ -4,10 +4,10 @@ # Please read this tutorial on how to prepare your images for use with DeepCreamPy. # The greater the number of variations, the longer decensoring process will be. -import sys -from PySide2.QtWidgets import QWidget, QHBoxLayout, QVBoxLayout, QGridLayout, QGroupBox, QDesktopWidget, QApplication, QAction, qApp, QApplication, QMessageBox, QRadioButton, QPushButton, QLabel, QSizePolicy -from PySide2.QtCore import Qt -from PySide2.QtGui import QFont +import sys, time +from PySide2.QtWidgets import QWidget, QHBoxLayout, QVBoxLayout, QGridLayout, QGroupBox, QDesktopWidget, QApplication, QAction, qApp, QApplication, QMessageBox, QRadioButton, QPushButton, QTextEdit, QLabel, QSizePolicy +from PySide2.QtCore import Qt, QObject +from PySide2.QtGui import QFont, QTextCursor from decensor import Decensor @@ -25,7 +25,7 @@ class MainWindow(QWidget): #Tutorial self.tutorialLabel = QLabel() - self.tutorialLabel.setText("Welcome to DeepCreamPy!\nIf you're new to DCP, please read the manual.") + self.tutorialLabel.setText("Welcome to DeepCreamPy!\n\nIf you're new to DCP, please read the README.\nThis program does nothing without the proper setup of your images.") self.tutorialLabel.setAlignment(Qt.AlignCenter) self.tutorialLabel.setFont(QFont('Sans Serif', 13)) @@ -57,27 +57,40 @@ class MainWindow(QWidget): # varLayout.addStretch(1) self.variationsGroupBox.setLayout(varLayout) - #button - decensorButton = QPushButton('Decensor Your Images') - decensorButton.clicked.connect(self.decensorClicked) - decensorButton.setSizePolicy( + #Decensor button + self.decensorButton = QPushButton('Decensor Your Images') + self.decensorButton.clicked.connect(self.decensorClicked) + self.decensorButton.setSizePolicy( QSizePolicy.Preferred, QSizePolicy.Preferred) + #Progress message + # self.progressGroupBox = QGroupBox('Progress') + + self.progressMessage = QTextEdit() + self.progressCursor = QTextCursor(self.progressMessage.document()) + self.progressMessage.setTextCursor(self.progressCursor) + self.progressCursor.insertText("After you prepared your images, click on the decensor button once to begin decensoring.\nPlease be patient.\nDecensoring will take time.\n") + #put all groups into grid grid_layout.addWidget(self.tutorialLabel, 0, 0, 1, 2) grid_layout.addWidget(self.censorTypeGroupBox, 1, 0, 1, 1) grid_layout.addWidget(self.variationsGroupBox, 1, 1, 1, 1) - grid_layout.addWidget(decensorButton, 2, 0, 1, 2) + grid_layout.addWidget(self.decensorButton, 2, 0, 1, 2) + grid_layout.addWidget(self.progressMessage, 3, 0, 4, 2) #window size settings - self.resize(300, 300) + self.resize(500, 500) self.center() - self.setWindowTitle('DeepCreamPy v2.2.0') + self.setWindowTitle('DeepCreamPy v2.2.0-alpha') self.show() def decensorClicked(self): - decensor = Decensor() + self.decensorButton.setEnabled(False) + self.progressMessage.clear() + self.progressCursor.insertText("Decensoring has begun!\n") + + decensor = Decensor(text_edit = self.progressMessage, text_cursor = self.progressCursor, ui_mode = True) #https://stackoverflow.com/questions/42349470/pyqt-find-checked-radiobutton-in-a-group #set decensor to right settings #censor type @@ -101,6 +114,12 @@ class MainWindow(QWidget): decensor.decensor_all_images_in_folder() + self.progressCursor.insertText("--------------------------------------------------------------------------\nTo decensor a new batch of images, please close this program and reopen it.\nThis is because the developer encountered a hard-to-fix bug that messes up repeated use of the decensor button.\nThe bug will be fixed in a future update.") + # time.sleep(3) + # sys.exit() + + # self.decensorButton.setEnabled(False) + # def showAbout(self): # QMessageBox.about(self, 'About', "DeepCreamPy v2.2.0 \n Developed by deeppomf")