diff --git a/.gitignore b/.gitignore index 3c7eedca3..b1b543a8f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ resources/icons/.DS_Store - +env resources.py +Pipfile .idea* labelImg.egg-info* diff --git a/data/config.cfg b/data/config.cfg new file mode 100644 index 000000000..8890b9322 --- /dev/null +++ b/data/config.cfg @@ -0,0 +1,23 @@ +[save_config] +save_path = /home/pc02/testes_mask +demography_path = None +new_demography = None +fullbody_mask_path = None +new_fullbody_mask = None +save_demography = False +save_fullbody_mask = False +skip_save_confirmation = False + +[demography_config] +male = m +female = f +range_one = (0, 2) +range_two = (4, 6) +range_three = (8, 12) +range_four = (15, 20) +range_five = (25, 32) +range_six = (38, 43) +range_seven = (48, 53) +range_eight = (60, 100) +no_mask = no_mask +mask = mask diff --git a/data/predefined_classes.txt b/data/predefined_classes.txt index bc2eef133..92a0ae9f4 100644 --- a/data/predefined_classes.txt +++ b/data/predefined_classes.txt @@ -1,15 +1,5 @@ -dog person -cat -tv -car -meatballs -marinara sauce -tomato soup -chicken noodle soup -french onion soup -chicken breast -ribs -pulled pork -hamburger -cavity \ No newline at end of file +face +face_mask +male +female diff --git a/labelImg.py b/labelImg.py index 70c4cb7d5..b2f2dd62b 100755 --- a/labelImg.py +++ b/labelImg.py @@ -8,6 +8,10 @@ import re import sys import subprocess +import configparser +from typing import DefaultDict +from numpy.lib.npyio import save +import pandas as pd from functools import partial from collections import defaultdict @@ -100,6 +104,9 @@ def __init__(self, defaultFilename=None, defaultPrefdefClassFile=None, defaultSa # Whether we need to save or not. self.dirty = False + # Whether we delete last or not. + self.removeLast = False + self._noSelectionSlot = False self._beginner = True self.screencastViewer = self.getAvailableScreencastViewer() @@ -115,6 +122,32 @@ def __init__(self, defaultFilename=None, defaultPrefdefClassFile=None, defaultSa self.shapesToItems = {} self.prevLabelText = '' + self.config = configparser.ConfigParser() + self.config.read('data/config.cfg') + self.config.sections() + self.save_demography: bool = self.config.getboolean('save_config', 'save_demography') + self.save_fullbody_mask: bool = self.config.getboolean('save_config', 'save_fullbody_mask') + + try: + + self.demography_file = pd.read_csv(self.config.get('save_config', 'demography_path'), sep=';') + self.check_if_compatible_demography() + except Exception: + + self.demography_file = pd.DataFrame() + + try: + + self.fullbody_mask_file = pd.read_csv(self.config.get('save_config', 'fullbody_mask_path'), sep=';') + self.check_if_compatible_fullbody_mask() + except Exception: + + self.fullbody_mask_file = pd.DataFrame() + + self.gender: str = '' + self.age: str = '' + self.fullbody_mask = '' + listLayout = QVBoxLayout() listLayout.setContentsMargins(0, 0, 0, 0) @@ -155,8 +188,6 @@ def __init__(self, defaultFilename=None, defaultPrefdefClassFile=None, defaultSa self.labelList.itemChanged.connect(self.labelItemChanged) listLayout.addWidget(self.labelList) - - self.dock = QDockWidget(getStr('boxLabelText'), self) self.dock.setObjectName(getStr('labels')) self.dock.setWidget(labelListContainer) @@ -228,11 +259,51 @@ def __init__(self, defaultFilename=None, defaultPrefdefClassFile=None, defaultSa openPrevImg = action(getStr('prevImg'), self.openPrevImg, 'a', 'prev', getStr('prevImgDetail')) - verify = action(getStr('verifyImg'), self.verifyImg, - 'space', 'verify', getStr('verifyImgDetail')) - save = action(getStr('save'), self.saveFile, - 'Ctrl+S', 'save', getStr('saveDetail'), enabled=False) + 's', 'save', getStr('saveDetail'), enabled=True) + + saveMale = action('saveMale', self.saveMale, + 'm', 'saveMale', 'saveMale', enabled=True) + + saveFemale = action('saveFemale', self.saveFemale, + 'n', 'saveFemale', 'saveFemale', enabled=True) + + saveAgeRangeONE = action('saveAgeRangeONE', self.saveAgeRangeONE, + '5', 'saveAgeRangeONE', 'saveAgeRangeONE', enabled=True) + + saveAgeRangeTWO = action('saveAgeRangeTWO', self.saveAgeRangeTWO, + '6', 'saveAgeRangeTWO', 'saveAgeRangeTWO', enabled=True) + + saveAgeRangeTHREE = action('saveAgeRangeTHREE', self.saveAgeRangeTHREE, + '7', 'saveAgeRangeTHREE', 'saveAgeRangeTHREE', enabled=True) + + saveAgeRangeFOUR = action('saveAgeRangeFOUR', self.saveAgeRangeFOUR, + '8', 'saveAgeRangeFOUR', 'saveAgeRangeFOUR', enabled=True) + + saveAgeRangeFIVE = action('saveAgeRangeFIVE', self.saveAgeRangeFIVE, + '9', 'saveAgeRangeFIVE', 'saveAgeRangeFIVE', enabled=True) + + saveAgeRangeSIX = action('saveAgeRangeSIX', self.saveAgeRangeSIX, + '0', 'saveAgeRangeSIX', 'saveAgeRangeSIX', enabled=True) + + saveAgeRangeSEVEN = action('saveAgeRangeSEVEN', self.saveAgeRangeSEVEN, + '-', 'saveAgeRangeSEVEN', 'saveAgeRangeSEVEN', enabled=True) + + saveAgeRangeEIGHT = action('saveAgeRangeEIGHT', self.saveAgeRangeEIGHT, + '=', 'saveAgeRangeEIGHT', 'saveAgeRangeEIGHT', enabled=True) + + saveFullbodyMask = action('saveFullbodyMask', self.saveMaskStatusMask, + 'j', 'saveFullbodyMask', 'saveFullbodyMask', enabled=True) + + saveFullbodyNoMask = action('saveFullbodyNoMask', self.saveMaskStatusNoMask, + 'k', 'saveFullbodyNoMask', 'saveFullbodyNoMask', enabled=True) + + resetDemography = action('resetDemography', self.resetDemography, + 'e', 'resetDemography', 'resetDemography', enabled=True) + + deleteAnnotations = action('deleteAnnotations', self.deleteAnnotations, + 'r', 'deleteAnnotations', 'deleteAnnotations', enabled=True) + def getFormatMeta(format): """ @@ -351,9 +422,17 @@ def getFormatMeta(format): self.drawSquaresOption.triggered.connect(self.toogleDrawSquare) # Store actions for further handling. - self.actions = struct(save=save, save_format=save_format, saveAs=saveAs, open=open, close=close, resetAll = resetAll, deleteImg = deleteImg, + self.actions = struct(save=save, save_format=save_format, saveAs=saveAs, open=open, + close=close, resetAll = resetAll, deleteImg = deleteImg, lineColor=color1, create=create, delete=delete, edit=edit, copy=copy, createMode=createMode, editMode=editMode, advancedMode=advancedMode, + saveMale=saveMale, saveFemale=saveFemale, saveAgeRangeONE=saveAgeRangeONE, + saveAgeRangeTWO=saveAgeRangeTWO, saveAgeRangeTHREE=saveAgeRangeTHREE, + saveAgeRangeFOUR=saveAgeRangeFOUR, saveAgeRangeFIVE=saveAgeRangeFIVE, + saveAgeRangeSIX=saveAgeRangeSIX, saveAgeRangeSEVEN=saveAgeRangeSEVEN, + saveAgeRangeEIGHT=saveAgeRangeEIGHT, resetDemography=resetDemography, + deleteAnnotations=deleteAnnotations, saveFullbodyMask=saveFullbodyMask, + saveFullbodyNoMask=saveFullbodyNoMask, shapeLineColor=shapeLineColor, shapeFillColor=shapeFillColor, zoom=zoom, zoomIn=zoomIn, zoomOut=zoomOut, zoomOrg=zoomOrg, fitWindow=fitWindow, fitWidth=fitWidth, @@ -395,8 +474,13 @@ def getFormatMeta(format): self.displayLabelOption.setChecked(settings.get(SETTING_PAINT_LABEL, False)) self.displayLabelOption.triggered.connect(self.togglePaintLabelsOption) - addActions(self.menus.file, - (open, opendir, copyPrevBounding, changeSavedir, openAnnotation, self.menus.recentFiles, save, save_format, saveAs, close, resetAll, deleteImg, quit)) + addActions(self.menus.file,( + open, opendir, copyPrevBounding, changeSavedir, openAnnotation, + self.menus.recentFiles, save, save_format, saveAs, close, resetAll, deleteImg, quit, + saveMale, saveFemale, saveAgeRangeONE, saveAgeRangeTWO, saveAgeRangeTHREE, + saveAgeRangeFOUR, saveAgeRangeFIVE, saveAgeRangeSIX, saveAgeRangeSEVEN, saveAgeRangeEIGHT, + resetDemography, deleteAnnotations, saveFullbodyMask, saveFullbodyNoMask + )) addActions(self.menus.help, (help, showInfo)) addActions(self.menus.view, ( self.autoSaving, @@ -417,7 +501,7 @@ def getFormatMeta(format): self.tools = self.toolbar('Tools') self.actions.beginner = ( - open, opendir, changeSavedir, openNextImg, openPrevImg, verify, save, save_format, None, create, copy, delete, None, + open, opendir, changeSavedir, openNextImg, openPrevImg, save, save_format, None, create, copy, delete, None, zoomIn, zoom, zoomOut, fitWindow, fitWidth) self.actions.advanced = ( @@ -588,7 +672,7 @@ def setDirty(self): def setClean(self): self.dirty = False - self.actions.save.setEnabled(False) + self.actions.save.setEnabled(True) self.actions.create.setEnabled(True) def toggleActions(self, value=True): @@ -721,6 +805,10 @@ def fileitemDoubleClicked(self, item=None): filename = self.mImgList[currIndex] if filename: self.loadFile(filename) + if self.save_demography: + self.loadDemography() + if self.save_fullbody_mask: + self.loadFullbodyMask() # Add chris def btnstate(self, item= None): @@ -829,7 +917,7 @@ def updateComboBox(self): self.comboBox.update_items(uniqueTextList) - def saveLabels(self, annotationFilePath): + def saveLabels(self, annotationFilePath, name): annotationFilePath = ustr(annotationFilePath) if self.labelFile is None: self.labelFile = LabelFile() @@ -849,8 +937,8 @@ def format_shape(s): if self.labelFileFormat == LabelFileFormat.PASCAL_VOC: if annotationFilePath[-4:].lower() != ".xml": annotationFilePath += XML_EXT - self.labelFile.savePascalVocFormat(annotationFilePath, shapes, self.filePath, self.imageData, - self.lineColor.getRgb(), self.fillColor.getRgb()) + self.labelFile.savePascalVocFormat(annotationFilePath, shapes, self.filePath + name, self.imageData, + self.lineColor.getRgb(), self.fillColor.getRgb()) elif self.labelFileFormat == LabelFileFormat.YOLO: if annotationFilePath[-4:].lower() != ".txt": annotationFilePath += TXT_EXT @@ -1030,6 +1118,7 @@ def loadFile(self, filePath=None): """Load the specified file, or the last opened file if None.""" self.resetState() self.canvas.setEnabled(False) + if filePath is None: filePath = self.settings.get(SETTING_FILENAME) @@ -1202,6 +1291,11 @@ def closeEvent(self, event): def loadRecent(self, filename): if self.mayContinue(): self.loadFile(filename) + if self.save_demography: + self.loadDemography() + if self.save_fullbody_mask: + self.loadFullbodyMask() + def scanAllImages(self, folderPath): extensions = ['.%s' % fmt.data().decode("ascii").lower() for fmt in QImageReader.supportedImageFormats()] @@ -1281,30 +1375,24 @@ def importDirImages(self, dirpath): item = QListWidgetItem(imgPath) self.fileListWidget.addItem(item) - def verifyImg(self, _value=False): - # Proceding next image without dialog if having any label - if self.filePath is not None: - try: - self.labelFile.toggleVerify() - except AttributeError: - # If the labelling file does not exist yet, create if and - # re-save it with the verified attribute. - self.saveFile() - if self.labelFile != None: - self.labelFile.toggleVerify() - else: - return - - self.canvas.verified = self.labelFile.verified - self.paintCanvas() - self.saveFile() - def openPrevImg(self, _value=False): # Proceding prev image without dialog if having any label + if self.autoSaving.isChecked(): if self.defaultSaveDir is not None: if self.dirty is True: self.saveFile() + if self.save_demography: + try: + self.saveDemography() + except: + print(f'Failed to save demography of {self.filePath}') + if self.save_fullbody_mask: + try: + self.saveStatus() + except: + print(f'Failed to save fullbody mask of {self.filePath}') + else: self.changeSavedirDialog() return @@ -1320,16 +1408,31 @@ def openPrevImg(self, _value=False): currIndex = self.mImgList.index(self.filePath) if currIndex - 1 >= 0: + filename = self.mImgList[currIndex - 1] if filename: self.loadFile(filename) + if self.save_demography: + self.loadDemography() + if self.save_fullbody_mask: + self.loadFullbodyMask() def openNextImg(self, _value=False): # Proceding prev image without dialog if having any label - if self.autoSaving.isChecked(): + if self.autoSaving.isChecked() and not self.removeLast: if self.defaultSaveDir is not None: if self.dirty is True: self.saveFile() + if self.save_demography: + try: + self.saveDemography() + except: + print(f'Failed to save demography of {self.filePath}') + if self.save_fullbody_mask: + try: + self.saveStatus() + except: + print(f'Failed to save fullbody mask of {self.filePath}') else: self.changeSavedirDialog() return @@ -1345,11 +1448,23 @@ def openNextImg(self, _value=False): filename = self.mImgList[0] else: currIndex = self.mImgList.index(self.filePath) + lastFile = self.filePath if currIndex + 1 < len(self.mImgList): filename = self.mImgList[currIndex + 1] + if self.removeLast: + try: + os.remove(lastFile) + except FileNotFoundError: + print(f'File {lastFile} not found') + self.mImgList = self.scanAllImages(self.dirname) + self.removeLast = False if filename: self.loadFile(filename) + if self.save_demography: + self.loadDemography() + if self.save_fullbody_mask: + self.loadFullbodyMask() def openFile(self, _value=False): if not self.mayContinue(): @@ -1362,21 +1477,10 @@ def openFile(self, _value=False): if isinstance(filename, (tuple, list)): filename = filename[0] self.loadFile(filename) - - def saveFile(self, _value=False): - if self.defaultSaveDir is not None and len(ustr(self.defaultSaveDir)): - if self.filePath: - imgFileName = os.path.basename(self.filePath) - savedFileName = os.path.splitext(imgFileName)[0] - savedPath = os.path.join(ustr(self.defaultSaveDir), savedFileName) - self._saveFile(savedPath) - else: - imgFileDir = os.path.dirname(self.filePath) - imgFileName = os.path.basename(self.filePath) - savedFileName = os.path.splitext(imgFileName)[0] - savedPath = os.path.join(imgFileDir, savedFileName) - self._saveFile(savedPath if self.labelFile - else self.saveFileDialog(removeExt=False)) + if self.save_demography: + self.loadDemography() + if self.save_fullbody_mask: + self.loadFullbodyMask() def saveFileAs(self, _value=False): assert not self.image.isNull(), "cannot save empty image" @@ -1400,8 +1504,8 @@ def saveFileDialog(self, removeExt=True): return fullFilePath return '' - def _saveFile(self, annotationFilePath): - if annotationFilePath and self.saveLabels(annotationFilePath): + def _saveFile(self, annotationFilePath, name): + if annotationFilePath and self.saveLabels(annotationFilePath, name): self.setClean() self.statusBar().showMessage('Saved to %s' % annotationFilePath) self.statusBar().show() @@ -1430,6 +1534,11 @@ def resetAll(self): proc.startDetached(os.path.abspath(__file__)) def mayContinue(self): + if self.config.getboolean('save_config', 'skip_save_confirmation'): + try: + self.saveFile() + except: + print(f'Could Not save {self.filePath}') if not self.dirty: return True else: @@ -1559,10 +1668,291 @@ def togglePaintLabelsOption(self): def toogleDrawSquare(self): self.canvas.setDrawingShapeToSquare(self.drawSquaresOption.isChecked()) + # our methods + + def saveFile(self, _value=False): + currIndex = self.mImgList.index(self.filePath) + + save_to: str = self.config.get('save_config', 'save_path') + imgFileName = os.path.basename(self.filePath) + savedFileName = os.path.splitext(imgFileName)[0] + savedPath = os.path.join(ustr(save_to), savedFileName) + + if self.save_demography: + self.image.save(savedPath + '.jpg') + self.saveDemography() + self.setClean() + + return + + if self.save_fullbody_mask: + self.image.save(savedPath + '.jpg') + self.saveStatus() + self.setClean() + + return + + if self.defaultSaveDir is not None and len(ustr(self.defaultSaveDir)): + if self.filePath: + self.image.save(savedPath + '.jpg', imgFileName) + self._saveFile(savedPath, imgFileName) + else: + + self.image.save(savedPath + '.jpg') + self._saveFile(savedPath + '.xml', imgFileName) + + def saveDemography(self): + + relative_path = '/'.join(self.filePath.split('/')[-2:]) ##olhar + indexes = self.getIndexes(self.demography_file, relative_path) + if len(indexes) >= 1: + self.demography_file = self.demography_file.drop(indexes,0) + + if len(indexes) <= 1: + output_dict: DefaultDict = DefaultDict(list) + output_dict['original_image'].append(relative_path) + output_dict['age'].append(self.age) + output_dict['gender'].append(self.gender) + output_dict['x'].append('0') + output_dict['y'].append('0') + output_dict['dx'].append('0') + output_dict['dy'].append('0') + new_record = pd.DataFrame.from_dict(output_dict) + + self.demography_file = pd.concat([self.demography_file, new_record], ignore_index=True).fillna('') + self.demography_file.to_csv(self.config.get('save_config','new_demography'), sep=';', index=False) + self.resetDemography() + + else: + print(f'Error whith the record {relative_path}') + self.resetDemography() + + def saveStatus(self): + + relative_path = '/'.join(self.filePath.split('/')[-2:]) ##olhar + indexes = self.getIndexes(self.fullbody_mask_file, relative_path) + print(indexes) + if len(indexes) >= 1: + self.fullbody_mask_file = self.fullbody_mask_file.drop(indexes,0) + + if len(indexes) <= 1: + output_dict: DefaultDict = DefaultDict(list) + output_dict['original_image'].append(relative_path) + output_dict['status'].append(self.fullbody_mask) + new_record = pd.DataFrame.from_dict(output_dict) + + self.fullbody_mask_file = pd.concat([self.fullbody_mask_file, new_record], ignore_index=True).fillna('') + self.fullbody_mask_file.to_csv(self.config.get('save_config','new_fullbody_mask'), sep=';', index=False) + self.resetFullbodyMask() + + else: + print(f'Error whith the record {relative_path}') + self.resetFullbodyMask() + + def getIndexes(self, data_frame, value): + ''' Get index positions of value in dataframe i.e. dfObj.''' + listOfPos = list() + + result = data_frame.isin([value]) + + series = result.any() + columnNames = list(series[series == True].index) + + for col in columnNames: + rows = list(result[col][result[col] == True].index) + for row in rows: + listOfPos.append(row) + + return listOfPos + + def saveMale(self): + self.gender = self.config.get('demography_config', 'male') + self.statusBar().showMessage(f'Saved annotation {self.gender}') + self.dirty = True + + def saveFemale(self): + self.gender = self.config.get('demography_config', 'female') + self.statusBar().showMessage(f'Saved annotation {self.gender}') + self.dirty = True + + def saveAgeRangeONE(self): + self.age = self.config.get('demography_config', 'range_one') + self.statusBar().showMessage(f'Saved annotation {self.age}') + self.dirty = True + + def saveAgeRangeTWO(self): + self.age = self.config.get('demography_config', 'range_two') + self.statusBar().showMessage(f'Saved annotation {self.age}') + self.dirty = True + + def saveAgeRangeTHREE(self): + self.age = self.config.get('demography_config', 'range_three') + self.statusBar().showMessage(f'Saved annotation {self.age}') + self.dirty = True + + def saveAgeRangeFOUR(self): + self.age = self.config.get('demography_config', 'range_four') + self.statusBar().showMessage(f'Saved annotation {self.age}') + self.dirty = True + + def saveAgeRangeFIVE(self): + self.age = self.config.get('demography_config', 'range_five') + self.statusBar().showMessage(f'Saved annotation {self.age}') + self.dirty = True + + def saveAgeRangeSIX(self): + self.age = self.config.get('demography_config', 'range_six') + self.statusBar().showMessage(f'Saved annotation {self.age}') + self.dirty = True + + def saveAgeRangeSEVEN(self): + self.age = self.config.get('demography_config', 'range_seven') + self.statusBar().showMessage(f'Saved annotation {self.age}') + self.dirty = True + + def saveAgeRangeEIGHT(self): + self.age = self.config.get('demography_config', 'range_eight') + self.statusBar().showMessage(f'Saved annotation {self.age}') + self.dirty = True + + def saveMaskStatusMask(self): + self.fullbody_mask = self.config.get('demography_config', 'mask') + self.statusBar().showMessage(f'Saved annotation {self.fullbody_mask}') + self.dirty = True + + def saveMaskStatusNoMask(self): + self.fullbody_mask = self.config.get('demography_config', 'no_mask') + self.statusBar().showMessage(f'Saved annotation {self.fullbody_mask}') + self.dirty = True + + def resetDemography(self): + self.age = '' + self.gender = '' + + def resetFullbodyMask(self): + self.fullbody_mask = '' + + def loadDemography(self): + relative_path = '/'.join(self.filePath.split('/')[-2:]) + indexes = self.getIndexes(self.demography_file, relative_path) + + if len(indexes) == 1: + + demography = self.demography_file.loc[indexes[0]] + self.age = demography['age'] + self.gender = demography['gender'] + self.statusBar().showMessage(f'Loaded annotation Gender:{self.gender}\tAge: {self.age} ') + + elif len(indexes) > 1: + self.demography_file = self.demography_file.drop(indexes[0],0) + print(f'Multiple instances of the record {relative_path}') + + elif len(indexes) == 0: + output_dict: DefaultDict = DefaultDict(list) + output_dict['original_image'].append(relative_path) + output_dict['age'].append(self.age) + output_dict['gender'].append(self.gender) + output_dict['x'].append('0') + output_dict['y'].append('0') + output_dict['dx'].append('0') + output_dict['dy'].append('0') + new_record = pd.DataFrame.from_dict(output_dict) + + self.demography_file = pd.concat([self.demography_file, new_record], ignore_index=True).fillna('') + self.demography_file.to_csv(self.config.get('save_config','new_demography'), sep=';', index=False) + + def loadFullbodyMask(self): + + relative_path = '/'.join(self.filePath.split('/')[-2:]) + indexes = self.getIndexes(self.fullbody_mask_file , relative_path) + + if len(indexes) == 1: + + fullbody_mask = self.fullbody_mask_file.loc[indexes[0]] + self.fullbody_mask = fullbody_mask['status'] + self.statusBar().showMessage(f'Loaded annotation Fullbody Mask:{self.fullbody_mask}') + + elif len(indexes) > 1: + + self.fullbody_mask_file = self.fullbody_mask_file.drop(indexes[0],0) + print(f'Multiple instances of the record {relative_path}') + + elif len(indexes) == 0: + + output_dict: DefaultDict = DefaultDict(list) + output_dict['original_image'].append(relative_path) + output_dict['status'].append(self.fullbody_mask) + new_record = pd.DataFrame.from_dict(output_dict) + + self.fullbody_mask_file = pd.concat([self.fullbody_mask_file, new_record], ignore_index=True).fillna('') + self.fullbody_mask_file.to_csv(self.config.get('save_config','new_fullbody_mask'), sep=';', index=False) + + def deleteAnnotations(self): + if self.save_demography: + self.deleteDemography() + elif self.save_fullbody_mask: + self.deleteFullbodyMask() + + def deleteDemography(self): + + folder_path = self.config.get('save_config', 'save_path') + relative_path = '/'.join(self.filePath.split('/')[-2:]) + indexes = self.getIndexes(self.demography_file, relative_path) + + if len(indexes) == 1: + + self.demography_file = self.demography_file.drop(indexes[0],0) + + if self.filePath.split('/')[-1] in os.listdir(folder_path): + + os.remove(os.path.join(folder_path, self.filePath.split('/')[-1])) + + self.removeLast = True + self.dirty = False + self.openNextImg() + + def deleteFullbodyMask(self): + + folder_path = self.config.get('save_config', 'save_path') + + relative_path = '/'.join(self.filePath.split('/')[-2:]) + indexes = self.getIndexes(self.fullbody_mask_file, relative_path) + + if len(indexes) == 1: + + self.fullbody_mask_file = self.fullbody_mask_file.drop(indexes[0],0) + + if self.filePath.split('/')[-1] in os.listdir(folder_path): + + os.remove(os.path.join(folder_path, self.filePath.split('/')[-1])) + + self.removeLast = True + self.dirty = False + self.openNextImg() + + def check_if_compatible_fullbody_mask(self): + + if not set(['status', 'original_image']).issubset(self.fullbody_mask_file.keys()): + + print( + f'Did not fond an compatible mask status at {self.config.get("save_config", "fullbody_mask_path")}\n' + 'Be aware that it can be overwritten' + ) + raise Exception + + def check_if_compatible_demography(self): + + if not set(['gender', 'age', 'original_image']).issubset(self.demography_file.keys()): + + print( + f'Did not fond an compatible demography at {self.config.get("save_config", "demography_path")}\n' + 'Be aware that it can be overwritten' + ) + raise Exception + def inverted(color): return QColor(*[255 - v for v in color.getRgb()]) - def read(filename, default=None): try: reader = QImageReader(filename) diff --git a/requirements/requirements-linux-python3.txt b/requirements/requirements-linux-python3.txt index 787a7fda1..a4a90f753 100644 --- a/requirements/requirements-linux-python3.txt +++ b/requirements/requirements-linux-python3.txt @@ -1,2 +1,3 @@ pyqt5==5.10.1 lxml==4.2.4 +pandas==1.1.3