def augment_test_data(self, cherryPick=False): """ Deprecated Menu: Augments the test data.""" iteration = -1 equalizeAfter2ndIterationSize = -1 # no equalization if cherryPick: newName = "" iteration = utils.radio_question("[?]", "Pick iteration", None, [1, 2, 3], [1, 2, 3]) else: newName = utils.value_question( "[?]", "Provide new name for data set", "s", "Do not use the same name as your current data set.", False) if utils.radio_question("[?]", "Equalize after second iteration?", None, ["Yes", "No"], [True, False]): equalizeAfter2ndIterationSize = utils.value_question( "[?]", "Provide desired size (w * h)", "i", "250000 for 500x500 images") normDefaultData = utils.radio_question("[?]", "Use default dataset?", None, ["Yes", "No"], [True, False]) datasetPath = "" if normDefaultData: datasetPath = Settings.G_TEST_DATA_PATH else: datasetPath = utils.value_question("[?]", "Provide path to test data", "s") data = TestData(datasetPath, 1) data.augment_test_data(newName, iteration, equalizeAfter2ndIterationSize)
def __instantiate_model_by_id(self, name=None, description=None): """ Instantiates a model using self.__modelId of the type ClassifierType Keyword arguments: name -- Name of the model. Default: Ask description -- Description of the model. Default: Ask """ if name is None: name = utils.value_question("[?]", "Provide a name for the model", "s") if description is None: description = utils.value_question("[?]", "Provide a description for the model", "s", "(optional)", True) # Ini testdata if self.__modelId != ClassifierType.VOTE.value: testdata = TestData(Settings.G_TEST_DATA_PATH, Settings.H_CROSS_VALIDATION_K, True) # Ini potential bow if self.__modelId == ClassifierType.SIFT.value: m = SIFTClassifier(testdata, Settings.E_MODEL_TYPE, name, description) bow = utils.value_question("[?]", "Provide a precomputed bow", "s", "(optional)", True) if bow != "": m.restore_bow(bow) return m elif self.__modelId == ClassifierType.HIST.value: return HistogramClassifier(testdata, Settings.H_MODEL_TYPE, name, description) elif self.__modelId == ClassifierType.SURF.value: m = SURFClassifier(testdata, Settings.E_MODEL_TYPE, name, description) bow = utils.value_question("[?]", "Provide a precomputed bow", "s", "(optional)", True) if bow != "": m.restore_bow(bow) return m elif self.__modelId == ClassifierType.ORB.value: return ORBClassifier(testdata, Settings.E_MODEL_TYPE, name, description) elif self.__modelId == ClassifierType.DAISY.value: return DaisyClassifier(testdata, Settings.E_MODEL_TYPE, name, description) elif self.__modelId == ClassifierType.CENSURE.value: from classification.local_features.censure import CENSUREClassifier return CENSUREClassifier(testdata, Settings.E_MODEL_TYPE, name, description) elif self.__modelId == ClassifierType.LF.value: return MultiStepClassifier(testdata, ModelType.OpenCV, name, description) elif self.__modelId == ClassifierType.LBP.value: return LBPClassifier(testdata, Settings.L_MODEL_TYPE, name, description) elif self.__modelId == ClassifierType.NN.value: return NeuralNetClassifier(testdata, name, description=description) elif self.__modelId == ClassifierType.VOTE.value: return MajorityClassifier(name, description) elif self.__modelId == ClassifierType.RANDOM.value: return RandomKeypointSampler(testdata, Settings.E_MODEL_TYPE, name, description)
def predict_image_folder(self): """ Menu for predicting images in a given folder.""" if MODEL_CONTROLLER.has_tester: tester = ModelTester(MODEL_CONTROLLER.model) else: tester = MODEL_CONTROLLER.tester path = utils.value_question("[...]", "Path to image folder", "s") tester.classify_image_folder(path)
def test_parameters(self): """ Main function to test one or more parameters of a classifier.""" classifier = MODEL_CONTROLLER.show_model_screen() if classifier == -1: return name = utils.value_question("[?]", "Provide a name for the test run", "s") description = utils.value_question( "[?]", "Provide a description for the test run", "s", "(optional)", True) # TODO: get parameter id ts = Testsuite(iterations=-1, random=False) ts.add_parameter(4, "Number of keypoints", range(32, 1182, 32)) tester = ParameterTester(name, description, classifier, ts) tester.start_testing()
def crop_bounding_boxes(self): """Menu for cropping the bounding boxes of datasets (Works with Food-100).""" boundingBoxFilename = utils.value_question( "[?]", "Provide bounding box file name", "s", "Do not forget the file extension.", True) normDefaultData = utils.radio_question("[?]", "Use default dataset?", None, ["Yes", "No"], [True, False]) datasetPath = "" if normDefaultData: datasetPath = Settings.G_TEST_DATA_PATH else: datasetPath = utils.value_question("[?]", "Provide path to test data", "s") data = TestData(datasetPath, 1) data.crop_bounding_boxes(boundingBoxFilename)
def rename_prefix(self): """Menu for renaming images in a dataset so that datasets can be merged / combined without overwriting files by merging.""" prefix = utils.value_question("[?]", "Provide prefix", "s", "Please do not use underscores (_).", True) normDefaultData = utils.radio_question("[?]", "Use default dataset?", None, ["Yes", "No"], [True, False]) datasetPath = "" if normDefaultData: datasetPath = Settings.G_TEST_DATA_PATH else: datasetPath = utils.value_question("[?]", "Provide path to test data", "s") data = TestData(datasetPath, 1) data.add_prefix_to_test_data(prefix)
def crop_test_data_to_square(self): """ Deprecated Menu: Crops all images in a dataset to squares.""" rejectedName = utils.value_question( "[?]", "Provide folder name for images that get rejected due to bad aspect ratio", "s", "Do not use the same name as your current data set.", False) normDefaultData = utils.radio_question("[?]", "Use default dataset?", None, ["Yes", "No"], [True, False]) datasetPath = "" if normDefaultData: datasetPath = Settings.G_TEST_DATA_PATH else: datasetPath = utils.value_question("[?]", "Provide path to test data", "s") data = TestData(datasetPath, 1) data.crop_test_data_to_square(rejectedName)
def normalize_testdata(self): """ Deprecated Menu: Resizes every image in a physical dataset to be the same.""" size = utils.value_question("[?]", "Provide desired size (w * h)", "i", "250000 for 500x500 images") newName = utils.value_question( "[?]", "Provide new name", "s", "Leave blank if you want to overwrite images", True) normDefaultData = utils.radio_question("[?]", "Use default dataset?", None, ["Yes", "No"], [True, False]) datasetPath = "" if normDefaultData: datasetPath = Settings.G_TEST_DATA_PATH else: datasetPath = utils.value_question("[?]", "Provide path to test data", "s") data = TestData(datasetPath, 1) data.normalize_test_data(size, newName)
def show_loading_screen(self): """ Loads a model by letting the user choose from a loading screen. Returns: model """ modelUuids, modelParams = self.get_model_options() if not modelUuids: print "No models available :(" raw_input("Press any key to continue") return None else: modelParams.insert(0, "Load manually") modelUuids.insert(0, "manual") modelUuid = utils.radio_question("[Load Model]", "Model Loader", None, modelParams, modelUuids) model = None if modelUuid == "manual": path = utils.value_question( "[...]", "Provide the path to the model directory", "s") if not utils.check_if_dir_exists(path): raise Exception("Could not find path {0}.".format(path)) try: model = self.load_model(None, path) return model except Exception, e: logging.exception( "Could not load model with Path {0}.".format(path)) raw_input("Press any key to continue") return None try: model = self.load_model(modelUuid) print "Model {0} was loaded successfully.".format( model.modelSaver.modelUuid) return model except Exception, e: logging.exception( "Could not load model with Uuid {0}. Restart application and try again." .format(modelUuid)) delete = utils.radio_question("[?]", "Delete model?", None, ["Yes", "No"], [True, False]) if delete: remove_model(modelUuid) raw_input("Press any key to continue") return None
def learn_custom_marker(self): """ "Learns a custom rectangular marker object by calculating SIFT keypoints.""" markerImage = load_image(utils.get_path_via_file_ui(), 0, 1) # save image cv.imwrite(utils.get_data_path() + "segmentationMarkerImage.jpg", markerImage) sift = cv.SIFT() self.CUSTOM_MARKER = sift.detectAndCompute(markerImage, None) # contains keypoints and descriptors self.MARKER_SIZE = (utils.value_question("[Marker Size]", "What is the marker width in cm?", "f"), utils.value_question("[Marker Size]", "What is the marker height in cm?", "f")) # save marker (not saving keypoints as they are not pickable) markerFile = {"marker": self.CUSTOM_MARKER[1], "markerDimension": self.MARKER_SIZE} with open(utils.get_data_path() + "segmentationMarker", "wb") as f: pickle.dump(markerFile, f) raw_input("Learning complete. Press any key to continue")
def normalize_test_data(self, size, newName="", forceOverwrite=False): normTestDataRootPath = utils.get_parent_dir(self.get_root_path()) + "/" if newName == "": if not forceOverwrite: overwrite = utils.radio_question("[?]", "Do you really wish to overwrite existing images?", None, ["Yes", "No"], [True, False]) else: overwrite = True if not overwrite: normTestDataRootPath += utils.value_question("", "Provide new foldername:", "s") else: normTestDataRootPath = self.get_root_path() else: normTestDataRootPath += newName utils.create_dir_if_necessary(normTestDataRootPath) print "Saving equalized test data set in path",normTestDataRootPath # segment data with only one segment self.segment_test_data({"all": 1}) self.new_segmentation() numberOfImages = self.testDataSize numberOfImagesDone = 0 currentClass = "" print "Starting equalization.\n" for img, class_, fileName in self.load_data("all", grayscale=False, outputActions=False, yieldFilename=True): path = normTestDataRootPath + "/" + class_ + "/" # reset counter if new class if not currentClass == class_: currentClass = class_ utils.create_dir_if_necessary(path) resizedImg = utils.equalize_image_size(img, size) path += fileName cv.imwrite(path, resizedImg) numberOfImagesDone += 1 utils.show_progress(True, numberOfImagesDone, numberOfImages, "Processing class {0}.\tTotal progress:", currentClass) print "\nEqualization finished." print "\n"
def initialize(self): """ Method to load the classifiers and test them.""" loader = ModelLoader() input = None testDataPath = None while True: input = utils.menue( "Majority Vote classifier", ["add classifier", "save", "test + finish", "finish"], False, True) if input == 2: self.modelSaver(self, -1) continue if input > 2: break # Display loading menu model = loader.show_loading_screen() if not model is None: if testDataPath is None: testDataPath = model.testData.get_root_path() self.modelSaver.datasetPath = testDataPath else: # check if the test datasets are the same if testDataPath != model.testData.get_root_path(): print "Could not load classifier {0} because the classifier was trained on different test data.".format( model.name) continue self.classifiers.append( (1, model) ) # Tuple[0] = model weight (1 is default weight) | Tuple[1] = model # why did we leave the loop? if input == 5: print "Cancel" return False # cancel -> back to start else: # initialize test data for the majority classifier # check if test data path has changed if not utils.check_if_dir_exists(testDataPath): testDataPath = utils.value_question( "[...]", "Root path to new Dataset Path", "s") self.testData = TestData(testDataPath, 1, False) self.testData.segment_test_data({"test": 1}) self.testData.new_segmentation() self.tester = ModelTester(self) # test classifier if input == 3 if input == 3: # Be careful: the results might not reflect the actual accuracy of the classifier. # if not changed the tester will test on the whole test data set. This might include images that the # classifiers has been trained on. For a real accuracy test the images have to be separated manually. results = self.tester.test_classifier(["test"]) self.tester.save_results(results, exportToCSV=False) print self.tester.format_results_string(results) testLoss = results["test"][1] save = utils.radio_question("[?]", "Save/Update classifier?", None, ["Yes", "No"], [True, False]) if save: self.modelSaver(self, testLoss) return self.classifiers != [ ] # finish. Return True if classifiers where loaded, False if not.
def load_model(self, modelUuid, manualPath=None): """ Load model from either model dictionary or manually. Keyword arguments: modelUuid -- uuid of the model. If None the method will try to load the model using the manualPath. manualPath -- if model shall be loaded manually this is the root path of the model directory Returns: model """ # manual mode. Load model that is not part of the model dictionary. if modelUuid is None: classifier = None try: with open(manualPath + "model", "rb") as f: classifier = pickle.load(f) except: logging.exception("Could not load model manually") return None return classifier else: # Load model from model dictionary modelParams = self.get_model_param(modelUuid) modelSavePath = modelParams[4] modelTypeId = modelParams[0] testdata = TestData(modelParams[3], 1, True) if not self.does_model_exist(modelUuid): raise AttributeError( "Model with uuid {0} was not found in model dictionary.". format(modelUuid)) if modelTypeId == "SIFT": from classification.local_features.sift import SIFTClassifier from classification.model import ModelType model = SIFTClassifier(testdata, Settings.E_MODEL_TYPE) model = model.load(modelSavePath) elif modelTypeId == "SURF": from classification.local_features.surf import SURFClassifier from classification.model import ModelType model = SURFClassifier(testdata, Settings.E_MODEL_TYPE) return model.load(modelSavePath) elif modelTypeId == "HIST": from classification.global_features.histogram import HistogramClassifier from classification.model import ModelType model = HistogramClassifier(testdata, Settings.E_MODEL_TYPE) return model.load(modelSavePath) if modelTypeId.startswith("mCL"): from classification.late_fusion import MajorityClassifier model = MajorityClassifier(testdata) try: with open(modelSavePath + "model", "r") as f: model = pickle.load(f) except: logging.exception("Could not load majority classifier.") return None return model # NNs or CNNs if modelTypeId.startswith("NN") or modelTypeId.startswith("CNN"): from classification.deep.neural_net import * # load testdata because we need the output shape modelWrapper = NeuralNetClassifier(testdata, modelParams[3]) # search for best weights if not utils.check_if_file_exists(modelSavePath + "model"): print "[!] Model file {0} was not found.".format( modelSavePath + "model") continue_ = utils.radio_question( "[?]", "It might be possible to restore the model using the weights file. Continue?", None, ["Yes", "No"], [True, False]) if not continue_: delete = utils.radio_question("[?]", "Delete model?", None, ["Yes", "No"], [True, False]) if delete: remove_model(modelUuid) raise Exception("Model file does not exist.") # try to restore best weights if more recent bestWeights = None if modelParams[7] == "nn_weights" and utils.check_if_file_exists( modelSavePath + "best_weights"): bestWeights = modelSavePath + "best_weights" modelWrapper.load_model(modelSavePath + "model", bestWeights) # restore params modelWrapper.modelSaver.bestLoss = modelParams[5] modelWrapper.modelSaver.modelDescription = modelParams[2] modelWrapper.modelSaver.modelUuid = modelUuid return modelWrapper if modelTypeId is None or modelTypeId == "None": print "There was a problem loading this model {0}. The save file might be corrupted. Model Dictionary {1}".format( modelTypeId, modelParams) if utils.radio_question("[?]", "Repair model with new model type ID?", None, ["Yes", "No"], [True, False]): modelTypeId = utils.value_question("[?]", "Model ID", "s") update_model_dict(modelUuid, 0, modelTypeId) print "Model Id changed. Restart application and try again." raw_input("Press any key to continue.") import sys sys.exit() raise Exception("Could not repair model.") else: raise Exception( "Model {0} is not supported yet.".format(modelTypeId))