Example #1
0
class ParamSlider(QWidget):
    valueChanged = Signal(int)

    def __init__(self, interval, ticks=10, reset=0, suffix=None, label=None, bold=False, special=None, parent=None):
        super(ParamSlider, self).__init__(parent)

        self.slider = QSlider(Qt.Horizontal)
        self.slider.setRange(interval[0], interval[1])
        self.slider.setTickPosition(QSlider.TicksBelow)
        self.slider.setTickInterval((interval[1] - interval[0] + 1) / ticks)
        self.slider.setSingleStep(1)
        self.slider.setPageStep(1)
        self.slider.setValue(reset)
        self.slider.mouseDoubleClickEvent = self.doubleClicked

        self.spin = QSpinBox()
        self.spin.setRange(interval[0], interval[1])
        self.spin.setValue(reset)
        self.spin.setSuffix(suffix)
        self.spin.setFixedWidth(55)
        self.spin.setSpecialValueText(special)

        self.reset = reset
        self.slider.valueChanged.connect(self.spin.setValue)
        self.spin.valueChanged.connect(self.slider.setValue)
        self.slider.valueChanged.connect(self.valueChanged)

        layout = QHBoxLayout()
        if label is not None:
            lab = QLabel(label)
            modify_font(lab, bold=bold)
            layout.addWidget(lab)
        layout.addWidget(self.slider)
        layout.addWidget(self.spin)
        self.setLayout(layout)

    def doubleClicked(self, _):
        self.reset_value()

    def reset_value(self):
        self.slider.setValue(self.reset)
        self.spin.setValue(self.reset)

    def value(self):
        return self.slider.value()

    def setValue(self, value):
        self.spin.setValue(value)
        self.slider.setValue(value)
        self.valueChanged.emit(value)

    def sync(self):
        self.spin.setValue(self.slider.value())
        self.slider.setValue(self.spin.value())
        self.valueChanged.emit(self.slider.value())
Example #2
0
class FrequencyWidget(ToolWidget):
    def __init__(self, image, parent=None):
        super(FrequencyWidget, self).__init__(parent)

        self.split_spin = QSpinBox()
        self.split_spin.setRange(0, 100)
        self.split_spin.setValue(15)
        self.split_spin.setSuffix(self.tr(" %"))

        self.smooth_spin = QSpinBox()
        self.smooth_spin.setRange(0, 100)
        self.smooth_spin.setValue(25)
        self.smooth_spin.setSuffix(self.tr(" %"))
        self.smooth_spin.setSpecialValueText(self.tr("Off"))

        self.thr_spin = QSpinBox()
        self.thr_spin.setRange(0, 100)
        self.thr_spin.setValue(0)
        self.thr_spin.setSuffix(self.tr(" %"))
        self.thr_spin.setSpecialValueText(self.tr("Off"))

        self.zero_label = QLabel()
        modify_font(self.zero_label, italic=True)

        self.filter_spin = QSpinBox()
        self.filter_spin.setRange(0, 15)
        self.filter_spin.setValue(0)
        self.filter_spin.setSuffix(self.tr(" px"))
        self.filter_spin.setSpecialValueText(self.tr("Off"))

        self.split_spin.valueChanged.connect(self.process)
        self.smooth_spin.valueChanged.connect(self.process)
        self.thr_spin.valueChanged.connect(self.process)
        self.filter_spin.valueChanged.connect(self.postprocess)

        self.image = image
        gray = cv.cvtColor(self.image, cv.COLOR_BGR2GRAY)
        rows, cols = gray.shape
        height = cv.getOptimalDFTSize(rows)
        width = cv.getOptimalDFTSize(cols)
        padded = cv.copyMakeBorder(gray, 0, height - rows, 0, width - cols, cv.BORDER_CONSTANT)
        self.dft = np.fft.fftshift(cv.dft(padded.astype(np.float32), flags=cv.DFT_COMPLEX_OUTPUT))
        self.magnitude0, self.phase0 = cv.cartToPolar(self.dft[:, :, 0], self.dft[:, :, 1])
        self.magnitude0 = cv.normalize(cv.log(self.magnitude0), None, 0, 255, cv.NORM_MINMAX)
        self.phase0 = cv.normalize(self.phase0, None, 0, 255, cv.NORM_MINMAX)
        self.magnitude = self.phase = None

        self.low_viewer = ImageViewer(self.image, self.image, self.tr("Low frequency"), export=True)
        self.high_viewer = ImageViewer(self.image, self.image, self.tr("High frequency"), export=True)
        self.mag_viewer = ImageViewer(self.image, None, self.tr("DFT Magnitude"), export=True)
        self.phase_viewer = ImageViewer(self.image, None, self.tr("DFT Phase"), export=True)
        self.process()

        self.low_viewer.viewChanged.connect(self.high_viewer.changeView)
        self.high_viewer.viewChanged.connect(self.low_viewer.changeView)
        self.mag_viewer.viewChanged.connect(self.phase_viewer.changeView)
        self.phase_viewer.viewChanged.connect(self.mag_viewer.changeView)

        top_layout = QHBoxLayout()
        top_layout.addWidget(QLabel(self.tr("Separation:")))
        top_layout.addWidget(self.split_spin)
        top_layout.addWidget(QLabel(self.tr("Smooth:")))
        top_layout.addWidget(self.smooth_spin)
        top_layout.addWidget(QLabel(self.tr("Threshold:")))
        top_layout.addWidget(self.thr_spin)
        top_layout.addWidget(QLabel(self.tr("Filter:")))
        top_layout.addWidget(self.filter_spin)
        top_layout.addWidget(self.zero_label)
        top_layout.addStretch()

        center_layout = QGridLayout()
        center_layout.addWidget(self.low_viewer, 0, 0)
        center_layout.addWidget(self.high_viewer, 0, 1)
        center_layout.addWidget(self.mag_viewer, 1, 0)
        center_layout.addWidget(self.phase_viewer, 1, 1)

        main_layout = QVBoxLayout()
        main_layout.addLayout(top_layout)
        main_layout.addLayout(center_layout)
        self.setLayout(main_layout)

    def process(self):
        start = time()
        rows, cols, _ = self.dft.shape
        mask = np.zeros((rows, cols), np.float32)
        half = np.sqrt(rows ** 2 + cols ** 2) / 2
        radius = int(half * self.split_spin.value() / 100)
        mask = cv.circle(mask, (cols // 2, rows // 2), radius, 1, cv.FILLED)
        kernel = 2 * int(half * self.smooth_spin.value() / 100) + 1
        mask = cv.GaussianBlur(mask, (kernel, kernel), 0)
        mask /= np.max(mask)
        threshold = int(self.thr_spin.value() / 100 * 255)
        if threshold > 0:
            mask[self.magnitude0 < threshold] = 0
            zeros = (mask.size - np.count_nonzero(mask)) / mask.size * 100
        else:
            zeros = 0
        self.zero_label.setText(self.tr("(zeroed coefficients = {:.2f}%)").format(zeros))
        mask2 = np.repeat(mask[:, :, np.newaxis], 2, axis=2)

        rows0, cols0, _ = self.image.shape
        low = cv.idft(np.fft.ifftshift(self.dft * mask2), flags=cv.DFT_SCALE)
        low = norm_mat(cv.magnitude(low[:, :, 0], low[:, :, 1])[:rows0, :cols0], to_bgr=True)
        self.low_viewer.update_processed(low)
        high = cv.idft(np.fft.ifftshift(self.dft * (1 - mask2)), flags=cv.DFT_SCALE)
        high = norm_mat(cv.magnitude(high[:, :, 0], high[:, :, 1]), to_bgr=True)
        self.high_viewer.update_processed(np.copy(high[: self.image.shape[0], : self.image.shape[1]]))
        self.magnitude = (self.magnitude0 * mask).astype(np.uint8)
        self.phase = (self.phase0 * mask).astype(np.uint8)
        self.postprocess()
        self.info_message.emit(self.tr(f"Frequency Split = {elapsed_time(start)}"))

    def postprocess(self):
        kernel = 2 * self.filter_spin.value() + 1
        if kernel >= 3:
            magnitude = cv.GaussianBlur(self.magnitude, (kernel, kernel), 0)
            phase = cv.GaussianBlur(self.phase, (kernel, kernel), 0)
            # phase = cv.medianBlur(self.phase, kernel)
        else:
            magnitude = self.magnitude
            phase = self.phase
        self.mag_viewer.update_original(cv.cvtColor(magnitude, cv.COLOR_GRAY2BGR))
        self.phase_viewer.update_original(cv.cvtColor(phase, cv.COLOR_GRAY2BGR))
Example #3
0
class FrequencyWidget(ToolWidget):
    def __init__(self, image, parent=None):
        super(FrequencyWidget, self).__init__(parent)

        self.ampl_radio = QRadioButton(self.tr('Amplitude'))
        self.ampl_radio.setChecked(True)
        self.phase_radio = QRadioButton(self.tr('Phase'))
        self.dct_radio = QRadioButton(self.tr('DCT Map'))
        self.last_radio = self.ampl_radio
        self.thr_spin = QSpinBox()
        self.thr_spin.setRange(0, 255)
        self.thr_spin.setSpecialValueText(self.tr('Off'))
        self.ratio_label = QLabel()
        self.filter_check = QCheckBox(self.tr('Filter'))

        self.ampl_radio.clicked.connect(self.process)
        self.phase_radio.clicked.connect(self.process)
        self.dct_radio.clicked.connect(self.process)
        self.thr_spin.valueChanged.connect(self.process)
        self.filter_check.stateChanged.connect(self.process)

        gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
        rows, cols = gray.shape
        height = cv.getOptimalDFTSize(rows)
        width = cv.getOptimalDFTSize(cols)
        padded = cv.copyMakeBorder(gray, 0, height - rows, 0, width - cols,
                                   cv.BORDER_CONSTANT).astype(np.float32)
        planes = cv.merge([padded, np.zeros_like(padded)])
        dft = cv.split(np.fft.fftshift(cv.dft(planes)))
        mag, phase = cv.cartToPolar(dft[0], dft[1])
        dct = cv.dct(padded)
        self.result = [
            normalize_mat(img)
            for img in [cv.log(mag), phase, cv.log(dct)]
        ]

        self.image = image
        self.viewer = ImageViewer(self.image, None)
        self.process()

        top_layout = QHBoxLayout()
        top_layout.addWidget(QLabel(self.tr('Coefficients:')))
        top_layout.addWidget(self.ampl_radio)
        top_layout.addWidget(self.phase_radio)
        top_layout.addWidget(self.dct_radio)
        top_layout.addWidget(self.filter_check)
        top_layout.addStretch()
        top_layout.addWidget(QLabel(self.tr('Threshold:')))
        top_layout.addWidget(self.thr_spin)
        top_layout.addWidget(self.ratio_label)

        main_layout = QVBoxLayout()
        main_layout.addLayout(top_layout)
        main_layout.addWidget(self.viewer)
        self.setLayout(main_layout)

    def process(self):
        if self.ampl_radio.isChecked():
            output = self.result[0]
            self.last_radio = self.ampl_radio
        elif self.phase_radio.isChecked():
            output = self.result[1]
            self.last_radio = self.phase_radio
        elif self.dct_radio.isChecked():
            output = self.result[2]
            self.last_radio = self.dct_radio
        else:
            self.last_radio.setChecked(True)
            return
        if self.filter_check.isChecked():
            output = cv.medianBlur(output, 3)
        thr = self.thr_spin.value()
        if thr > 0:
            _, output = cv.threshold(output, thr, 0, cv.THRESH_TOZERO)
            zeros = (1.0 - cv.countNonZero(output) / output.size) * 100
        else:
            zeros = 0
        self.ratio_label.setText('(masked = {:.1f}%)'.format(zeros))
        self.viewer.update_original(cv.cvtColor(output, cv.COLOR_GRAY2BGR))
Example #4
0
class MinMaxWidget(ToolWidget):
    def __init__(self, image, parent=None):
        super(MinMaxWidget, self).__init__(parent)

        self.chan_combo = QComboBox()
        self.chan_combo.addItems([
            self.tr('Luminance'),
            self.tr('Red'),
            self.tr('Green'),
            self.tr('Blue'),
            self.tr('RGB Norm')
        ])

        colors = [
            self.tr('Red'),
            self.tr('Green'),
            self.tr('Blue'),
            self.tr('White'),
            self.tr('Black')
        ]

        self.min_combo = QComboBox()
        self.min_combo.addItems(colors)
        self.min_combo.setCurrentIndex(1)

        self.max_combo = QComboBox()
        self.max_combo.addItems(colors)
        self.max_combo.setCurrentIndex(0)

        self.filter_spin = QSpinBox()
        self.filter_spin.setRange(0, 5)
        self.filter_spin.setSpecialValueText(self.tr('off'))

        self.image = image
        self.viewer = ImageViewer(self.image, self.image)
        self.low = self.high = None
        self.preprocess()

        self.chan_combo.currentIndexChanged.connect(self.preprocess)
        self.min_combo.currentIndexChanged.connect(self.process)
        self.max_combo.currentIndexChanged.connect(self.process)
        self.filter_spin.valueChanged.connect(self.process)

        top_layout = QHBoxLayout()
        top_layout.addWidget(QLabel(self.tr('Channel:')))
        top_layout.addWidget(self.chan_combo)
        top_layout.addWidget(QLabel(self.tr('Minimum:')))
        top_layout.addWidget(self.min_combo)
        top_layout.addWidget(QLabel(self.tr('Maximum:')))
        top_layout.addWidget(self.max_combo)
        top_layout.addWidget(QLabel(self.tr('Filter:')))
        top_layout.addWidget(self.filter_spin)
        top_layout.addStretch()
        main_layout = QVBoxLayout()
        main_layout.addLayout(top_layout)
        main_layout.addWidget(self.viewer)
        self.setLayout(main_layout)

    @staticmethod
    def minmax_dev(patch, mask):
        c = patch[1, 1]
        minimum, maximum, _, _ = cv.minMaxLoc(patch, mask)
        if c < minimum:
            return -1
        if c > maximum:
            return +1
        return 0

    @staticmethod
    def blk_filter(img, radius):
        result = np.zeros_like(img, np.float32)
        rows, cols = result.shape
        block = 2 * radius + 1
        for i in range(radius, rows, block):
            for j in range(radius, cols, block):
                result[i - radius:i + radius + 1, j - radius:j + radius +
                       1] = np.std(img[i - radius:i + radius + 1,
                                       j - radius:j + radius + 1])
        return cv.normalize(result, None, 0, 127, cv.NORM_MINMAX, cv.CV_8UC1)

    def preprocess(self):
        start = time()
        channel = self.chan_combo.currentIndex()
        if channel == 0:
            img = cv.cvtColor(self.image, cv.COLOR_BGR2GRAY)
        elif channel == 4:
            b, g, r = cv.split(self.image.astype(np.float64))
            img = cv.sqrt(cv.pow(b, 2) + cv.pow(g, 2) + cv.pow(r, 2))
        else:
            img = self.image[:, :, 3 - channel]
        kernel = 3
        border = kernel // 2
        shape = (img.shape[0] - kernel + 1, img.shape[1] - kernel + 1, kernel,
                 kernel)
        strides = 2 * img.strides
        patches = np.lib.stride_tricks.as_strided(img,
                                                  shape=shape,
                                                  strides=strides)
        patches = patches.reshape((-1, kernel, kernel))
        mask = np.full((kernel, kernel), 255, dtype=np.uint8)
        mask[border, border] = 0
        output = np.array([self.minmax_dev(patch, mask)
                           for patch in patches]).reshape(shape[:-2])
        output = cv.copyMakeBorder(output, border, border, border, border,
                                   cv.BORDER_CONSTANT)
        self.low = output == -1
        self.high = output == +1
        self.process()
        self.info_message.emit(
            self.tr('Min/Max Deviation = {}'.format(elapsed_time(start))))

    def process(self):
        minmax = np.zeros_like(self.image)
        minimum = self.min_combo.currentIndex()
        maximum = self.max_combo.currentIndex()
        radius = self.filter_spin.value()
        if radius > 0:
            start = time()
            radius += 2
            low = self.blk_filter(self.low, radius)
            high = self.blk_filter(self.high, radius)
            if minimum <= 2:
                minmax[:, :, 2 - minimum] = low
            else:
                minmax = low
            if maximum <= 2:
                minmax[:, :, 2 - maximum] += high
            else:
                # FIXME: minmax ha un solo canale quando si sceglie black come colore
                minmax += high
            minmax = normalize_mat(minmax)
            self.info_message.emit(
                self.tr('Min/Max Filter = {}'.format(elapsed_time(start))))
        else:
            if minimum == 0:
                minmax[self.low] = [0, 0, 255]
            elif minimum == 1:
                minmax[self.low] = [0, 255, 0]
            elif minimum == 2:
                minmax[self.low] = [255, 0, 0]
            elif minimum == 3:
                minmax[self.low] = [255, 255, 255]
            if maximum == 0:
                minmax[self.high] = [0, 0, 255]
            elif maximum == 1:
                minmax[self.high] = [0, 255, 0]
            elif maximum == 2:
                minmax[self.high] = [255, 0, 0]
            elif maximum == 3:
                minmax[self.high] = [255, 255, 255]
        self.viewer.update_processed(minmax)
Example #5
0
class MinMaxWidget(ToolWidget):
    def __init__(self, image, parent=None):
        super(MinMaxWidget, self).__init__(parent)

        self.chan_combo = QComboBox()
        self.chan_combo.addItems(
            [self.tr("Luminance"), self.tr("Red"), self.tr("Green"), self.tr("Blue"), self.tr("RGB Norm")]
        )
        colors = [self.tr("Red"), self.tr("Green"), self.tr("Blue"), self.tr("White"), self.tr("Black")]
        self.process_button = QPushButton(self.tr("Process"))

        self.min_combo = QComboBox()
        self.min_combo.addItems(colors)
        self.min_combo.setCurrentIndex(1)

        self.max_combo = QComboBox()
        self.max_combo.addItems(colors)
        self.max_combo.setCurrentIndex(0)

        self.filter_spin = QSpinBox()
        self.filter_spin.setRange(0, 5)
        self.filter_spin.setSpecialValueText(self.tr("Off"))

        self.image = image
        self.viewer = ImageViewer(self.image, self.image)
        self.low = self.high = None
        self.stopped = False
        self.change()

        self.process_button.clicked.connect(self.preprocess)
        self.chan_combo.currentIndexChanged.connect(self.change)
        self.min_combo.currentIndexChanged.connect(self.process)
        self.max_combo.currentIndexChanged.connect(self.process)
        self.filter_spin.valueChanged.connect(self.process)

        top_layout = QHBoxLayout()
        top_layout.addWidget(QLabel(self.tr("Channel:")))
        top_layout.addWidget(self.chan_combo)
        top_layout.addWidget(self.process_button)
        top_layout.addWidget(QLabel(self.tr("Minimum:")))
        top_layout.addWidget(self.min_combo)
        top_layout.addWidget(QLabel(self.tr("Maximum:")))
        top_layout.addWidget(self.max_combo)
        top_layout.addWidget(QLabel(self.tr("Filter:")))
        top_layout.addWidget(self.filter_spin)
        top_layout.addStretch()
        main_layout = QVBoxLayout()
        main_layout.addLayout(top_layout)
        main_layout.addWidget(self.viewer)
        self.setLayout(main_layout)

    @staticmethod
    def minmax_dev(patch, mask):
        c = patch[1, 1]
        minimum, maximum, _, _ = cv.minMaxLoc(patch, mask)
        if c < minimum:
            return -1
        if c > maximum:
            return +1
        return 0

    @staticmethod
    def blk_filter(img, radius):
        result = np.zeros_like(img, np.float32)
        rows, cols = result.shape
        block = 2 * radius + 1
        for i in range(radius, rows, block):
            for j in range(radius, cols, block):
                result[i - radius : i + radius + 1, j - radius : j + radius + 1] = np.std(
                    img[i - radius : i + radius + 1, j - radius : j + radius + 1]
                )
        return cv.normalize(result, None, 0, 127, cv.NORM_MINMAX, cv.CV_8UC1)

    def change(self):
        self.min_combo.setEnabled(False)
        self.max_combo.setEnabled(False)
        self.filter_spin.setEnabled(False)
        self.process_button.setEnabled(True)
        self.viewer.update_processed(self.image)

    def preprocess(self):
        start = time()
        channel = self.chan_combo.currentIndex()
        if channel == 0:
            img = cv.cvtColor(self.image, cv.COLOR_BGR2GRAY)
        elif channel == 4:
            b, g, r = cv.split(self.image.astype(np.float64))
            img = cv.sqrt(cv.pow(b, 2) + cv.pow(g, 2) + cv.pow(r, 2))
        else:
            img = self.image[:, :, 3 - channel]
        kernel = 3
        border = kernel // 2
        shape = (img.shape[0] - kernel + 1, img.shape[1] - kernel + 1, kernel, kernel)
        strides = 2 * img.strides
        patches = np.lib.stride_tricks.as_strided(img, shape=shape, strides=strides)
        patches = patches.reshape((-1, kernel, kernel))
        mask = np.full((kernel, kernel), 255, dtype=np.uint8)
        mask[border, border] = 0
        progress = QProgressDialog(
            self.tr("Computing deviation..."), self.tr("Cancel"), 0, shape[0] * shape[1] - 1, self
        )
        progress.canceled.connect(self.cancel)
        progress.setWindowModality(Qt.WindowModal)
        blocks = [0] * shape[0] * shape[1]
        for i, patch in enumerate(patches):
            blocks[i] = self.minmax_dev(patch, mask)
            progress.setValue(i)
            if self.stopped:
                self.stopped = False
                return
        output = np.array(blocks).reshape(shape[:-2])
        output = cv.copyMakeBorder(output, border, border, border, border, cv.BORDER_CONSTANT)
        self.low = output == -1
        self.high = output == +1
        self.min_combo.setEnabled(True)
        self.max_combo.setEnabled(True)
        self.filter_spin.setEnabled(True)
        self.process_button.setEnabled(False)
        self.process()
        self.info_message.emit(self.tr(f"Min/Max Deviation = {elapsed_time(start)}"))

    def cancel(self):
        self.stopped = True

    def process(self):
        minmax = np.zeros_like(self.image)
        minimum = self.min_combo.currentIndex()
        maximum = self.max_combo.currentIndex()
        radius = self.filter_spin.value()
        if radius > 0:
            start = time()
            radius += 3
            if minimum < 4:
                low = self.blk_filter(self.low, radius)
                if minimum <= 2:
                    minmax[:, :, 2 - minimum] = low
                else:
                    minmax = np.repeat(low[:, :, np.newaxis], 3, axis=2)
            if maximum < 4:
                high = self.blk_filter(self.high, radius)
                if maximum <= 2:
                    minmax[:, :, 2 - maximum] += high
                else:
                    minmax += np.repeat(high[:, :, np.newaxis], 3, axis=2)
            minmax = norm_mat(minmax)
            self.info_message.emit(self.tr(f"Min/Max Filter = {elapsed_time(start)}"))
        else:
            if minimum == 0:
                minmax[self.low] = [0, 0, 255]
            elif minimum == 1:
                minmax[self.low] = [0, 255, 0]
            elif minimum == 2:
                minmax[self.low] = [255, 0, 0]
            elif minimum == 3:
                minmax[self.low] = [255, 255, 255]
            if maximum == 0:
                minmax[self.high] = [0, 0, 255]
            elif maximum == 1:
                minmax[self.high] = [0, 255, 0]
            elif maximum == 2:
                minmax[self.high] = [255, 0, 0]
            elif maximum == 3:
                minmax[self.high] = [255, 255, 255]
        self.viewer.update_processed(minmax)
Example #6
0
class NoiseWidget(ToolWidget):
    def __init__(self, image, parent=None):
        super(NoiseWidget, self).__init__(parent)

        self.mode_combo = QComboBox()
        self.mode_combo.addItems([
            self.tr('Median'),
            self.tr('Gaussian'),
            self.tr('BoxBlur'),
            self.tr('Bilateral'),
            self.tr('NonLocal')
        ])

        self.radius_spin = QSpinBox()
        self.radius_spin.setRange(1, 10)
        self.radius_spin.setSuffix(self.tr(' px'))
        self.radius_spin.setValue(1)

        self.sigma_spin = QSpinBox()
        self.sigma_spin.setRange(1, 200)
        self.sigma_spin.setValue(3)

        self.levels_spin = QSpinBox()
        self.levels_spin.setRange(0, 255)
        self.levels_spin.setSpecialValueText(self.tr('Equalized'))
        self.levels_spin.setValue(32)

        self.gray_check = QCheckBox(self.tr('Grayscale'))
        self.denoised_check = QCheckBox(self.tr('Denoised'))

        self.image = image
        self.viewer = ImageViewer(self.image, self.image)
        self.process()

        params_layout = QHBoxLayout()
        params_layout.addWidget(QLabel(self.tr('Mode:')))
        params_layout.addWidget(self.mode_combo)
        params_layout.addWidget(QLabel(self.tr('Radius:')))
        params_layout.addWidget(self.radius_spin)
        params_layout.addWidget(QLabel(self.tr('Sigma:')))
        params_layout.addWidget(self.sigma_spin)
        params_layout.addWidget(QLabel(self.tr('Levels:')))
        params_layout.addWidget(self.levels_spin)
        params_layout.addWidget(self.gray_check)
        params_layout.addWidget(self.denoised_check)
        params_layout.addStretch()

        main_layout = QVBoxLayout()
        main_layout.addLayout(params_layout)
        main_layout.addWidget(self.viewer)
        self.setLayout(main_layout)

        self.mode_combo.currentTextChanged.connect(self.process)
        self.radius_spin.valueChanged.connect(self.process)
        self.sigma_spin.valueChanged.connect(self.process)
        self.levels_spin.valueChanged.connect(self.process)
        self.gray_check.stateChanged.connect(self.process)
        self.denoised_check.stateChanged.connect(self.process)

    def process(self):
        start = time()
        grayscale = self.gray_check.isChecked()
        if grayscale:
            original = cv.cvtColor(self.image, cv.COLOR_BGR2GRAY)
        else:
            original = self.image
        radius = self.radius_spin.value()
        kernel = radius * 2 + 1
        sigma = self.sigma_spin.value()
        choice = self.mode_combo.currentText()
        if choice == self.tr('Median'):
            self.sigma_spin.setEnabled(False)
            denoised = cv.medianBlur(original, kernel)
        elif choice == self.tr('Gaussian'):
            self.sigma_spin.setEnabled(False)
            denoised = cv.GaussianBlur(original, (kernel, kernel), 0)
        elif choice == self.tr('BoxBlur'):
            self.sigma_spin.setEnabled(False)
            denoised = cv.blur(original, (kernel, kernel))
        elif choice == self.tr('Bilateral'):
            self.sigma_spin.setEnabled(True)
            denoised = cv.bilateralFilter(original, kernel, sigma, sigma)
        elif choice == self.tr('NonLocal'):
            if grayscale:
                denoised = cv.fastNlMeansDenoising(original, None, kernel)
            else:
                denoised = cv.fastNlMeansDenoisingColored(
                    original, None, kernel, kernel)
        else:
            denoised = None

        if self.denoised_check.isChecked():
            self.levels_spin.setEnabled(False)
            result = denoised
        else:
            self.levels_spin.setEnabled(True)
            noise = cv.absdiff(original, denoised)
            levels = self.levels_spin.value()
            if levels == 0:
                if grayscale:
                    result = cv.equalizeHist(noise)
                else:
                    result = equalize_img(noise)
            else:
                result = cv.LUT(noise, create_lut(0, 255 - levels))
        if grayscale:
            result = cv.cvtColor(result, cv.COLOR_GRAY2BGR)
        self.viewer.update_processed(result)
        self.info_message.emit(
            self.tr('Noise estimation = {}'.format(elapsed_time(start))))
Example #7
0
class PlotsWidget(ToolWidget):
    def __init__(self, image, parent=None):
        super(PlotsWidget, self).__init__(parent)

        choices = ['Red', 'Green', 'Blue', 'Hue', 'Saturation', 'Value']
        self.xaxis_combo = QComboBox()
        self.xaxis_combo.addItems(choices)
        self.xaxis_combo.setCurrentIndex(3)
        self.yaxis_combo = QComboBox()
        self.yaxis_combo.addItems(choices)
        self.yaxis_combo.setCurrentIndex(4)
        self.sampling_spin = QSpinBox()
        levels = int(np.log2(min(image.shape[:-1])))
        self.sampling_spin.setRange(0, levels)
        self.sampling_spin.setSpecialValueText(self.tr('Off'))
        self.sampling_spin.setValue(1)
        self.sampling_spin.setSuffix(self.tr(' level(s)'))
        self.size_spin = QSpinBox()
        self.size_spin.setRange(1, 10)
        self.size_spin.setValue(2)
        self.size_spin.setSuffix(self.tr(' pt'))
        self.style_combo = QComboBox()
        self.markers = [
            ',', '.', 'o', '8', 's', 'p', 'P', '*', 'h', 'H', 'X', 'D'
        ]
        self.style_combo.addItems([
            'pixel', 'point', 'circle', 'octa', 'square', 'penta', 'plus',
            'star', 'hexa1', 'hexa2', 'cross', 'diamond'
        ])
        self.alpha_spin = QDoubleSpinBox()
        self.alpha_spin.setRange(0, 1)
        self.alpha_spin.setDecimals(2)
        self.alpha_spin.setSingleStep(0.05)
        self.alpha_spin.setValue(1)
        self.colors_check = QCheckBox(self.tr('Show colors'))
        self.grid_check = QCheckBox(self.tr('Show grid'))
        self.norm_check = QCheckBox(self.tr('Normalized'))
        self.total_label = QLabel()

        img = np.copy(image)
        self.colors = [None] * (levels + 1)
        for scale in range(levels + 1):
            rgb = cv.cvtColor(img.astype(np.float32) / 255, cv.COLOR_BGR2RGB)
            hsv = cv.cvtColor(rgb, cv.COLOR_RGB2HSV)
            hsv[:, :, 0] /= 360
            shape = (img.shape[0] * img.shape[1], img.shape[2])
            self.colors[scale] = np.concatenate(
                (np.reshape(rgb, shape), np.reshape(hsv, shape)), axis=1)
            img = cv.pyrDown(img)
        figure = Figure()
        plot_canvas = FigureCanvas(figure)
        self.axes = plot_canvas.figure.subplots()
        self.redraw()
        figure.set_tight_layout(True)

        self.xaxis_combo.currentIndexChanged.connect(self.redraw)
        self.yaxis_combo.currentIndexChanged.connect(self.redraw)
        self.sampling_spin.valueChanged.connect(self.redraw)
        self.size_spin.valueChanged.connect(self.redraw)
        self.style_combo.currentIndexChanged.connect(self.redraw)
        self.alpha_spin.valueChanged.connect(self.redraw)
        self.colors_check.stateChanged.connect(self.redraw)
        self.grid_check.stateChanged.connect(self.redraw)
        self.norm_check.stateChanged.connect(self.redraw)

        bottom_layout = QGridLayout()
        bottom_layout.addWidget(NavigationToolbar(plot_canvas, self), 0, 0, 1,
                                5)
        bottom_layout.addWidget(QLabel(self.tr('X axis:')), 1, 0)
        bottom_layout.addWidget(self.xaxis_combo, 1, 1)
        bottom_layout.addWidget(QLabel(self.tr('Y Axis:')), 2, 0)
        bottom_layout.addWidget(self.yaxis_combo, 2, 1)
        bottom_layout.addWidget(QLabel(self.tr('Subsampling:')), 3, 0)
        bottom_layout.addWidget(self.sampling_spin, 3, 1)
        bottom_layout.addWidget(QLabel(self.tr('Point size:')), 1, 2)
        bottom_layout.addWidget(self.size_spin, 1, 3)
        bottom_layout.addWidget(QLabel(self.tr('Point style:')), 2, 2)
        bottom_layout.addWidget(self.style_combo, 2, 3)
        bottom_layout.addWidget(QLabel(self.tr('Point alpha:')), 3, 2)
        bottom_layout.addWidget(self.alpha_spin, 3, 3)
        bottom_layout.addWidget(self.colors_check, 1, 4)
        bottom_layout.addWidget(self.grid_check, 2, 4)
        bottom_layout.addWidget(self.total_label, 3, 4)

        main_layout = QVBoxLayout()
        main_layout.addWidget(plot_canvas)
        main_layout.addLayout(bottom_layout)
        self.setLayout(main_layout)

    def redraw(self):
        start = time()
        v = self.sampling_spin.value()
        x = self.colors[v][:, self.xaxis_combo.currentIndex()]
        y = self.colors[v][:, self.yaxis_combo.currentIndex()]
        xlim = self.axes.get_xlim()
        ylim = self.axes.get_ylim()
        s = self.size_spin.value()**2
        c = None if not self.colors_check.isChecked(
        ) else self.colors[v][:, :3]
        a = self.alpha_spin.value()
        m = self.markers[self.style_combo.currentIndex()]
        self.axes.clear()
        self.axes.set_facecolor([0.5] * 3 if c is not None else [1.0] * 3)
        self.axes.scatter(x, y, s, c, m, alpha=a)
        self.axes.set_xlabel(self.xaxis_combo.currentText())
        self.axes.set_ylabel(self.yaxis_combo.currentText())
        self.axes.grid(self.grid_check.isChecked(), which='both')
        self.axes.set_xlim(xlim)
        self.axes.set_ylim(ylim)
        self.axes.figure.canvas.draw()
        self.total_label.setText(self.tr('[{} points]'.format(len(x))))
        self.info_message.emit('Plot redraw = {}'.format(elapsed_time(start)))
    def _init_simgrs_tab(self, tab):
        # simgrs list

        simgrs_label = QLabel(self)
        simgrs_label.setText('Simulation Manager')

        simgrs_list = QComboBox(self)
        self._simgrs_list = simgrs_list
        simgrs_list.currentIndexChanged.connect(self._on_simgr_selection)

        pg_layout = QHBoxLayout()
        pg_layout.addWidget(simgrs_label)
        pg_layout.addWidget(simgrs_list)

        # simulation manager information
        viewer = QSimulationManagerViewer(self.simgr)
        self._simgr_viewer = viewer
        viewer.itemClicked.connect(self._on_item_clicked)

        def _jump_to_state_address(item, column):
            if not isinstance(item, StateTreeItem):
                return
            self.instance.workspace.jump_to(item.state.addr)

        viewer.itemDoubleClicked.connect(_jump_to_state_address)

        #
        # Max settings
        #

        lbl_max_active = QLabel()
        lbl_max_active.setText("Max active")

        max_active = QSpinBox()
        max_active.setMinimum(0)
        max_active.setMaximum(1000)
        max_active.setSpecialValueText('-')
        self._max_active = max_active

        lbl_max_steps = QLabel()
        lbl_max_steps.setText("Max steps")

        max_steps = QSpinBox()
        max_steps.setMinimum(0)
        max_steps.setMaximum(1000)
        max_steps.setSpecialValueText('-')
        self._max_steps = max_steps

        max_settings_layout = QVBoxLayout()
        layout = QHBoxLayout()
        layout.addWidget(lbl_max_active)
        layout.addWidget(max_active)
        max_settings_layout.addLayout(layout)

        layout = QHBoxLayout()
        layout.addWidget(lbl_max_steps)
        layout.addWidget(max_steps)
        max_settings_layout.addLayout(layout)

        #
        # Buttons
        #

        # step button
        self.explore_buttons = []
        step_button = QPushButton()
        step_button.setText('&Step actives')
        step_button.released.connect(self._on_step_clicked)
        self.explore_buttons.append(step_button)

        # step until branch
        step_until_branch_button = QPushButton('Step actives until &branch')
        step_until_branch_button.released.connect(
            self._on_step_until_branch_clicked)
        self.explore_buttons.append(step_until_branch_button)

        # explore button
        explore_button = QPushButton('&Explore')
        explore_button.released.connect(self._on_explore_clicked)
        self.explore_buttons.append(explore_button)

        # buttons layout
        buttons_layout = QVBoxLayout()
        layout = QHBoxLayout()
        layout.addWidget(explore_button)
        buttons_layout.addLayout(layout)

        layout = QHBoxLayout()
        layout.addWidget(step_button)
        layout.addWidget(step_until_branch_button)
        buttons_layout.addLayout(layout)

        simgrs_layout = QVBoxLayout()
        simgrs_layout.addLayout(pg_layout)
        simgrs_layout.addWidget(viewer)
        simgrs_layout.addLayout(max_settings_layout)
        simgrs_layout.addLayout(buttons_layout)

        frame = QFrame()
        frame.setLayout(simgrs_layout)

        tab.addTab(frame, 'General')
Example #9
0
class Window(QWidget):
    def __init__(self):
        super(Window, self).__init__()

        self.renderArea = RenderArea()

        self.shapeComboBox = QComboBox()
        self.shapeComboBox.addItem("Polygon", RenderArea.Polygon)
        self.shapeComboBox.addItem("Rectangle", RenderArea.Rect)
        self.shapeComboBox.addItem("Rounded Rectangle", RenderArea.RoundedRect)
        self.shapeComboBox.addItem("Ellipse", RenderArea.Ellipse)
        self.shapeComboBox.addItem("Pie", RenderArea.Pie)
        self.shapeComboBox.addItem("Chord", RenderArea.Chord)
        self.shapeComboBox.addItem("Path", RenderArea.Path)
        self.shapeComboBox.addItem("Line", RenderArea.Line)
        self.shapeComboBox.addItem("Polyline", RenderArea.Polyline)
        self.shapeComboBox.addItem("Arc", RenderArea.Arc)
        self.shapeComboBox.addItem("Points", RenderArea.Points)
        self.shapeComboBox.addItem("Text", RenderArea.Text)
        self.shapeComboBox.addItem("Pixmap", RenderArea.Pixmap)

        shapeLabel = QLabel("&Shape:")
        shapeLabel.setBuddy(self.shapeComboBox)

        self.penWidthSpinBox = QSpinBox()
        self.penWidthSpinBox.setRange(0, 20)
        self.penWidthSpinBox.setSpecialValueText("0 (cosmetic pen)")

        penWidthLabel = QLabel("Pen &Width:")
        penWidthLabel.setBuddy(self.penWidthSpinBox)

        self.penStyleComboBox = QComboBox()
        self.penStyleComboBox.addItem("Solid", Qt.SolidLine)
        self.penStyleComboBox.addItem("Dash", Qt.DashLine)
        self.penStyleComboBox.addItem("Dot", Qt.DotLine)
        self.penStyleComboBox.addItem("Dash Dot", Qt.DashDotLine)
        self.penStyleComboBox.addItem("Dash Dot Dot", Qt.DashDotDotLine)
        self.penStyleComboBox.addItem("None", Qt.NoPen)

        penStyleLabel = QLabel("&Pen Style:")
        penStyleLabel.setBuddy(self.penStyleComboBox)

        self.penCapComboBox = QComboBox()
        self.penCapComboBox.addItem("Flat", Qt.FlatCap)
        self.penCapComboBox.addItem("Square", Qt.SquareCap)
        self.penCapComboBox.addItem("Round", Qt.RoundCap)

        penCapLabel = QLabel("Pen &Cap:")
        penCapLabel.setBuddy(self.penCapComboBox)

        self.penJoinComboBox = QComboBox()
        self.penJoinComboBox.addItem("Miter", Qt.MiterJoin)
        self.penJoinComboBox.addItem("Bevel", Qt.BevelJoin)
        self.penJoinComboBox.addItem("Round", Qt.RoundJoin)

        penJoinLabel = QLabel("Pen &Join:")
        penJoinLabel.setBuddy(self.penJoinComboBox)

        self.brushStyleComboBox = QComboBox()
        self.brushStyleComboBox.addItem("Linear Gradient",
                Qt.LinearGradientPattern)
        self.brushStyleComboBox.addItem("Radial Gradient",
                Qt.RadialGradientPattern)
        self.brushStyleComboBox.addItem("Conical Gradient",
                Qt.ConicalGradientPattern)
        self.brushStyleComboBox.addItem("Texture", Qt.TexturePattern)
        self.brushStyleComboBox.addItem("Solid", Qt.SolidPattern)
        self.brushStyleComboBox.addItem("Horizontal", Qt.HorPattern)
        self.brushStyleComboBox.addItem("Vertical", Qt.VerPattern)
        self.brushStyleComboBox.addItem("Cross", Qt.CrossPattern)
        self.brushStyleComboBox.addItem("Backward Diagonal", Qt.BDiagPattern)
        self.brushStyleComboBox.addItem("Forward Diagonal", Qt.FDiagPattern)
        self.brushStyleComboBox.addItem("Diagonal Cross", Qt.DiagCrossPattern)
        self.brushStyleComboBox.addItem("Dense 1", Qt.Dense1Pattern)
        self.brushStyleComboBox.addItem("Dense 2", Qt.Dense2Pattern)
        self.brushStyleComboBox.addItem("Dense 3", Qt.Dense3Pattern)
        self.brushStyleComboBox.addItem("Dense 4", Qt.Dense4Pattern)
        self.brushStyleComboBox.addItem("Dense 5", Qt.Dense5Pattern)
        self.brushStyleComboBox.addItem("Dense 6", Qt.Dense6Pattern)
        self.brushStyleComboBox.addItem("Dense 7", Qt.Dense7Pattern)
        self.brushStyleComboBox.addItem("None", Qt.NoBrush)

        brushStyleLabel = QLabel("&Brush Style:")
        brushStyleLabel.setBuddy(self.brushStyleComboBox)

        otherOptionsLabel = QLabel("Other Options:")
        self.antialiasingCheckBox = QCheckBox("&Antialiasing")
        self.transformationsCheckBox = QCheckBox("&Transformations")

        self.shapeComboBox.activated.connect(self.shapeChanged)
        self.penWidthSpinBox.valueChanged.connect(self.penChanged)
        self.penStyleComboBox.activated.connect(self.penChanged)
        self.penCapComboBox.activated.connect(self.penChanged)
        self.penJoinComboBox.activated.connect(self.penChanged)
        self.brushStyleComboBox.activated.connect(self.brushChanged)
        self.antialiasingCheckBox.toggled.connect(self.renderArea.setAntialiased)
        self.transformationsCheckBox.toggled.connect(self.renderArea.setTransformed)

        mainLayout = QGridLayout()
        mainLayout.setColumnStretch(0, 1)
        mainLayout.setColumnStretch(3, 1)
        mainLayout.addWidget(self.renderArea, 0, 0, 1, 4)
        mainLayout.setRowMinimumHeight(1, 6)
        mainLayout.addWidget(shapeLabel, 2, 1, Qt.AlignRight)
        mainLayout.addWidget(self.shapeComboBox, 2, 2)
        mainLayout.addWidget(penWidthLabel, 3, 1, Qt.AlignRight)
        mainLayout.addWidget(self.penWidthSpinBox, 3, 2)
        mainLayout.addWidget(penStyleLabel, 4, 1, Qt.AlignRight)
        mainLayout.addWidget(self.penStyleComboBox, 4, 2)
        mainLayout.addWidget(penCapLabel, 5, 1, Qt.AlignRight)
        mainLayout.addWidget(self.penCapComboBox, 5, 2)
        mainLayout.addWidget(penJoinLabel, 6, 1, Qt.AlignRight)
        mainLayout.addWidget(self.penJoinComboBox, 6, 2)
        mainLayout.addWidget(brushStyleLabel, 7, 1, Qt.AlignRight)
        mainLayout.addWidget(self.brushStyleComboBox, 7, 2)
        mainLayout.setRowMinimumHeight(8, 6)
        mainLayout.addWidget(otherOptionsLabel, 9, 1, Qt.AlignRight)
        mainLayout.addWidget(self.antialiasingCheckBox, 9, 2)
        mainLayout.addWidget(self.transformationsCheckBox, 10, 2)
        self.setLayout(mainLayout)

        self.shapeChanged()
        self.penChanged()
        self.brushChanged()
        self.antialiasingCheckBox.setChecked(True)

        self.setWindowTitle("Basic Drawing")

    def shapeChanged(self):
        shape = self.shapeComboBox.itemData(self.shapeComboBox.currentIndex(),
                IdRole)
        self.renderArea.setShape(shape)

    def penChanged(self):
        width = self.penWidthSpinBox.value()
        style = Qt.PenStyle(self.penStyleComboBox.itemData(
                self.penStyleComboBox.currentIndex(), IdRole))
        cap = Qt.PenCapStyle(self.penCapComboBox.itemData(
                self.penCapComboBox.currentIndex(), IdRole))
        join = Qt.PenJoinStyle(self.penJoinComboBox.itemData(
                self.penJoinComboBox.currentIndex(), IdRole))

        self.renderArea.setPen(QPen(Qt.blue, width, style, cap, join))

    def brushChanged(self):
        style = Qt.BrushStyle(self.brushStyleComboBox.itemData(
                self.brushStyleComboBox.currentIndex(), IdRole))

        if style == Qt.LinearGradientPattern:
            linearGradient = QLinearGradient(0, 0, 100, 100)
            linearGradient.setColorAt(0.0, Qt.white)
            linearGradient.setColorAt(0.2, Qt.green)
            linearGradient.setColorAt(1.0, Qt.black)
            self.renderArea.setBrush(QBrush(linearGradient))
        elif style == Qt.RadialGradientPattern:
            radialGradient = QRadialGradient(50, 50, 50, 70, 70)
            radialGradient.setColorAt(0.0, Qt.white)
            radialGradient.setColorAt(0.2, Qt.green)
            radialGradient.setColorAt(1.0, Qt.black)
            self.renderArea.setBrush(QBrush(radialGradient))
        elif style == Qt.ConicalGradientPattern:
            conicalGradient = QConicalGradient(50, 50, 150)
            conicalGradient.setColorAt(0.0, Qt.white)
            conicalGradient.setColorAt(0.2, Qt.green)
            conicalGradient.setColorAt(1.0, Qt.black)
            self.renderArea.setBrush(QBrush(conicalGradient))
        elif style == Qt.TexturePattern:
            self.renderArea.setBrush(QBrush(QPixmap(':/images/brick.png')))
        else:
            self.renderArea.setBrush(QBrush(Qt.green, style))
Example #10
0
class SpecifySearchConditionsDialog(BaseDialog):
    def __init__(self, parent, entity):
        super().__init__(parent, _("Search criteria"), _("&Start search"),
                         _("&Cancel"))
        self._entity = entity
        self._value_widget = None
        self._value_label = None
        self._search_expression_parts = []
        self._added_condition = False
        self._populate_fields_tree(self._entity)

    def create_ui(self):
        fields_label = QLabel(_("Class fields"), self)
        self.layout.addWidget(fields_label, 0, 0)
        self._fields_tree = QTreeWidget(self)
        fields_label.setBuddy(self._fields_tree)
        self._fields_tree.currentItemChanged.connect(
            self.on_fields_tree_sel_changed)
        self.layout.addWidget(self._fields_tree, 1, 0)
        operator_label = QLabel(_("Operator"), self)
        self.layout.addWidget(operator_label, 0, 1)
        self._operator = QListWidget(self)
        operator_label.setBuddy(self._operator)
        self.layout.addWidget(self._operator, 1, 1)
        self._operator.currentRowChanged.connect(self.on_operator_choice)
        self._operator.setCurrentRow(0)
        add_button = QPushButton(_("&Add condition"), self)
        add_button.clicked.connect(self.on_add_clicked)
        self.layout.addWidget(add_button, 2, 0, 1, 3)
        criteria_label = QLabel(_("Current search criteria"), self)
        self.layout.addWidget(criteria_label, 3, 0, 1, 3)
        self._criteria_list = QListWidget(self)
        criteria_label.setBuddy(self._criteria_list)
        self.layout.addWidget(self._criteria_list, 4, 0, 1, 3)
        remove_button = QPushButton(_("&Remove condition"), self)
        remove_button.clicked.connect(self.on_remove_clicked)
        self.layout.addWidget(remove_button, 5, 0, 1, 3)
        distance_label = QLabel(_("Search objects to distance"), self)
        self.layout.addWidget(distance_label, 6, 0)
        self._distance_field = QSpinBox(self)
        self._distance_field.setMaximum(100000)
        self._distance_field.setSuffix(" " + _("meters"))
        self._distance_field.setSpecialValueText(_("No limit"))
        distance_label.setBuddy(self._distance_field)
        self.layout.addWidget(self._distance_field, 6, 1)

    def _populate_fields_tree(self, entity, parent=None):
        if parent is None:
            parent = self._fields_tree.invisibleRootItem()
        metadata = EntityMetadata.for_discriminator(entity)
        for field_name, field in sorted(
                metadata.all_fields.items(),
                key=lambda i: underscored_to_words(i[0])):
            child_metadata = None
            try:
                child_metadata = EntityMetadata.for_discriminator(
                    field.type_name)
            except KeyError:
                pass
            if child_metadata:
                name = get_class_display_name(field.type_name)
                subparent = QTreeWidgetItem([name])
                subparent.setData(0, Qt.UserRole, field_name)
                parent.addChild(subparent)
                self._populate_fields_tree(field.type_name, subparent)
            else:
                item = QTreeWidgetItem([underscored_to_words(field_name)])
                item.setData(0, Qt.UserRole, (field_name, field))
                parent.addChild(item)

    def on_fields_tree_sel_changed(self, item):
        data = item.data(0, Qt.UserRole)
        if data is not None and not isinstance(data, str):
            self._field_name = data[0]
            self._field = data[1]
            self._operators = operators_for_column_class(self._field.type_name)
            self._operator.clear()
            self._operator.addItems([o.label for o in self._operators])
            self._added_condition = False

    def on_operator_choice(self, index):
        self._added_condition = False
        if self._value_widget:
            self.layout.removeWidget(self._value_widget)
            self._value_widget.deleteLater()
        if self._value_label:
            self.layout.removeWidget(self._value_label)
            self._value_label.deleteLater()
            self._value_label = None
        operator = self._operators[self._operator.currentRow()]
        value_label = self._create_value_label(
            operator.get_value_label(self._field))
        self._value_widget = operator.get_value_widget(self, self._field)
        if not self._value_widget:
            return
        QWidget.setTabOrder(self._operator, self._value_widget)
        self._value_label = value_label
        if self._value_label:
            self._value_label.setBuddy(self._value_widget)
            self.layout.addWidget(self._value_label, 0, 2)
        self.layout.addWidget(self._value_widget, 1, 2)

    def _create_value_label(self, label):
        if not label:
            return
        label = QLabel(label, self)
        return label

    def on_add_clicked(self, evt):
        if not hasattr(self, "_field_name"):
            return
        self._added_condition = True
        json_path = []
        parent_item = self._fields_tree.currentItem().parent()
        parent_data = parent_item.data(0, Qt.UserRole) if parent_item else None
        if isinstance(parent_data, str):
            json_path.append(parent_data)
        json_path.append(self._field_name)
        json_path = ".".join(json_path)
        operator_obj = self._operators[self._operator.currentRow()]
        expression = operator_obj.get_comparison_expression(
            self._field, FieldNamed(json_path), self._value_widget)
        self._search_expression_parts.append(expression)
        self._criteria_list.addItem(
            f"{underscored_to_words(self._field_name)} {operator_obj.label} {operator_obj.get_value_as_string(self._field, self._value_widget)}"
        )

    @property
    def distance(self):
        return self._distance_field.value()

    def create_conditions(self):
        conditions = []
        if self._search_expression_parts:
            for part in self._search_expression_parts:
                conditions.append(part)
        return conditions

    def on_remove_clicked(self, evt):
        selection = self._criteria_list.currentRow()
        if selection < 0:
            return
        del self._search_expression_parts[selection]
        self._criteria_list.removeItemWidget(self._criteria_list.currentItem())

    def ok_clicked(self):
        if not self._added_condition:
            if QMessageBox.question(
                    self, _("Question"),
                    _("It appears that you forgot to add the current condition to the conditions list. Do you want to add it before starting the search?"
                      )):
                self.on_add_clicked(None)
        super().ok_clicked()
class Window(QWidget):
    def __init__(self):
        super(Window, self).__init__()

        self.renderArea = RenderArea()

        self.shapeComboBox = QComboBox()
        self.shapeComboBox.addItem("Polygon", RenderArea.Polygon)
        self.shapeComboBox.addItem("Rectangle", RenderArea.Rect)
        self.shapeComboBox.addItem("Rounded Rectangle", RenderArea.RoundedRect)
        self.shapeComboBox.addItem("Ellipse", RenderArea.Ellipse)
        self.shapeComboBox.addItem("Pie", RenderArea.Pie)
        self.shapeComboBox.addItem("Chord", RenderArea.Chord)
        self.shapeComboBox.addItem("Path", RenderArea.Path)
        self.shapeComboBox.addItem("Line", RenderArea.Line)
        self.shapeComboBox.addItem("Polyline", RenderArea.Polyline)
        self.shapeComboBox.addItem("Arc", RenderArea.Arc)
        self.shapeComboBox.addItem("Points", RenderArea.Points)
        self.shapeComboBox.addItem("Text", RenderArea.Text)
        self.shapeComboBox.addItem("Pixmap", RenderArea.Pixmap)

        shapeLabel = QLabel("&Shape:")
        shapeLabel.setBuddy(self.shapeComboBox)

        self.penWidthSpinBox = QSpinBox()
        self.penWidthSpinBox.setRange(0, 20)
        self.penWidthSpinBox.setSpecialValueText("0 (cosmetic pen)")

        penWidthLabel = QLabel("Pen &Width:")
        penWidthLabel.setBuddy(self.penWidthSpinBox)

        self.penStyleComboBox = QComboBox()
        self.penStyleComboBox.addItem("Solid", Qt.SolidLine)
        self.penStyleComboBox.addItem("Dash", Qt.DashLine)
        self.penStyleComboBox.addItem("Dot", Qt.DotLine)
        self.penStyleComboBox.addItem("Dash Dot", Qt.DashDotLine)
        self.penStyleComboBox.addItem("Dash Dot Dot", Qt.DashDotDotLine)
        self.penStyleComboBox.addItem("None", Qt.NoPen)

        penStyleLabel = QLabel("&Pen Style:")
        penStyleLabel.setBuddy(self.penStyleComboBox)

        self.penCapComboBox = QComboBox()
        self.penCapComboBox.addItem("Flat", Qt.FlatCap)
        self.penCapComboBox.addItem("Square", Qt.SquareCap)
        self.penCapComboBox.addItem("Round", Qt.RoundCap)

        penCapLabel = QLabel("Pen &Cap:")
        penCapLabel.setBuddy(self.penCapComboBox)

        self.penJoinComboBox = QComboBox()
        self.penJoinComboBox.addItem("Miter", Qt.MiterJoin)
        self.penJoinComboBox.addItem("Bevel", Qt.BevelJoin)
        self.penJoinComboBox.addItem("Round", Qt.RoundJoin)

        penJoinLabel = QLabel("Pen &Join:")
        penJoinLabel.setBuddy(self.penJoinComboBox)

        self.brushStyleComboBox = QComboBox()
        self.brushStyleComboBox.addItem("Linear Gradient",
                                        Qt.LinearGradientPattern)
        self.brushStyleComboBox.addItem("Radial Gradient",
                                        Qt.RadialGradientPattern)
        self.brushStyleComboBox.addItem("Conical Gradient",
                                        Qt.ConicalGradientPattern)
        self.brushStyleComboBox.addItem("Texture", Qt.TexturePattern)
        self.brushStyleComboBox.addItem("Solid", Qt.SolidPattern)
        self.brushStyleComboBox.addItem("Horizontal", Qt.HorPattern)
        self.brushStyleComboBox.addItem("Vertical", Qt.VerPattern)
        self.brushStyleComboBox.addItem("Cross", Qt.CrossPattern)
        self.brushStyleComboBox.addItem("Backward Diagonal", Qt.BDiagPattern)
        self.brushStyleComboBox.addItem("Forward Diagonal", Qt.FDiagPattern)
        self.brushStyleComboBox.addItem("Diagonal Cross", Qt.DiagCrossPattern)
        self.brushStyleComboBox.addItem("Dense 1", Qt.Dense1Pattern)
        self.brushStyleComboBox.addItem("Dense 2", Qt.Dense2Pattern)
        self.brushStyleComboBox.addItem("Dense 3", Qt.Dense3Pattern)
        self.brushStyleComboBox.addItem("Dense 4", Qt.Dense4Pattern)
        self.brushStyleComboBox.addItem("Dense 5", Qt.Dense5Pattern)
        self.brushStyleComboBox.addItem("Dense 6", Qt.Dense6Pattern)
        self.brushStyleComboBox.addItem("Dense 7", Qt.Dense7Pattern)
        self.brushStyleComboBox.addItem("None", Qt.NoBrush)

        brushStyleLabel = QLabel("&Brush Style:")
        brushStyleLabel.setBuddy(self.brushStyleComboBox)

        otherOptionsLabel = QLabel("Other Options:")
        self.antialiasingCheckBox = QCheckBox("&Antialiasing")
        self.transformationsCheckBox = QCheckBox("&Transformations")

        self.shapeComboBox.activated.connect(self.shapeChanged)
        self.penWidthSpinBox.valueChanged.connect(self.penChanged)
        self.penStyleComboBox.activated.connect(self.penChanged)
        self.penCapComboBox.activated.connect(self.penChanged)
        self.penJoinComboBox.activated.connect(self.penChanged)
        self.brushStyleComboBox.activated.connect(self.brushChanged)
        self.antialiasingCheckBox.toggled.connect(
            self.renderArea.setAntialiased)
        self.transformationsCheckBox.toggled.connect(
            self.renderArea.setTransformed)

        mainLayout = QGridLayout()
        mainLayout.setColumnStretch(0, 1)
        mainLayout.setColumnStretch(3, 1)
        mainLayout.addWidget(self.renderArea, 0, 0, 1, 4)
        mainLayout.setRowMinimumHeight(1, 6)
        mainLayout.addWidget(shapeLabel, 2, 1, Qt.AlignRight)
        mainLayout.addWidget(self.shapeComboBox, 2, 2)
        mainLayout.addWidget(penWidthLabel, 3, 1, Qt.AlignRight)
        mainLayout.addWidget(self.penWidthSpinBox, 3, 2)
        mainLayout.addWidget(penStyleLabel, 4, 1, Qt.AlignRight)
        mainLayout.addWidget(self.penStyleComboBox, 4, 2)
        mainLayout.addWidget(penCapLabel, 5, 1, Qt.AlignRight)
        mainLayout.addWidget(self.penCapComboBox, 5, 2)
        mainLayout.addWidget(penJoinLabel, 6, 1, Qt.AlignRight)
        mainLayout.addWidget(self.penJoinComboBox, 6, 2)
        mainLayout.addWidget(brushStyleLabel, 7, 1, Qt.AlignRight)
        mainLayout.addWidget(self.brushStyleComboBox, 7, 2)
        mainLayout.setRowMinimumHeight(8, 6)
        mainLayout.addWidget(otherOptionsLabel, 9, 1, Qt.AlignRight)
        mainLayout.addWidget(self.antialiasingCheckBox, 9, 2)
        mainLayout.addWidget(self.transformationsCheckBox, 10, 2)
        self.setLayout(mainLayout)

        self.shapeChanged()
        self.penChanged()
        self.brushChanged()
        self.antialiasingCheckBox.setChecked(True)

        self.setWindowTitle("Basic Drawing")

    def shapeChanged(self):
        shape = self.shapeComboBox.itemData(self.shapeComboBox.currentIndex(),
                                            IdRole)
        self.renderArea.setShape(shape)

    def penChanged(self):
        width = self.penWidthSpinBox.value()
        style = Qt.PenStyle(
            self.penStyleComboBox.itemData(
                self.penStyleComboBox.currentIndex(), IdRole))
        cap = Qt.PenCapStyle(
            self.penCapComboBox.itemData(self.penCapComboBox.currentIndex(),
                                         IdRole))
        join = Qt.PenJoinStyle(
            self.penJoinComboBox.itemData(self.penJoinComboBox.currentIndex(),
                                          IdRole))

        self.renderArea.setPen(QPen(Qt.blue, width, style, cap, join))

    def brushChanged(self):
        style = Qt.BrushStyle(
            self.brushStyleComboBox.itemData(
                self.brushStyleComboBox.currentIndex(), IdRole))

        if style == Qt.LinearGradientPattern:
            linearGradient = QLinearGradient(0, 0, 100, 100)
            linearGradient.setColorAt(0.0, Qt.white)
            linearGradient.setColorAt(0.2, Qt.green)
            linearGradient.setColorAt(1.0, Qt.black)
            self.renderArea.setBrush(QBrush(linearGradient))
        elif style == Qt.RadialGradientPattern:
            radialGradient = QRadialGradient(50, 50, 50, 70, 70)
            radialGradient.setColorAt(0.0, Qt.white)
            radialGradient.setColorAt(0.2, Qt.green)
            radialGradient.setColorAt(1.0, Qt.black)
            self.renderArea.setBrush(QBrush(radialGradient))
        elif style == Qt.ConicalGradientPattern:
            conicalGradient = QConicalGradient(50, 50, 150)
            conicalGradient.setColorAt(0.0, Qt.white)
            conicalGradient.setColorAt(0.2, Qt.green)
            conicalGradient.setColorAt(1.0, Qt.black)
            self.renderArea.setBrush(QBrush(conicalGradient))
        elif style == Qt.TexturePattern:
            self.renderArea.setBrush(QBrush(QPixmap(':/images/brick.png')))
        else:
            self.renderArea.setBrush(QBrush(Qt.green, style))
Example #12
0
class GradientWidget(ToolWidget):
    def __init__(self, image, parent=None):
        super(GradientWidget, self).__init__(parent)
        self.levels_spin = QSpinBox()
        self.levels_spin.setRange(-1, 16)
        self.levels_spin.setSpecialValueText(self.tr('Auto'))
        self.levels_spin.setValue(-1)
        self.invert_check = QCheckBox(self.tr('Invert'))
        self.abs_check = QCheckBox(self.tr('Absolute'))

        self.grad_viewer = ImageViewer(image, image)
        self.image = image
        self.process()

        self.levels_spin.valueChanged.connect(self.process)
        self.invert_check.toggled.connect(self.process)
        self.abs_check.toggled.connect(self.process)

        top_layout = QHBoxLayout()
        top_layout.addWidget(QLabel(self.tr('Levels:')))
        top_layout.addWidget(self.levels_spin)
        top_layout.addWidget(self.invert_check)
        top_layout.addWidget(self.abs_check)
        top_layout.addStretch()

        main_layout = QVBoxLayout()
        main_layout.addLayout(top_layout)
        main_layout.addWidget(self.grad_viewer)

        self.setLayout(main_layout)

    def process(self):
        intensity = self.levels_spin.value()
        invert = self.invert_check.isChecked()
        absolute = self.abs_check.isChecked()
        self.levels_spin.setEnabled(not absolute)
        self.invert_check.setEnabled(not absolute)

        gray = cv.cvtColor(self.image, cv.COLOR_BGR2GRAY)
        diff_x = cv.Scharr(gray, cv.CV_32F, 1, 0)
        diff_y = cv.Scharr(gray, cv.CV_32F, 0, 1)
        diff_z = cv.normalize(np.abs(diff_x + diff_y), None, 0, 255,
                              cv.NORM_MINMAX)
        diff_z = cv.LUT(diff_z.astype(np.uint8), create_lut(0, 90))
        grad_x = +diff_x if invert else -diff_x
        grad_y = +diff_y if invert else -diff_y
        grad_z = diff_z

        if not absolute:
            min_x, max_x, _, _ = cv.minMaxLoc(grad_x)
            lim_x = max(abs(min_x), abs(max_x))
            grad_x = (grad_x / lim_x + 1) * 127
            min_y, max_y, _, _ = cv.minMaxLoc(grad_y)
            lim_y = max(abs(min_y), abs(max_y))
            grad_y = (grad_y / lim_y + 1) * 127
        else:
            grad_x = cv.normalize(np.abs(grad_x), None, 0, 255, cv.NORM_MINMAX)
            grad_y = cv.normalize(np.abs(grad_y), None, 0, 255, cv.NORM_MINMAX)
        grad_x = grad_x.astype(np.uint8)
        grad_y = grad_y.astype(np.uint8)

        if intensity >= 0 and not absolute:
            max_intensity = self.levels_spin.maximum()
            low = 127 - (max_intensity - intensity)
            high = 127 + (max_intensity - intensity)
            lut_xy = create_lut(low, high)
            grad_x = cv.LUT(grad_x, lut_xy)
            grad_y = cv.LUT(grad_y, lut_xy)
        else:
            grad_x = cv.equalizeHist(grad_x)
            grad_y = cv.equalizeHist(grad_y)
        gradient = np.stack((grad_z, grad_x, grad_y), axis=2)
        self.grad_viewer.update_processed(gradient)
Example #13
0
class PlotsWidget(ToolWidget):
    def __init__(self, image, parent=None):
        super(PlotsWidget, self).__init__(parent)

        choices = ["Red", "Green", "Blue", "Hue", "Saturation", "Value"]
        self.xaxis_combo = QComboBox()
        self.xaxis_combo.addItems(choices)
        self.xaxis_combo.setCurrentIndex(3)
        self.yaxis_combo = QComboBox()
        self.yaxis_combo.addItems(choices)
        self.yaxis_combo.setCurrentIndex(4)
        self.zaxis_combo = QComboBox()
        self.zaxis_combo.addItems(choices)
        self.zaxis_combo.setCurrentIndex(5)
        self.sampling_spin = QSpinBox()
        levels = int(np.log2(min(image.shape[:-1])))
        self.sampling_spin.setRange(0, levels)
        self.sampling_spin.setSpecialValueText(self.tr("Off"))
        # self.sampling_spin.setSuffix(self.tr(' level(s)'))
        self.sampling_spin.setValue(1)
        self.size_spin = QSpinBox()
        self.size_spin.setRange(1, 10)
        self.size_spin.setValue(1)
        self.size_spin.setSuffix(self.tr(" pt"))
        self.markers = [
            ",", ".", "o", "8", "s", "p", "P", "*", "h", "H", "X", "D"
        ]
        self.alpha_spin = QDoubleSpinBox()
        self.alpha_spin.setRange(0, 1)
        self.alpha_spin.setDecimals(2)
        self.alpha_spin.setSingleStep(0.05)
        self.alpha_spin.setValue(1)
        self.colors_check = QCheckBox(self.tr("Show colors"))
        self.grid_check = QCheckBox(self.tr("Show grid"))
        self.norm_check = QCheckBox(self.tr("Normalized"))
        self.total_label = QLabel()

        img = np.copy(image)
        self.colors = [None] * (levels + 1)
        for scale in range(levels + 1):
            rgb = cv.cvtColor(img.astype(np.float32) / 255, cv.COLOR_BGR2RGB)
            hsv = cv.cvtColor(rgb, cv.COLOR_RGB2HSV)
            hsv[:, :, 0] /= 360
            shape = (img.shape[0] * img.shape[1], img.shape[2])
            self.colors[scale] = np.concatenate(
                (np.reshape(rgb, shape), np.reshape(hsv, shape)), axis=1)
            img = cv.pyrDown(img)

        figure2 = Figure()
        plot2_canvas = FigureCanvas(figure2)
        self.axes2 = plot2_canvas.figure.subplots()
        toolbar2 = NavigationToolbar(plot2_canvas, self)
        plot2_layout = QVBoxLayout()
        plot2_layout.addWidget(plot2_canvas)
        plot2_layout.addWidget(toolbar2)
        plot2_widget = QWidget()
        plot2_widget.setLayout(plot2_layout)

        figure3 = Figure()
        plot3_canvas = FigureCanvas(figure3)
        self.axes3 = plot3_canvas.figure.add_subplot(111, projection="3d")
        toolbar3 = NavigationToolbar(plot3_canvas, self)
        plot3_layout = QVBoxLayout()
        plot3_layout.addWidget(plot3_canvas)
        plot3_layout.addWidget(toolbar3)
        plot3_widget = QWidget()
        plot3_widget.setLayout(plot3_layout)

        self.tab_widget = QTabWidget()
        self.tab_widget.addTab(plot2_widget, "2D Plot")
        self.tab_widget.addTab(plot3_widget, "3D Plot")
        self.redraw()
        figure2.set_tight_layout(True)
        figure3.set_tight_layout(True)

        self.xaxis_combo.currentIndexChanged.connect(self.redraw)
        self.yaxis_combo.currentIndexChanged.connect(self.redraw)
        self.zaxis_combo.currentIndexChanged.connect(self.redraw)
        self.sampling_spin.valueChanged.connect(self.redraw)
        self.size_spin.valueChanged.connect(self.redraw)
        self.alpha_spin.valueChanged.connect(self.redraw)
        self.colors_check.stateChanged.connect(self.redraw)
        self.grid_check.stateChanged.connect(self.redraw)
        self.norm_check.stateChanged.connect(self.redraw)
        self.tab_widget.currentChanged.connect(self.redraw)

        params_layout = QGridLayout()
        params_layout.addWidget(QLabel(self.tr("X axis:")), 0, 0)
        params_layout.addWidget(self.xaxis_combo, 0, 1)
        params_layout.addWidget(QLabel(self.tr("Y axis:")), 1, 0)
        params_layout.addWidget(self.yaxis_combo, 1, 1)
        params_layout.addWidget(QLabel(self.tr("Z axis:")), 2, 0)
        params_layout.addWidget(self.zaxis_combo, 2, 1)
        params_layout.addWidget(QLabel(self.tr("Subsampling:")), 0, 2)
        params_layout.addWidget(self.sampling_spin, 0, 3)
        params_layout.addWidget(QLabel(self.tr("Point size:")), 1, 2)
        params_layout.addWidget(self.size_spin, 1, 3)
        params_layout.addWidget(QLabel(self.tr("Point alpha:")), 2, 2)
        params_layout.addWidget(self.alpha_spin, 2, 3)
        params_layout.addWidget(self.colors_check, 0, 4)
        params_layout.addWidget(self.grid_check, 1, 4)
        params_layout.addWidget(self.total_label, 2, 4)
        bottom_layout = QHBoxLayout()
        bottom_layout.addLayout(params_layout)
        bottom_layout.addStretch()

        main_layout = QVBoxLayout()
        main_layout.addWidget(self.tab_widget)
        main_layout.addLayout(bottom_layout)
        self.setLayout(main_layout)

    def redraw(self):
        start = time()
        v = self.sampling_spin.value()
        x = self.colors[v][:, self.xaxis_combo.currentIndex()]
        y = self.colors[v][:, self.yaxis_combo.currentIndex()]
        s = self.size_spin.value()**2
        c = None if not self.colors_check.isChecked(
        ) else self.colors[v][:, :3]

        if self.tab_widget.currentIndex() == 0:
            self.zaxis_combo.setEnabled(False)
            self.grid_check.setEnabled(True)
            self.alpha_spin.setEnabled(True)
            a = self.alpha_spin.value()
            xlim = self.axes2.get_xlim()
            ylim = self.axes2.get_ylim()
            self.axes2.clear()
            self.axes2.set_facecolor([0.5] * 3 if c is not None else [1.0] * 3)
            self.axes2.scatter(x, y, s, c, ".", alpha=a)
            self.axes2.set_xlabel(self.xaxis_combo.currentText())
            self.axes2.set_ylabel(self.yaxis_combo.currentText())
            self.axes2.grid(self.grid_check.isChecked(), which="both")
            self.axes2.set_xlim(xlim)
            self.axes2.set_ylim(ylim)
            self.axes2.figure.canvas.draw()
        else:
            self.zaxis_combo.setEnabled(True)
            self.grid_check.setEnabled(False)
            self.alpha_spin.setEnabled(False)
            z = self.colors[v][:, self.zaxis_combo.currentIndex()]
            self.axes3.clear()
            self.axes3.set_facecolor([0.5] * 3 if c is not None else [1.0] * 3)
            self.axes3.scatter(x, y, z, s=s, c=c, marker=".", depthshade=True)
            self.axes3.set_xlabel(self.xaxis_combo.currentText())
            self.axes3.set_ylabel(self.yaxis_combo.currentText())
            self.axes3.set_zlabel(self.zaxis_combo.currentText())
            self.axes3.grid(self.grid_check.isChecked(), which="both")
            self.axes3.figure.canvas.draw()

        self.total_label.setText(self.tr(f"[{len(x)} points]"))
        self.info_message.emit(f"Plot redraw = {elapsed_time(start)}")