Esempio n. 1
0
    def __init__(self):
        self.already_marked_dir = 'Datasets/legacy_jsons/agro'
        self.already_marked_list = os.listdir(self.already_marked_dir)

        super(WindowClassificationPicture, self).__init__()
        self.setWindowTitle("Plant Disease Recognizer")

        # TODO some dev stuff
        # with open(self.choose_json(content_title='config data')) as config_fp:
        with open('config_create_json.json') as config_fp:
            config_dict = json.load(config_fp)

        # self.img_path = self.choose_picture()
        # self.img_name = os.path.splitext(self.img_path)[0]

        self.window_shape = config_dict['window_shape']
        self.classes = config_dict['classes']
        self.default_label_size = config_dict['qt_label_size']
        self.img_thumb = config_dict['img_thumb']

        self._init_hbox_control()
        self._init_main_menu()

        self.main_layout = MyGridWidget(hbox_control=self.hbox_control)
        self.setCentralWidget(self.main_layout)
        self.showFullScreen()

        self.choose_and_render_image()

        # for offset calculation
        self.last_x = 0
        self.last_y = 0
Esempio n. 2
0
    def __init__(self):
        super(WindowPredictOnImage, self).__init__()
        with open(os.path.abspath('config_full_system.json')) as config_fp:
            self.config_dict = json.load(config_fp)

            # load layers
            self.clusterer = get_clusterer_by_name(
                self.config_dict['clusterer']['name'],
                self.config_dict['clusterer']['args'])
            if self.config_dict['preprocessor']['use']:
                self.segmentator = get_preprocessor_by_name(
                    self.config_dict['preprocessor']['name'],
                    self.config_dict['preprocessor']['args'])
            self.classifier = get_classifier_by_name(
                self.config_dict['classifier']['name'],
                self.config_dict['classifier']['args'])
            self.bad_key = self.config_dict['classifier']['bad_key']

            self._define_max_key_len()
            self._parse_image()

            self.main_layout = MyGridWidget(hbox_control=self.hbox_control)
            self.pbar = QProgressBar(self)
            self.main_layout.layout.addWidget(self.pbar)
            self.right_text_labels = []

            self.setCentralWidget(self.main_layout)
            self.showFullScreen()
            self.update_main_layout()
Esempio n. 3
0
    def __init__(self, x_data, y_data, y_predicted):
        super(WindowShowUnetFitting, self).__init__()
        with open('config_full_system.json') as config_fp:
            self.label_size = json.load(config_fp)['gui']['qt_label_size']

        self.main_layout = MyGridWidget(hbox_control=self.hbox_control)
        self.setCentralWidget(self.main_layout)
        self.showFullScreen()
        self.update_main_layout(x_data, y_data, y_predicted)
Esempio n. 4
0
class WindowShowUnetFitting(WindowInterface):
    ##############################################################
    # ---------------- init stuff --------------------------------
    ##############################################################
    def __init__(self, x_data, y_data, y_predicted):
        super(WindowShowUnetFitting, self).__init__()
        with open('config_full_system.json') as config_fp:
            self.label_size = json.load(config_fp)['gui']['qt_label_size']

        self.main_layout = MyGridWidget(hbox_control=self.hbox_control)
        self.setCentralWidget(self.main_layout)
        self.showFullScreen()
        self.update_main_layout(x_data, y_data, y_predicted)

    def _init_hbox_control(self):
        self.hbox_control = QtWidgets.QHBoxLayout()
        self.hbox_control.addStretch(1)
        self.hbox_control.addWidget(
            ControlButton("Update", self.update_main_layout))
        self.hbox_control.addWidget(ControlButton("Quit", self.quit_default))

    ##############################################################
    # ---------------- gui logic stuff ---------------------------
    ##############################################################
    def clear(self):
        self.main_layout.clear()

    def update_main_layout(self, x_data, y_data, y_predicted):
        self.clear()

        label_list = []
        for x, y, y_answer in zip(x_data, y_data, y_predicted):
            label_list.append(
                ImageTextLabel(x=x, text='input', label_size=self.label_size))
            label_list.append(
                ImageTextLabel(x=y, text='output', label_size=self.label_size))
            label_list.append(
                ImageTextLabel(x=y_answer,
                               text='U-Net answer',
                               label_size=self.label_size))

        x_len = 3
        self.main_layout.update_grid(
            windows_width=self.frameGeometry().width(),
            window_height=self.frameGeometry().height(),
            x_len=x_len,
            y_len=int(x_data.shape[0] * 3 / x_len),
            label_list=label_list)
Esempio n. 5
0
    def __init__(self, x_data, y_data, y_predicted, classes):
        super(WindowShowPredictions, self).__init__()

        config_dict = self.load_dict_from_json_with_keys(
            key_list=['qt_label_size'])
        self.label_size = config_dict['qt_label_size']

        self.x_data = x_data
        self.y_data = y_data
        self.y_predicted = y_predicted
        self.classes = classes

        self._define_max_key_len()

        self.main_layout = MyGridWidget(hbox_control=self.hbox_control)
        self.setCentralWidget(self.main_layout)
        self.showFullScreen()
        self.update_main_layout()
Esempio n. 6
0
class WindowClassificationPicture(WindowInterface):
    ##############################################################
    # ---------------- init stuff --------------------------------
    ##############################################################
    def __init__(self):
        self.already_marked_dir = 'Datasets/legacy_jsons/agro'
        self.already_marked_list = os.listdir(self.already_marked_dir)

        super(WindowClassificationPicture, self).__init__()
        self.setWindowTitle("Plant Disease Recognizer")

        # TODO some dev stuff
        # with open(self.choose_json(content_title='config data')) as config_fp:
        with open('config_create_json.json') as config_fp:
            config_dict = json.load(config_fp)

        # self.img_path = self.choose_picture()
        # self.img_name = os.path.splitext(self.img_path)[0]

        self.window_shape = config_dict['window_shape']
        self.classes = config_dict['classes']
        self.default_label_size = config_dict['qt_label_size']
        self.img_thumb = config_dict['img_thumb']

        self._init_hbox_control()
        self._init_main_menu()

        self.main_layout = MyGridWidget(hbox_control=self.hbox_control)
        self.setCentralWidget(self.main_layout)
        self.showFullScreen()

        self.choose_and_render_image()

        # for offset calculation
        self.last_x = 0
        self.last_y = 0

    def choose_and_render_image(self):
        self.img_path = self.choose_picture()
        if self.img_path != '':
            self.clear()
            self.img_name = os.path.splitext(self.img_path)[0]
            self._init_images()
            self._init_label_list()
            self.update_main_layout()

    def _init_hbox_control(self):

        self.hbox_control = QtWidgets.QHBoxLayout()

        self.zoom_list = [0.25, 0.5, 0.75, 1]
        self.zoom = self.zoom_list[0]
        self.zoom_no = 0

        self.hbox_control.addWidget(
            ControlButton("Okay",
                          self.okay_pressed,
                          styleSheet='background-color: #0cdb3c'))
        self.hbox_control.addWidget(
            ControlButton("Choose image",
                          self.choose_and_render_image,
                          styleSheet='background-color: #ffbe25'))
        self.hbox_control.addWidget(
            ControlButton("Quit",
                          self.quit_default,
                          styleSheet='background-color: #e84a1a'))

    def _init_main_menu(self):

        mainMenu = self.menuBar()
        zoomMenu = mainMenu.addMenu('Zoom')

        def add_zoom_to_menu(new_zoom):
            newAct = QAction('Zoom %d %%' % (zoom * 100), self)
            newAct.triggered.connect(lambda: self.change_zoom(new_zoom))
            zoomMenu.addAction(newAct)

        for zoom in self.zoom_list:
            add_zoom_to_menu(zoom)

    ####################################################################################
    # ------------------------ MOUSE DRAGGING PART -------------------------------------
    ####################################################################################
    def mousePressEvent(self, event):
        # TODO to fix
        if hasattr(self, 'img_name'):
            rect = list(
                map(lambda x: x * self.zoom_list[self.zoom_no],
                    self.full_img.size))
            self.first_x = max(0, min(int(rect[0]), event.x() + self.last_x))
            self.first_y = max(0, min(int(rect[1]), event.y() + self.last_y))
            print("event ", event.x(), event.y())
            print("last ", self.last_x, self.last_y)
            print("press offset ", self.first_x, self.first_y)

    def mouseMoveEvent(self, event):
        if hasattr(self, 'img_name'):
            self.v_bar = self.main_layout.left_scroll_area.verticalScrollBar()
            self.h_bar = self.main_layout.left_scroll_area.horizontalScrollBar(
            )
            rect = list(
                map(lambda x: x * self.zoom_list[self.zoom_no],
                    self.full_img.size))
            if self.main_layout.width() < rect[0]:
                x = self.first_x - event.x()
                y = self.first_y - event.y()
                self.last_x = x
                self.last_y = y
                print("\n\nDRAG OFFSET:", x, y)
                self.main_layout.set_offset(x, y)

    ####################################################################################
    # ------------------------ WHEEL PART ----------------------------------------------
    ####################################################################################
    #   mouse wheel event scrollо
    def wheelEvent(self, event):
        if hasattr(self, 'img_name'):
            modifiers = QApplication.keyboardModifiers()
            if modifiers == QtCore.Qt.ControlModifier:
                if event.angleDelta().y() > 0:
                    if self.zoom_no < len(self.zoom_list) - 1:
                        self.zoom_no += 1
                else:
                    if self.zoom_no > 0: self.zoom_no -= 1
                self.change_zoom(self.zoom_list[self.zoom_no])
                self.move_by_cursor()

    def move_by_cursor(self):
        cursor_x = QtGui.QCursor.pos().x()
        cursor_y = QtGui.QCursor.pos().y()

        window_width = self.main_layout.width()
        window_height = self.main_layout.height()

        rect = list(
            map(lambda x: x * self.zoom_list[self.zoom_no],
                self.full_img.size))
        real_image_width = int(rect[0])
        real_image_height = int(rect[1])
        print("x coor ", cursor_x, window_width, real_image_width)
        if (real_image_width < window_width | real_image_height <
                window_height):
            print("nothing to move")
        else:
            koef_x = (cursor_x) / real_image_width
            koef_y = (cursor_y) / real_image_height

            offset_x = (real_image_width - window_width) * koef_x
            offset_y = (real_image_height - window_height) * koef_y

            # TODO famous math constant 4 and 2
            x = int(offset_x * 4)
            y = int(offset_y * 2)

            print("\n\nZOOM OFFSET:", x, y)
            self.main_layout.set_offset(x, y)

            # TODO maybe someday zoom will work
            # self.last_x = x
            # self.last_y = y

    ####################################################################################
    # ------------------------ ZOOM PART -----------------------------------------------
    ####################################################################################
    def change_zoom(self, new_zoom):
        self.zoom = new_zoom
        print('new zoom = %d' % self.zoom)
        self.update_main_layout()

    def _init_images(self):
        def get_marked_indexes():
            marked_indexes = []
            pref_path = self.img_path.split('.')[0].split('/')[-1]
            if pref_path in list(
                    map(lambda repeat_file: repeat_file.split('.')[0],
                        self.already_marked_list)):
                with open("%s/%s.json" %
                          (self.already_marked_dir, pref_path)) as repeat_fp:
                    x_repeated = np.array(json.load(repeat_fp)['x_data'],
                                          dtype='uint8')
                    mae_threshold = 1.2  # experimental
                    for i, x in enumerate(self.x_data_full['x_data']):
                        for rep_i, rep_x in enumerate(x_repeated):
                            mae = abs((x - rep_x).astype('int8')).mean()
                            if mae < mae_threshold:
                                print('%d->%d:mae = %.3f' % (rep_i, i, mae))
                                marked_indexes.append(i)
                                break

                    if len(marked_indexes) != len(x_repeated):
                        raise Exception('bad threshold')
            return marked_indexes

        self.pre_rendered_img_dict = {}
        QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor))

        print("rendering image...")
        self.x_data_full, self.full_img = \
            dmk.get_x_from_croped_img(
                path_to_img=self.img_path,
                window_shape=self.window_shape,
                step=1.0,
                verbose=True
            )
        print("ok")

        self.marked_indexes = get_marked_indexes()
        QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
        print("ok")

    def _init_label_list(self):
        self.label_list = []
        for i, x in enumerate(self.x_data_full['x_data']):
            if i in self.marked_indexes:
                img_data = x * 10
            else:
                img_data = x

            self.label_list.append(
                MergedTrainExLabel(x_data=img_data,
                                   classes=self.classes,
                                   label_size=self.default_label_size))

    ##############################################################
    # ---------------- gui logic stuff ---------------------------
    ##############################################################
    def clear(self):
        self.main_layout.clear()

    def update_main_layout(self):
        self.clear()

        for label in self.label_list:
            label.updateImage(label_size=list(
                map(lambda x: x * self.zoom, self.default_label_size)))

        self.main_layout.update_grid(
            windows_width=self.main_layout.max_width,
            window_height=self.main_layout.max_height,
            x_len=int(self.full_img.size[0] /
                      self.x_data_full["x_data"].shape[1]),
            y_len=int(self.full_img.size[1] /
                      self.x_data_full["x_data"].shape[2]),
            label_list=self.label_list)

        print("img_size = %s\nex_num = %d\n" %
              (str(self.full_img.size), len(self.x_data_full['x_data'])))

    def okay_pressed(self):

        y_data = np.empty(0)
        for class_name in self.classes.keys():
            for sub_class_name in self.classes[class_name]:
                self.classes[class_name][sub_class_name]['num'] = 0

        # Now we're going to store only examples of diseased plants
        x_data_full = {
            'x_data': np.empty(0, dtype='uint8'),
            'x_coord': [],
            'longitudes': [],
            'latitudes': []
        }

        ex_num = 0
        for x, label in zip(self.x_data_full['x_data'],
                            self.main_layout.label_list):
            if label.class_name is not None:
                x_data_full['x_data'] = np.append(x_data_full['x_data'], x)
                y_data = np.append(
                    y_data, self.classes[label.class_name][
                        label.sub_class_name]['value'])
                self.classes[label.class_name][
                    label.sub_class_name]['num'] += 1
                ex_num += 1

        x_data_full['x_data'].shape = (ex_num, *self.window_shape)
        y_data.shape = (len(x_data_full['x_data']), 1)

        dmk.json_train_create(path="%s.json" % self.img_name,
                              x_data_full=x_data_full,
                              y_data=y_data,
                              img_shape=self.full_img.size,
                              classes=self.classes)

        print("OKAY")

        self.choose_and_render_image()
Esempio n. 7
0
class WindowShowPredictions(WindowInterface):
    ##############################################################
    # ---------------- init stuff --------------------------------
    ##############################################################
    def __init__(self, x_data, y_data, y_predicted, classes):
        super(WindowShowPredictions, self).__init__()

        config_dict = self.load_dict_from_json_with_keys(
            key_list=['qt_label_size'])
        self.label_size = config_dict['qt_label_size']

        self.x_data = x_data
        self.y_data = y_data
        self.y_predicted = y_predicted
        self.classes = classes

        self._define_max_key_len()

        self.main_layout = MyGridWidget(hbox_control=self.hbox_control)
        self.setCentralWidget(self.main_layout)
        self.showFullScreen()
        self.update_main_layout()

    def _init_hbox_control(self):
        self.hbox_control = QtWidgets.QHBoxLayout()
        self.hbox_control.addStretch(1)
        self.hbox_control.addWidget(
            ControlButton("Update", self.update_main_layout))
        self.hbox_control.addWidget(ControlButton("Quit", self.quit_default))

    def _define_max_key_len(self):
        self.max_key_len = 0
        for key, value in self.classes.items():
            if len(key) > self.max_key_len:
                self.max_key_len = len(key)

    ##############################################################
    # ---------------- gui logic stuff ---------------------------
    ##############################################################
    def clear(self):
        self.main_layout.clear()

    def update_main_layout(self):
        self.clear()

        def get_key_by_answer(pos_code):
            answer = {'mae': 9999, 'key': None, 'value': 0}
            for key in self.classes.keys():
                mae = np.average(abs((self.classes[key]['value'] - pos_code)))
                if mae < answer['mae']:
                    answer['mae'] = mae
                    answer['key'] = key
                    answer['value'] = max(pos_code)
            return answer

        def add_spaces(word, new_size):  # TODO fix gui label alignment
            while len(word) < new_size:
                word += '_'
            return word

        label_list = []
        for x, y, y_answer in zip(self.x_data, self.y_data, self.y_predicted):
            answer = get_key_by_answer(pos_code=y_answer)

            right_ans = get_key_by_answer(pos_code=y)

            is_right_ans = True if answer['key'] == right_ans['key'] else False

            answer['key'] = add_spaces(answer['key'],
                                       new_size=self.max_key_len)

            label_list.append(
                ImageTextLabel(x=x,
                               text='%s %.2f' %
                               (answer['key'], answer['value']),
                               label_size=self.label_size))

            if is_right_ans:
                label_list[-1].text_label.setStyleSheet(
                    'background-color: green')
            else:
                label_list[-1].text_label.setStyleSheet(
                    'background-color: red')

        rect_len = int(np.sqrt(len(self.x_data)))
        self.main_layout.update_grid(
            windows_width=self.frameGeometry().width(),
            window_height=self.frameGeometry().height(),
            x_len=rect_len,
            y_len=rect_len,
            label_list=label_list)
Esempio n. 8
0
class WindowPredictOnImage(WindowInterface):
    ##############################################################
    # ---------------- init stuff --------------------------------
    ##############################################################
    def __init__(self):
        super(WindowPredictOnImage, self).__init__()
        with open(os.path.abspath('config_full_system.json')) as config_fp:
            self.config_dict = json.load(config_fp)

            # load layers
            self.clusterer = get_clusterer_by_name(
                self.config_dict['clusterer']['name'],
                self.config_dict['clusterer']['args'])
            if self.config_dict['preprocessor']['use']:
                self.segmentator = get_preprocessor_by_name(
                    self.config_dict['preprocessor']['name'],
                    self.config_dict['preprocessor']['args'])
            self.classifier = get_classifier_by_name(
                self.config_dict['classifier']['name'],
                self.config_dict['classifier']['args'])
            self.bad_key = self.config_dict['classifier']['bad_key']

            self._define_max_key_len()
            self._parse_image()

            self.main_layout = MyGridWidget(hbox_control=self.hbox_control)
            self.pbar = QProgressBar(self)
            self.main_layout.layout.addWidget(self.pbar)
            self.right_text_labels = []

            self.setCentralWidget(self.main_layout)
            self.showFullScreen()
            self.update_main_layout()

    def _init_hbox_control(self):
        self.hbox_control = QtWidgets.QHBoxLayout()
        self.hbox_control.addStretch(1)
        self.hbox_control.addWidget(
            ControlButton("Predict", self.update_main_layout))
        self.hbox_control.addWidget(
            ControlButton("Choose model", self.choose_NN))
        self.hbox_control.addWidget(
            ControlButton("Choose image", self._parse_image))
        self.hbox_control.addWidget(ControlButton("Quit", self.quit_default))

    def _parse_image(self):
        self.picture_path = self.choose_picture()
        x_cropped = self.clusterer.cluster(self.picture_path)
        self.x_data = x_cropped['x_data']

    def _define_max_key_len(self):
        self.max_key_len = 0
        for key, value in self.classifier.classes.items():
            if len(key) > self.max_key_len:
                self.max_key_len = len(key)

    def clear(self):
        self.main_layout.clear()
        for text_label in self.right_text_labels:
            text_label.setParent(None)

    def update_main_layout(self):
        self.clear()

        self.predict_thread = PredictThread(self)
        fake_timer = FakeTimer(self)
        fake_timer.valueChanged.connect(self.predict_thread.valueChanged.emit)

        self.predict_thread.valueChanged.connect(self.pbar.setValue)
        self.predict_thread.canDraw.connect(self.draw_result)
        self.predict_thread.fakeTimerToStop.connect(fake_timer.terminate)

        self.main_layout.update_scroll(
            windows_width=self.frameGeometry().width(),
            window_height=self.frameGeometry().height(),
        )

        # self.x_data = self.x_data[:4]
        self.predict_thread.start()
        fake_timer.start()

    def draw_result(self):
        def get_key_by_answer(pos_code, bad_key):
            answer = {'mae': 9999, 'key': bad_key, 'value': 0}
            if sum(pos_code) > 0:
                for key in self.classifier.classes.keys():
                    mae = np.average(
                        abs((self.classifier.classes[key]['value'] -
                             pos_code)))
                    if mae < answer['mae']:
                        answer['mae'] = mae
                        answer['key'] = key
                        answer['value'] = max(pos_code)
            return answer

        label_list = []

        classes_dict = self.classifier.classes.copy()
        classes_dict[self.bad_key] = {}
        for key in [*classes_dict.keys(), self.bad_key]:
            classes_dict[key]['num'] = 0
            classes_dict[key]['indexes'] = []

        for i, (x, y_answer) in enumerate(
                zip(self.x_data, self.predict_thread.y_answer)):
            answer = get_key_by_answer(pos_code=y_answer, bad_key=self.bad_key)

            classes_dict[answer['key']]['num'] += 1

            classes_dict[answer['key']]['indexes'].append(i)
            answer['key'] += (self.max_key_len - len(answer['key'])) * " "
            answer['key'] = "%d: %s" % (i, answer['key'])

            label_list.append(
                ImageTextLabel(
                    x=x,
                    text='%s %.2f' % (answer['key'], answer['value']),
                    label_size=self.config_dict['gui']['qt_label_size']))

        self.right_text_labels = []
        for key in classes_dict:
            text_label = QLabel()
            text_label.setText("%s: %d" % (key, classes_dict[key]['num']))
            text_label.setAlignment(QtCore.Qt.AlignLeft)
            print("%s: %s" % (key, str(classes_dict[key]['indexes'])))
            self.right_text_labels.append(text_label)
            self.main_layout.right_layout.addWidget(text_label)

        rect_len = int(np.sqrt(len(self.x_data)))
        self.main_layout.update_grid(
            windows_width=self.frameGeometry().width(),
            window_height=self.frameGeometry().height(),
            x_len=rect_len,
            y_len=rect_len,
            label_list=label_list)

    def choose_NN(self):
        self.weights_path = str(
            QtWidgets.QFileDialog.getOpenFileName(self,
                                                  "Open *.h5 with NN weights",
                                                  "models", "*.h5 *.H5")[0])
        self.structure_path = str(
            QtWidgets.QFileDialog.getOpenFileName(
                self, "Open *.json with NN structure", "models",
                "*.json *.JSON")[0])

        if os.path.isfile(self.weights_path) and os.path.isfile(
                self.structure_path):
            self.classifier = get_full_model(json_path=self.structure_path,
                                             h5_path=self.weights_path)
        else:
            print(
                "Files with model weights and model structure does't choosed")
Esempio n. 9
0
    def __init__(self, json_list):
        super(WindowMultipleExamples, self).__init__()
        self.postfix = 'joined'

        self.label_size = (224, 224)

        # TODO maybe will be restored someday
        # with open(self.choose_json(content_title='config augmentation data')) as aug_config_fp:
        with open('config_data_augmentation.json') as aug_config_fp:
            aug_config_dict = json.load(aug_config_fp)
            alghs_dict = aug_config_dict['algorithms']

            self.max_aug_part = aug_config_dict['aug_part']
            self.augment_all = aug_config_dict['augment_all']
            self.output_json = aug_config_dict['output_json']
            self.save_data_binary = aug_config_dict['save_data_to_binary']
            self.save_data_dir = aug_config_dict['save_data_to_dir']

            for key, value in alghs_dict.items():
                if value['use'] and len(
                        value['val_list']) != self.max_aug_part:
                    raise Exception('bad val_list size for %s' % key)

            self.arg_dict = {
                'use_noise': alghs_dict['noise']['use'],
                'intensity_noise_list': alghs_dict['noise']['val_list'],
                'use_deform': alghs_dict['deform']['use'],
                'k_deform_list': alghs_dict['deform']['val_list'],
                'use_blur': alghs_dict['blur']['use'],
                'rad_list': alghs_dict['blur']['val_list'],
                'use_affine': alghs_dict['affine']['use'],
                'affine_list': alghs_dict['affine']['val_list'],
                'use_contrast': alghs_dict['contrast']['use'],
                'contrast_list': alghs_dict['contrast']['val_list']
            }

        if json_list == None:
            raise Exception('No passed json')
        self.json_name = os.path.splitext(json_list[0])[0]

        if len(json_list) == 1:
            print('Parsing preprocessed json')
            self.classes, img_shape, self.x_data, self.y_data = \
                dmk.json_big_load(json_list[0])
            self.x_data = np.array(self.x_data, dtype='uint8')
            self.y_data = np.array(self.y_data, dtype='uint8')
        else:
            print('Parsing json list')
            self.classes, self.x_data, self.y_data = dmk.get_data_from_json_list(
                json_list=json_list,
                # remove_classes=None,
                # TODO some dev stuff
                remove_classes=[
                    'альтернариоз', 'прочие инфекции', 'морщинистая мозаика',
                    'полосатая мозаика'
                ])
        self.init_size = len(self.x_data)
        self.img_shape = self.x_data.shape[1:]
        # TODO some dev stuff
        # self.classes['здоровый куст'] = self.classes['марь белая']
        # del self.classes['марь белая']
        # self.classes['мозаика'] = self.classes['прочие мозаики']
        # del self.classes['прочие мозаики']
        # self.classes['сорняк'] = self.classes['прочие сорняки']
        # del self.classes['прочие сорняки']

        self._define_max_class()

        self.main_layout = MyGridWidget(hbox_control=self.hbox_control)
        self.setCentralWidget(self.main_layout)

        self.showFullScreen()
        self.show_full()

        print("---------------------------------")
        print('classes      = %s' % str(self.classes))
        print('max_classes  = %s' % str(self.max_aug_for_classes))
        print('ex_num = %d' %
              sum(map(lambda x: x['num'], self.classes.values())))
        print("---------------------------------")

        self.show_histogram(labels=list(self.classes.keys()),
                            values=list(
                                map(lambda val: val['num'],
                                    self.classes.values())))
Esempio n. 10
0
class WindowMultipleExamples(WindowInterface):
    ##############################################################
    # ---------------- init stuff --------------------------------
    ##############################################################
    def __init__(self, json_list):
        super(WindowMultipleExamples, self).__init__()
        self.postfix = 'joined'

        self.label_size = (224, 224)

        # TODO maybe will be restored someday
        # with open(self.choose_json(content_title='config augmentation data')) as aug_config_fp:
        with open('config_data_augmentation.json') as aug_config_fp:
            aug_config_dict = json.load(aug_config_fp)
            alghs_dict = aug_config_dict['algorithms']

            self.max_aug_part = aug_config_dict['aug_part']
            self.augment_all = aug_config_dict['augment_all']
            self.output_json = aug_config_dict['output_json']
            self.save_data_binary = aug_config_dict['save_data_to_binary']
            self.save_data_dir = aug_config_dict['save_data_to_dir']

            for key, value in alghs_dict.items():
                if value['use'] and len(
                        value['val_list']) != self.max_aug_part:
                    raise Exception('bad val_list size for %s' % key)

            self.arg_dict = {
                'use_noise': alghs_dict['noise']['use'],
                'intensity_noise_list': alghs_dict['noise']['val_list'],
                'use_deform': alghs_dict['deform']['use'],
                'k_deform_list': alghs_dict['deform']['val_list'],
                'use_blur': alghs_dict['blur']['use'],
                'rad_list': alghs_dict['blur']['val_list'],
                'use_affine': alghs_dict['affine']['use'],
                'affine_list': alghs_dict['affine']['val_list'],
                'use_contrast': alghs_dict['contrast']['use'],
                'contrast_list': alghs_dict['contrast']['val_list']
            }

        if json_list == None:
            raise Exception('No passed json')
        self.json_name = os.path.splitext(json_list[0])[0]

        if len(json_list) == 1:
            print('Parsing preprocessed json')
            self.classes, img_shape, self.x_data, self.y_data = \
                dmk.json_big_load(json_list[0])
            self.x_data = np.array(self.x_data, dtype='uint8')
            self.y_data = np.array(self.y_data, dtype='uint8')
        else:
            print('Parsing json list')
            self.classes, self.x_data, self.y_data = dmk.get_data_from_json_list(
                json_list=json_list,
                # remove_classes=None,
                # TODO some dev stuff
                remove_classes=[
                    'альтернариоз', 'прочие инфекции', 'морщинистая мозаика',
                    'полосатая мозаика'
                ])
        self.init_size = len(self.x_data)
        self.img_shape = self.x_data.shape[1:]
        # TODO some dev stuff
        # self.classes['здоровый куст'] = self.classes['марь белая']
        # del self.classes['марь белая']
        # self.classes['мозаика'] = self.classes['прочие мозаики']
        # del self.classes['прочие мозаики']
        # self.classes['сорняк'] = self.classes['прочие сорняки']
        # del self.classes['прочие сорняки']

        self._define_max_class()

        self.main_layout = MyGridWidget(hbox_control=self.hbox_control)
        self.setCentralWidget(self.main_layout)

        self.showFullScreen()
        self.show_full()

        print("---------------------------------")
        print('classes      = %s' % str(self.classes))
        print('max_classes  = %s' % str(self.max_aug_for_classes))
        print('ex_num = %d' %
              sum(map(lambda x: x['num'], self.classes.values())))
        print("---------------------------------")

        self.show_histogram(labels=list(self.classes.keys()),
                            values=list(
                                map(lambda val: val['num'],
                                    self.classes.values())))

    def _init_hbox_control(self):
        self.hbox_control = QtWidgets.QHBoxLayout()
        self.hbox_control.addStretch(1)
        self.hbox_control.addWidget(ControlButton("Okay", self.okay_pressed))
        self.hbox_control.addWidget(ControlButton("Show Full", self.show_full))
        self.hbox_control.addWidget(
            ControlButton("Multiple", self.multiple_pressed))
        self.hbox_control.addWidget(ControlButton("Quit", self.quit_default))

    def _define_max_class(self):
        self.max_class = {'name': None, 'num': 0, 'value': None}
        self.max_key_len = 0
        self.max_aug_for_classes = {}
        for key, value in self.classes.items():
            if self.classes[key]['num'] > self.max_class['num']:
                self.max_class['name'] = key
                self.max_class['num'] = self.classes[key]['num']
                self.max_class['value'] = self.classes[key]['value']
            if len(key) > self.max_key_len:
                self.max_key_len = len(key)

            self.max_aug_for_classes[key] = self.classes[key]['num'] \
                                            + int(self.classes[key]['num'] * self.max_aug_part)

    ##############################################################
    # ---------------- gui logic stuff ---------------------------
    ##############################################################
    def show_histogram(self, labels, values, title='Diseases distribution'):
        import matplotlib.pyplot as plt
        import numpy as np

        x = np.arange(len(labels))  # the label locations
        width = 0.35  # the width of the bars

        fig, ax = plt.subplots()
        rects1 = ax.bar(x - width / 2, values, width, label='Examples num')

        # Add some text for labels, title and custom x-axis tick labels, etc.
        ax.set_ylabel('Num')
        ax.set_title(title)
        ax.set_xticks(x)
        ax.set_xticklabels(labels)
        ax.legend()

        def autolabel(rects):
            """Attach a text label above each bar in *rects*, displaying its height."""
            for rect in rects:
                height = rect.get_height()
                ax.annotate(
                    '{}'.format(height),
                    xy=(rect.get_x() + rect.get_width() / 2, height),
                    xytext=(0, 3),  # 3 points vertical offset
                    textcoords="offset points",
                    ha='center',
                    va='bottom')

        autolabel(rects1)

        fig.tight_layout()

        plt.xticks(rotation=45)
        plt.show()

    def clear(self):
        self.main_layout.clear()

    def show_full(self):
        self.clear()

        def get_key_by_value(value):
            for key in self.classes.keys():
                if (self.classes[key]['value'] == value).all():
                    return key
            raise Exception('No value == %s' % str(value))

        label_list = []
        for x, y in zip(self.x_data, self.y_data):
            label_text = get_key_by_value(value=y)
            label_text += (self.max_key_len - len(label_text)) * " "
            label_list.append(
                ImageTextLabel(x=x,
                               text=label_text,
                               label_size=self.label_size))
        rect_len = int(np.sqrt(len(self.x_data)))
        self.main_layout.update_grid(windows_width=self.main_layout.max_width,
                                     window_height=self.main_layout.max_height,
                                     x_len=rect_len,
                                     y_len=rect_len,
                                     label_list=label_list)

    def okay_pressed(self):
        print("Save to %s" % self.output_json)

        for key in self.classes.keys():
            self.classes[key]['value'] = list(
                self.classes[key]['value'].flatten())

        if self.save_data_binary:
            ###################################################################################
            # ------------------------ be aware of SIGKILL ------------------------------------
            ###################################################################################
            binary_path = dir_path = "/".join(self.output_json.split('/')[:-1]) + "/" \
                                     + self.output_json.split('/')[-1][:-5] + ".hd5f"
            dmk.json_big_create(json_path=self.output_json,
                                h5_path=binary_path,
                                x_data=self.x_data,
                                y_data=self.y_data,
                                longitudes=None,
                                latitudes=None,
                                img_shape=None,
                                classes=self.classes)
        elif self.save_data_dir:
            ###################################################################################
            # we can not pass array with size 10_000 * 256 * 256 * 3 to function, shout SIGKILL
            ###################################################################################
            dir_path = "/".join(self.output_json.split('/')[:-1]) \
                       + "/" + self.output_json.split('/')[-1][:-5]

            id = []
            label = []

            if not dir_path:
                raise Exception("Data directory %s need to be existed" %
                                dir_path)

            for key in self.classes.keys():
                self.classes[key]['value_num'] = dmk.get_num_from_pos(
                    self.classes[key]['value'])
                self.classes[key]['saved_num'] = 0
            for i, (x, y) in enumerate(zip(self.x_data, self.y_data)):
                for key in self.classes.keys():
                    if (self.classes[key]['value'] == y).all():
                        file_path = "%s/%d.JPG" % (dir_path, i + 1)
                        Image.fromarray(x).save(file_path)
                        print("%s saved" % file_path)
                        id.append(file_path)
                        label.append(key)

            with open(self.output_json, "w") as fp:
                json.dump(
                    {
                        "classes": self.classes,
                        "img_shape": None,
                        "dir_path": dir_path,
                        "longitudes": None,
                        "latitudes": None,
                        "dataframe": {
                            "id": id,
                            "label": label
                        }
                    }, fp)
                fp.close()

        self.quit_default()

    def multiple_pressed(self):

        if self.augment_all:
            if sum(map(lambda x: x['num'], self.classes.values())
                   ) < self.init_size * self.max_aug_part:
                # ----------------------------------- augment all -----------------------------------------------------
                old_class_size = len(self.x_data)
                x_data_new, y_data_new = dmk.multiple_class_examples(
                    x_train=self.x_data[:self.init_size],
                    y_train=self.y_data[:self.init_size],
                    **self.arg_dict,
                    max_class_num=self.init_size * self.max_aug_part,
                    mode='all')

                self.x_data = np.append(self.x_data, x_data_new)
                self.y_data = np.append(self.y_data, y_data_new)

                ex_num = int(self.y_data.shape[0] / len(self.classes))

                self.x_data.shape = (ex_num, *self.img_shape)
                self.y_data.shape = (ex_num, len(self.classes))

                for key, value in self.classes.items():
                    new_ex_num = len(self.x_data) - old_class_size
                    print('%s : generated %d new examples' % (key, new_ex_num))
                    self.classes[key]['num'] = 0
                    for y in self.y_data:
                        if ((y.__eq__(self.classes[key]['value'])).all()):
                            self.classes[key]['num'] += 1
            else:
                print('ex_num = max_num')

        else:
            # ----------------------------------- augment by classes ---------------------------------------------
            for key, value in self.classes.items():

                if self.classes[key]['num'] < self.max_aug_for_classes[key]:

                    max_class_num = self.max_aug_for_classes[key]
                    old_class_size = len(self.x_data)

                    x_data_new, y_data_new = dmk.multiple_class_examples(
                        x_train=self.x_data[:self.init_size],
                        y_train=self.y_data[:self.init_size],
                        class_for_mult=self.classes[key]['value'],
                        **self.arg_dict,
                        max_class_num=max_class_num)

                    self.x_data = np.append(self.x_data, x_data_new)
                    self.y_data = np.append(self.y_data, y_data_new)

                    ex_num = int(self.y_data.shape[0] / len(self.classes))

                    self.x_data.shape = (ex_num, *self.img_shape)
                    self.y_data.shape = (ex_num, len(self.classes))

                    new_ex_num = len(self.x_data) - old_class_size
                    print('%s : generated %d new examples' % (key, new_ex_num))
                    self.classes[key]['num'] = 0
                    for y in self.y_data:
                        if ((y.__eq__(self.classes[key]['value'])).all()):
                            self.classes[key]['num'] += 1

                else:
                    print(
                        '%s : generated %d new examples (class_size == max_size)'
                        % (key, 0))

        print("---------------------------------")
        print('classes = %s' % str(self.classes))
        print('ex_num = %d' %
              sum(map(lambda x: x['num'], self.classes.values())))
        print("---------------------------------")

        self.show_histogram(labels=list(self.classes.keys()),
                            values=list(
                                map(lambda val: val['num'],
                                    self.classes.values())),
                            title='Diseases distribution after augmentation')

        self.show_augmentation()

    def show_augmentation(self):
        self.clear()

        label_list = []

        for i in [0, 1, 2]:
            label_list.append(
                ImageTextLabel(x=self.x_data[i],
                               text='original',
                               label_size=self.label_size))
            for j in range(1, int(self.max_aug_part) + 1):
                label_text = 'aug %.2f' % self.arg_dict['contrast_list'][j - 1]
                label_list.append(
                    ImageTextLabel(x=self.x_data[i + j * self.init_size],
                                   text=label_text,
                                   label_size=self.label_size), )

        x_len = j + 1
        y_len = int(len(label_list) / x_len)
        self.main_layout.update_grid(windows_width=self.main_layout.max_width,
                                     window_height=self.main_layout.max_height,
                                     x_len=x_len,
                                     y_len=y_len,
                                     label_list=label_list)