class Config(SignalNode.Config): """Config widget displayed for ArtificialDelay.""" def __init__(self, parent=None): super().__init__(parent=parent) self.delay = QSpinBox() self.delay.setSuffix(" ms") self.delay.setMinimum(0) self.delay.setMaximum(1000000) self.delay.valueChanged.connect(self.updateModel) layout = QFormLayout() self.setLayout(layout) layout.addRow("Delay:", self.delay) def updateModel(self): n = self.node() if n is None: return n.setDelay(self.delay.value()) def updateView(self): n = self.node() if n is None: return self.delay.blockSignals(True) self.delay.setValue(n.delay()) self.delay.blockSignals(False)
class LabeledSpinBox(QWidget): valueChanged = Signal(int) def __init__(self, label_string, minimum=1, maximum=100, starting_value=0): super(LabeledSpinBox, self).__init__() self.spinbox = QSpinBox() self.spinbox.setRange(minimum, maximum) self.spinbox.setSuffix('/{}'.format(maximum)) self.spinbox.setValue(starting_value) self.spinbox.valueChanged.connect(self._valueChanged) self.label = QLabel() self.label.setText(label_string) SpinBoxLayout = QHBoxLayout(self) SpinBoxLayout.addWidget(self.label) SpinBoxLayout.addWidget(self.spinbox) def setValue(self, value, quiet=False): if quiet: self.spinbox.blockSignals(True) self.spinbox.setValue(value) self.spinbox.blockSignals(False) else: self.spinbox.setValue(value) def value(self): return self.spinbox.value() def setRange(self, minimum, maximum): self.spinbox.setRange(minimum, maximum) self.spinbox.setSuffix("/{}".format(maximum)) def _valueChanged(self, value): self.valueChanged.emit(value)
class Config(SignalNode.Config): """Config widget displayed for BandpassFilter.""" def __init__(self, parent=None): super().__init__(parent=parent) # Upper bound ---------------------------------------------------------------------------------------------- self.lower_bound_enable = QCheckBox() self.lower_bound_enable.setChecked(True) self.lower_bound_enable.stateChanged.connect(self.updateModel) self.lower_bound = QDoubleSpinBox() self.lower_bound.valueChanged.connect(self.updateModel) self.lower_bound.setMinimum(0) self.lower_bound.setMaximum(250) self.lower_bound.setSuffix(" Hz") layout = QHBoxLayout() layout.setContentsMargins(0, 0, 0, 0) lower_bound_widget = QWidget() lower_bound_widget.setContentsMargins(0, 0, 0, 0) lower_bound_widget.setLayout(layout) layout.addWidget(self.lower_bound_enable) layout.addWidget(self.lower_bound) # Lower bound ---------------------------------------------------------------------------------------------- self.upper_bound_enable = QCheckBox() self.upper_bound_enable.setChecked(True) self.upper_bound_enable.stateChanged.connect(self.updateModel) self.upper_bound = QDoubleSpinBox() self.upper_bound.valueChanged.connect(self.updateModel) self.upper_bound.setMinimum(0) self.upper_bound.setMaximum(250) self.upper_bound.setSuffix(" Hz") layout = QHBoxLayout() layout.setContentsMargins(0, 0, 0, 0) upper_bound_widget = QWidget() upper_bound_widget.setContentsMargins(0, 0, 0, 0) upper_bound_widget.setLayout(layout) layout.addWidget(self.upper_bound_enable) layout.addWidget(self.upper_bound) # Filter type and length ----------------------------------------------------------------------------------- self.filter_type = QComboBox() for name in BandpassFilter.filter_name_to_type: self.filter_type.addItem(name) self.filter_type.currentTextChanged.connect(self.updateModel) self.filter_length = QSpinBox() self.filter_length.setMinimum(2) self.filter_length.setMaximum(1000000) self.filter_length.setValue(1000) self.filter_length.valueChanged.connect(self.updateModel) self.filter_order = QSpinBox() self.filter_order.setRange(1, 4) self.filter_order.valueChanged.connect(self.updateModel) # ---------------------------------------------------------------------------------------------------------- layout = QFormLayout() layout.addRow("Lower bound:", lower_bound_widget) layout.addRow("Upper bound:", upper_bound_widget) layout.addRow("Filter type:", self.filter_type) layout.addRow("Filter order:", self.filter_order) layout.addRow("Filter length:", self.filter_length) self.setLayout(layout) def updateModel(self): n = self.node() if n is None: return if self.lower_bound_enable.isChecked(): lower_bound = self.lower_bound.value() else: lower_bound = None if self.upper_bound_enable.isChecked(): upper_bound = self.upper_bound.value() else: upper_bound = None filter_type = n.filter_name_to_type[self.filter_type.currentText()] filter_length = self.filter_length.value() filter_order = self.filter_order.value() n.setLowerBound(lower_bound) n.setUpperBound(upper_bound) n.setFilterType(filter_type) n.setFilterLength(filter_length) n.setFilterOrder(filter_order) def updateView(self): n = self.node() if n is None: return # Prevent view fields from emitting signals while they are updated self.lower_bound.blockSignals(True) self.upper_bound.blockSignals(True) self.filter_type.blockSignals(True) self.filter_length.blockSignals(True) self.filter_order.blockSignals(True) if n.upperBound() is None: self.upper_bound_enable.setChecked(False) else: self.upper_bound_enable.setChecked(True) self.upper_bound.setValue(n.upperBound()) if n.lowerBound() is None: self.lower_bound_enable.setChecked(False) else: self.lower_bound_enable.setChecked(True) self.lower_bound.setValue(n.lowerBound()) self.filter_type.setCurrentText( n.filter_type_to_name[n.filterType()]) self.filter_length.setValue(n.filterLength()) self.filter_order.setValue(n.filterOrder()) # Release the block and call adjust self.lower_bound.blockSignals(False) self.upper_bound.blockSignals(False) self.filter_type.blockSignals(False) self.filter_length.blockSignals(False) self.filter_order.blockSignals(False) self._adjust() def _adjust(self): """Adjust displayed values and limits in response to changes.""" # Enable spinbox widgets based on their checkbox self.lower_bound.setEnabled(self.lower_bound_enable.isChecked()) self.upper_bound.setEnabled(self.upper_bound_enable.isChecked()) # Adjust min and max so that lower_bound is never higher than upper_bound if self.lower_bound_enable.isChecked(): self.upper_bound.setMinimum(self.lower_bound.value()) else: self.upper_bound.setMinimum(0) if self.upper_bound_enable.isChecked(): self.lower_bound.setMaximum(self.upper_bound.value()) else: self.lower_bound.setMaximum(250) if self.filter_type.currentText() == "Butterworth": self.filter_order.setEnabled(True) else: self.filter_order.setEnabled(False)
class WaveletWidget(ToolWidget): def __init__(self, image, parent=None): super(WaveletWidget, self).__init__(parent) self.family_combo = QComboBox() self.family_combo.addItems( [self.tr('Daubechies'), self.tr('Symlets'), self.tr('Coiflets'), self.tr('Biorthogonal')]) self.wavelet_combo = QComboBox() self.wavelet_combo.setMinimumWidth(70) self.threshold_spin = QSpinBox() self.threshold_spin.setRange(0, 100) self.threshold_spin.setSuffix('%') self.mode_combo = QComboBox() self.mode_combo.addItems( [self.tr('Soft'), self.tr('Hard'), self.tr('Garrote'), self.tr('Greater'), self.tr('Less')]) self.level_spin = QSpinBox() self.image = image self.coeffs = None self.viewer = ImageViewer(self.image, self.image) self.update_wavelet() self.family_combo.activated.connect(self.update_wavelet) self.wavelet_combo.activated.connect(self.update_level) self.threshold_spin.valueChanged.connect(self.compute_idwt) self.mode_combo.activated.connect(self.compute_idwt) self.level_spin.valueChanged.connect(self.compute_idwt) top_layout = QHBoxLayout() top_layout.addWidget(QLabel(self.tr('Family:'))) top_layout.addWidget(self.family_combo) top_layout.addWidget(QLabel(self.tr('Wavelet:'))) top_layout.addWidget(self.wavelet_combo) top_layout.addWidget(QLabel(self.tr('Threshold:'))) top_layout.addWidget(self.threshold_spin) top_layout.addWidget(QLabel(self.tr('Mode:'))) top_layout.addWidget(self.mode_combo) top_layout.addWidget(QLabel(self.tr('Level:'))) top_layout.addWidget(self.level_spin) top_layout.addStretch() main_layout = QVBoxLayout() main_layout.addLayout(top_layout) main_layout.addWidget(self.viewer) self.setLayout(main_layout) def update_wavelet(self): self.wavelet_combo.clear() family = self.family_combo.currentIndex() if family == 0: self.wavelet_combo.addItems(['db{}'.format(i) for i in range(1, 21)]) elif family == 1: self.wavelet_combo.addItems(['sym{}'.format(i) for i in range(2, 21)]) elif family == 2: self.wavelet_combo.addItems(['coif{}'.format(i) for i in range(1, 6)]) else: types = ['1.1', '1.3', '1.5', '2.2', '2.4', '2.6', '2.8', '3.1', '3.3', '3.5', '3.7', '3.9', '4.4', '5.5', '6.8'] self.wavelet_combo.addItems(['bior{}'.format(t) for t in types]) self.update_level() def update_level(self): wavelet = self.wavelet_combo.currentText() max_level = pywt.dwtn_max_level(self.image.shape[:-1], wavelet) self.level_spin.blockSignals(True) self.level_spin.setRange(1, max_level) self.level_spin.setValue(max_level // 2) self.level_spin.blockSignals(False) self.compute_dwt() def compute_dwt(self): wavelet = self.wavelet_combo.currentText() self.coeffs = pywt.wavedec2(self.image[:, :, 0], wavelet) self.compute_idwt() def compute_idwt(self): thr = self.threshold_spin.value() if thr > 0: level = self.level_spin.value() coeffs = deepcopy(self.coeffs) threshold = self.threshold_spin.value() / 100 mode = self.mode_combo.currentText().lower() for i in range(1, level + 1): octave = [None]*3 for j in range(3): plane = coeffs[-i][j] t = threshold * np.max(np.abs(plane)) octave[j] = pywt.threshold(plane, t, mode) coeffs[-i] = tuple(octave) else: coeffs = self.coeffs wavelet = self.wavelet_combo.currentText() image = cv.cvtColor(pywt.waverec2(coeffs, wavelet).astype(np.uint8), cv.COLOR_GRAY2BGR) self.viewer.update_processed(image)
class WaveletWidget(ToolWidget): def __init__(self, image, parent=None): super(WaveletWidget, self).__init__(parent) self.family_combo = QComboBox() self.family_combo.addItems([ self.tr("Daubechies"), self.tr("Symlets"), self.tr("Coiflets"), self.tr("Biorthogonal") ]) self.wavelet_combo = QComboBox() self.wavelet_combo.setMinimumWidth(70) self.threshold_spin = QSpinBox() self.threshold_spin.setRange(0, 100) self.threshold_spin.setSuffix("%") self.mode_combo = QComboBox() self.mode_combo.addItems([ self.tr("Soft"), self.tr("Hard"), self.tr("Garrote"), self.tr("Greater"), self.tr("Less") ]) self.level_spin = QSpinBox() self.image = image self.coeffs = None self.viewer = ImageViewer(self.image, self.image) self.update_wavelet() self.family_combo.activated.connect(self.update_wavelet) self.wavelet_combo.activated.connect(self.update_level) self.threshold_spin.valueChanged.connect(self.compute_idwt) self.mode_combo.activated.connect(self.compute_idwt) self.level_spin.valueChanged.connect(self.compute_idwt) top_layout = QHBoxLayout() top_layout.addWidget(QLabel(self.tr("Family:"))) top_layout.addWidget(self.family_combo) top_layout.addWidget(QLabel(self.tr("Wavelet:"))) top_layout.addWidget(self.wavelet_combo) top_layout.addWidget(QLabel(self.tr("Threshold:"))) top_layout.addWidget(self.threshold_spin) top_layout.addWidget(QLabel(self.tr("Mode:"))) top_layout.addWidget(self.mode_combo) top_layout.addWidget(QLabel(self.tr("Level:"))) top_layout.addWidget(self.level_spin) top_layout.addStretch() main_layout = QVBoxLayout() main_layout.addLayout(top_layout) main_layout.addWidget(self.viewer) self.setLayout(main_layout) def update_wavelet(self): self.wavelet_combo.clear() family = self.family_combo.currentIndex() if family == 0: self.wavelet_combo.addItems([f"db{i}" for i in range(1, 21)]) elif family == 1: self.wavelet_combo.addItems([f"sym{i}" for i in range(2, 21)]) elif family == 2: self.wavelet_combo.addItems([f"coif{i}" for i in range(1, 6)]) else: types = [ "1.1", "1.3", "1.5", "2.2", "2.4", "2.6", "2.8", "3.1", "3.3", "3.5", "3.7", "3.9", "4.4", "5.5", "6.8", ] self.wavelet_combo.addItems([f"bior{t}" for t in types]) self.update_level() def update_level(self): wavelet = self.wavelet_combo.currentText() max_level = pywt.dwtn_max_level(self.image.shape[:-1], wavelet) self.level_spin.blockSignals(True) self.level_spin.setRange(1, max_level) self.level_spin.setValue(max_level // 2) self.level_spin.blockSignals(False) self.compute_dwt() def compute_dwt(self): wavelet = self.wavelet_combo.currentText() self.coeffs = pywt.wavedec2(self.image[:, :, 0], wavelet) self.compute_idwt() def compute_idwt(self): thr = self.threshold_spin.value() if thr > 0: level = self.level_spin.value() coeffs = deepcopy(self.coeffs) threshold = self.threshold_spin.value() / 100 mode = self.mode_combo.currentText().lower() for i in range(1, level + 1): octave = [None] * 3 for j in range(3): plane = coeffs[-i][j] t = threshold * np.max(np.abs(plane)) octave[j] = pywt.threshold(plane, t, mode) coeffs[-i] = tuple(octave) else: coeffs = self.coeffs wavelet = self.wavelet_combo.currentText() image = cv.cvtColor( pywt.waverec2(coeffs, wavelet).astype(np.uint8), cv.COLOR_GRAY2BGR) self.viewer.update_processed(image)