def __init__(self, image, parent=None): super(EchoWidget, self).__init__(parent) params_layout = QHBoxLayout() params_layout.addWidget(QLabel(self.tr('Radius:'))) self.radius_spin = QSpinBox() self.radius_spin.setRange(1, 15) self.radius_spin.setSuffix(self.tr(' px')) self.radius_spin.setValue(2) self.radius_spin.valueChanged.connect(self.process) params_layout.addWidget(self.radius_spin) params_layout.addWidget(QLabel(self.tr('Contrast:'))) self.contrast_spin = QSpinBox() self.contrast_spin.setRange(0, 100) self.contrast_spin.setSuffix(self.tr(' %')) self.contrast_spin.setValue(85) self.contrast_spin.valueChanged.connect(self.process) params_layout.addWidget(self.contrast_spin) params_layout.addStretch() self.image = image self.viewer = ImageViewer(self.image, self.image, None) self.process() main_layout = QVBoxLayout() main_layout.addLayout(params_layout) main_layout.addWidget(self.viewer) self.setLayout(main_layout)
def __init__(self, image, parent=None): super(MedianWidget, self).__init__(parent) self.block_combo = QComboBox() self.block_combo.addItems(['16', '32', '64', '128', '256']) self.block_combo.setCurrentIndex(2) self.block_combo.setToolTip(self.tr('Size of analyzed blocks')) self.multi_check = QCheckBox(self.tr('Multi-scale')) self.multi_check.setChecked(True) self.process_button = QPushButton(self.tr('Process')) top_layout = QHBoxLayout() top_layout.addWidget(QLabel(self.tr('Block size:'))) top_layout.addWidget(self.block_combo) top_layout.addWidget(self.multi_check) top_layout.addWidget(self.process_button) top_layout.addStretch() self.image = image self.gray = cv.cvtColor(self.image, cv.COLOR_BGR2GRAY) self.viewer = ImageViewer(self.image, self.image) self.canceled = False self.process_button.clicked.connect(self.process) self.block_combo.currentIndexChanged.connect(self.reset) main_layout = QVBoxLayout() main_layout.addLayout(top_layout) main_layout.addWidget(self.viewer) self.setLayout(main_layout)
def __init__(self, image, parent=None): super(SplicingWidget, self).__init__(parent) self.image = image self.image0 = cv.cvtColor(self.image, cv.COLOR_BGR2GRAY).astype( np.float32) / 255 self.noise = self.map = None self.noise_button = QPushButton(self.tr('(1/2) Estimate noise')) modify_font(self.noise_button, bold=True) gray = np.full_like(self.image, 127) self.noise_viewer = ImageViewer(self.image, gray, self.tr('Estimated noise print'), export=True) self.map_button = QPushButton(self.tr('(2/2) Compute heatmap')) modify_font(self.map_button, bold=True) self.map_button.setEnabled(False) self.map_viewer = ImageViewer(self.image, gray, self.tr('Splicing probability heatmap')) self.noise_button.clicked.connect(self.estimate_noise) self.noise_button.toggled.connect(self.estimate_noise) self.map_button.clicked.connect(self.compute_map) self.map_button.toggled.connect(self.compute_map) main_layout = QGridLayout() main_layout.addWidget(self.noise_viewer, 0, 0) main_layout.addWidget(self.noise_button, 1, 0) main_layout.addWidget(self.map_viewer, 0, 1) main_layout.addWidget(self.map_button, 1, 1) self.setLayout(main_layout)
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 __init__(self, image, parent=None): super(StatsWidget, self).__init__(parent) params_layout = QHBoxLayout() params_layout.addWidget(QLabel(self.tr('Mode:'))) self.min_radio = QRadioButton(self.tr('Minimum')) self.min_radio.setChecked(True) self.min_radio.toggled.connect(self.process) params_layout.addWidget(self.min_radio) self.avg_radio = QRadioButton(self.tr('Average')) self.avg_radio.toggled.connect(self.process) params_layout.addWidget(self.avg_radio) self.max_radio = QRadioButton(self.tr('Maximum')) self.max_radio.toggled.connect(self.process) params_layout.addWidget(self.max_radio) self.incl_check = QCheckBox(self.tr('Inclusive')) self.incl_check.stateChanged.connect(self.process) params_layout.addWidget(self.incl_check) params_layout.addStretch() help_button = QPushButton() help_button.setIcon(QIcon('icons/help.svg')) help_button.clicked.connect(self.show_help) params_layout.addWidget(help_button) self.image = image self.viewer = ImageViewer(self.image, self.image) self.process() main_layout = QVBoxLayout() main_layout.addLayout(params_layout) main_layout.addWidget(self.viewer) self.setLayout(main_layout)
def __init__(self, image, parent=None): super(PlanesWidget, 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')]) self.plane_spin = QSpinBox() self.plane_spin.setPrefix(self.tr('Bit ')) self.plane_spin.setRange(0, 7) self.filter_combo = QComboBox() self.filter_combo.addItems([self.tr('Disabled'), self.tr('Median'), self.tr('Gaussian')]) self.image = image self.viewer = ImageViewer(self.image, self.image) self.planes = None self.preprocess() self.chan_combo.currentIndexChanged.connect(self.preprocess) self.plane_spin.valueChanged.connect(self.process) self.filter_combo.currentIndexChanged.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('Plane:'))) top_layout.addWidget(self.plane_spin) top_layout.addWidget(QLabel(self.tr('Filter:'))) top_layout.addWidget(self.filter_combo) top_layout.addStretch() main_layout = QVBoxLayout() main_layout.addLayout(top_layout) main_layout.addWidget(self.viewer) self.setLayout(main_layout)
def __init__(self, image, parent=None): super(ElaWidget, self).__init__(parent) params_layout = QHBoxLayout() params_layout.addWidget(QLabel(self.tr('Quality:'))) self.quality_spin = QSpinBox() self.quality_spin.setRange(0, 100) self.quality_spin.setSuffix(self.tr(' %')) self.quality_spin.valueChanged.connect(self.process) params_layout.addWidget(self.quality_spin) params_layout.addWidget(QLabel(self.tr('Scale:'))) self.scale_spin = QSpinBox() self.scale_spin.setRange(1, 100) self.scale_spin.valueChanged.connect(self.process) params_layout.addWidget(self.scale_spin) self.equalize_check = QCheckBox(self.tr('Equalized')) self.equalize_check.stateChanged.connect(self.process) params_layout.addWidget(self.equalize_check) params_layout.addStretch() default_button = QPushButton(self.tr('Default')) default_button.clicked.connect(self.default) params_layout.addWidget(default_button) self.image = image self.viewer = ImageViewer(self.image, self.image) self.default() self.process() main_layout = QVBoxLayout() main_layout.addLayout(params_layout) main_layout.addWidget(self.viewer) self.setLayout(main_layout)
class ElaWidget(ToolWidget): def __init__(self, image, parent=None): super(ElaWidget, self).__init__(parent) params_layout = QHBoxLayout() params_layout.addWidget(QLabel(self.tr('Quality:'))) self.quality_spin = QSpinBox() self.quality_spin.setRange(0, 100) self.quality_spin.setSuffix(self.tr(' %')) self.quality_spin.valueChanged.connect(self.process) params_layout.addWidget(self.quality_spin) params_layout.addWidget(QLabel(self.tr('Scale:'))) self.scale_spin = QSpinBox() self.scale_spin.setRange(1, 100) self.scale_spin.valueChanged.connect(self.process) params_layout.addWidget(self.scale_spin) self.equalize_check = QCheckBox(self.tr('Equalized')) self.equalize_check.stateChanged.connect(self.process) params_layout.addWidget(self.equalize_check) params_layout.addStretch() default_button = QPushButton(self.tr('Default')) default_button.clicked.connect(self.default) params_layout.addWidget(default_button) self.image = image self.viewer = ImageViewer(self.image, self.image) self.default() self.process() main_layout = QVBoxLayout() main_layout.addLayout(params_layout) main_layout.addWidget(self.viewer) self.setLayout(main_layout) def process(self): equalize = self.equalize_check.isChecked() self.scale_spin.setEnabled(not equalize) start = time() quality = self.quality_spin.value() scale = self.scale_spin.value() compressed = compress_jpeg(self.image, quality) if not equalize: ela = cv.convertScaleAbs(cv.subtract(compressed, self.image), None, scale) else: ela = cv.merge([ cv.equalizeHist(c) for c in cv.split(cv.absdiff(compressed, self.image)) ]) self.viewer.update_processed(ela) self.info_message.emit( self.tr('Error Level Analysis = {}'.format(elapsed_time(start)))) def default(self): self.quality_spin.setValue(75) self.scale_spin.setValue(20)
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.addStretch() 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) main_layout = QVBoxLayout() main_layout.addLayout(top_layout) main_layout.addWidget(self.viewer) self.setLayout(main_layout)
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)
class EchoWidget(ToolWidget): def __init__(self, image, parent=None): super(EchoWidget, self).__init__(parent) self.radius_spin = QSpinBox() self.radius_spin.setRange(1, 15) self.radius_spin.setSuffix(self.tr(' px')) self.radius_spin.setValue(2) self.radius_spin.setToolTip(self.tr('Laplacian filter radius')) self.contrast_spin = QSpinBox() self.contrast_spin.setRange(0, 100) self.contrast_spin.setSuffix(self.tr(' %')) self.contrast_spin.setValue(85) self.contrast_spin.setToolTip(self.tr('Output tonality compression')) self.gray_check = QCheckBox(self.tr('Grayscale')) self.gray_check.setToolTip(self.tr('Desaturated output mode')) self.image = image self.viewer = ImageViewer(self.image, self.image, None) self.process() self.radius_spin.valueChanged.connect(self.process) self.contrast_spin.valueChanged.connect(self.process) self.gray_check.stateChanged.connect(self.process) params_layout = QHBoxLayout() params_layout.addWidget(QLabel(self.tr('Radius:'))) params_layout.addWidget(self.radius_spin) params_layout.addWidget(QLabel(self.tr('Contrast:'))) params_layout.addWidget(self.contrast_spin) params_layout.addWidget(self.gray_check) params_layout.addStretch() main_layout = QVBoxLayout() main_layout.addLayout(params_layout) main_layout.addWidget(self.viewer) self.setLayout(main_layout) def process(self): start = time() kernel = 2 * self.radius_spin.value() + 1 contrast = int(self.contrast_spin.value() / 100 * 255) lut = create_lut(0, contrast) laplace = [] for channel in cv.split(self.image): deriv = np.fabs(cv.Laplacian(channel, cv.CV_64F, None, kernel)) deriv = cv.normalize(deriv, None, 0, 255, cv.NORM_MINMAX, cv.CV_8UC1) laplace.append(cv.LUT(deriv, lut)) result = cv.merge(laplace) if self.gray_check.isChecked(): result = bgr_to_gray3(result) self.viewer.update_processed(result) self.info_message.emit('Echo Edge Filter = {}'.format( elapsed_time(start)))
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 __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 __init__(self, image, parent=None): super(ElaWidget, self).__init__(parent) self.quality_spin = QSpinBox() self.quality_spin.setRange(1, 100) self.quality_spin.setSuffix(self.tr(' %')) self.quality_spin.setToolTip(self.tr('JPEG reference quality level')) self.scale_spin = QSpinBox() self.scale_spin.setRange(1, 100) self.scale_spin.setSuffix(' %') self.scale_spin.setToolTip(self.tr('Output multiplicative gain')) self.contrast_spin = QSpinBox() self.contrast_spin.setRange(0, 100) self.contrast_spin.setSuffix(' %') self.contrast_spin.setToolTip(self.tr('Output tonality compression')) self.linear_check = QCheckBox(self.tr('Linear')) self.linear_check.setToolTip(self.tr('Linearize absolute difference')) self.gray_check = QCheckBox(self.tr('Grayscale')) self.gray_check.setToolTip(self.tr('Desaturated output')) default_button = QPushButton(self.tr('Default')) default_button.setToolTip(self.tr('Revert to default parameters')) params_layout = QHBoxLayout() params_layout.addWidget(QLabel(self.tr('Quality:'))) params_layout.addWidget(self.quality_spin) params_layout.addWidget(QLabel(self.tr('Scale:'))) params_layout.addWidget(self.scale_spin) params_layout.addWidget(QLabel(self.tr('Contrast:'))) params_layout.addWidget(self.contrast_spin) params_layout.addWidget(self.linear_check) params_layout.addWidget(self.gray_check) params_layout.addWidget(default_button) params_layout.addStretch() self.image = image self.original = image.astype(np.float32) / 255 self.compressed = None self.viewer = ImageViewer(self.image, self.image) self.default() self.quality_spin.valueChanged.connect(self.preprocess) self.scale_spin.valueChanged.connect(self.process) self.contrast_spin.valueChanged.connect(self.process) self.linear_check.stateChanged.connect(self.process) self.gray_check.stateChanged.connect(self.process) default_button.clicked.connect(self.default) main_layout = QVBoxLayout() main_layout.addLayout(params_layout) main_layout.addWidget(self.viewer) self.setLayout(main_layout)
def __init__(self, image, parent=None): super(GradientWidget, self).__init__(parent) self.intensity_spin = QSpinBox() self.intensity_spin.setRange(0, 100) self.intensity_spin.setValue(95) self.intensity_spin.setSuffix(self.tr(" %")) self.intensity_spin.setToolTip(self.tr("Tonality compression amount")) self.blue_combo = QComboBox() self.blue_combo.addItems([ self.tr("None"), self.tr("Flat"), self.tr("Abs"), self.tr("Norm") ]) self.blue_combo.setCurrentIndex(2) self.blue_combo.setToolTip(self.tr("Blue component inclusion mode")) self.invert_check = QCheckBox(self.tr("Invert")) self.invert_check.setToolTip(self.tr("Reverse lighting direction")) self.equalize_check = QCheckBox(self.tr("Equalize")) self.equalize_check.setToolTip(self.tr("Apply histogram equalization")) self.image = image self.viewer = ImageViewer(self.image, self.image) self.dx, self.dy = cv.spatialGradient( cv.cvtColor(self.image, cv.COLOR_BGR2GRAY)) self.process() self.intensity_spin.valueChanged.connect(self.process) self.blue_combo.currentIndexChanged.connect(self.process) self.invert_check.stateChanged.connect(self.process) self.equalize_check.stateChanged.connect(self.process) top_layout = QHBoxLayout() top_layout.addWidget(QLabel(self.tr("Intensity:"))) top_layout.addWidget(self.intensity_spin) top_layout.addWidget(QLabel(self.tr("Blue channel:"))) top_layout.addWidget(self.blue_combo) top_layout.addWidget(self.invert_check) top_layout.addWidget(self.equalize_check) top_layout.addStretch() main_layout = QVBoxLayout() main_layout.addLayout(top_layout) main_layout.addWidget(self.viewer) self.setLayout(main_layout)
def __init__(self, image, parent=None): super(MedianWidget, self).__init__(parent) self.variance_spin = QSpinBox() self.variance_spin.setRange(0, 50) self.variance_spin.setValue(10) self.threshold_spin = QDoubleSpinBox() self.threshold_spin.setRange(0, 1) self.threshold_spin.setValue(0.45) self.threshold_spin.setSingleStep(0.01) self.showprob_check = QCheckBox(self.tr('Probability map')) self.filter_check = QCheckBox(self.tr('Speckle filter')) self.filter_check.setChecked(True) self.process_button = QPushButton(self.tr('Process')) self.avgprob_label = QLabel(self.tr('Press "Process" to start')) top_layout = QHBoxLayout() top_layout.addWidget(QLabel(self.tr('Min variance:'))) top_layout.addWidget(self.variance_spin) top_layout.addWidget(QLabel(self.tr('Threshold:'))) top_layout.addWidget(self.threshold_spin) top_layout.addWidget(self.showprob_check) top_layout.addWidget(self.filter_check) top_layout.addWidget(self.process_button) # top_layout.addWidget(self.avgprob_label) top_layout.addStretch() self.image = image self.viewer = ImageViewer(self.image, self.image) self.gray = cv.cvtColor(self.image, cv.COLOR_BGR2GRAY) self.prob = self.var = None self.block = 64 self.canceled = False self.process_button.clicked.connect(self.prepare) self.variance_spin.valueChanged.connect(self.process) self.threshold_spin.valueChanged.connect(self.process) self.showprob_check.stateChanged.connect(self.process) self.filter_check.stateChanged.connect(self.process) main_layout = QVBoxLayout() main_layout.addLayout(top_layout) main_layout.addWidget(self.viewer) self.setLayout(main_layout)
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 __init__(self, image, parent=None): super(ContrastWidget, self).__init__(parent) self.algo_combo = QComboBox() self.algo_combo.addItems([ self.tr("Histogram Error"), self.tr("Channel Similarity"), self.tr("Joint probability") ]) self.algo_combo.setToolTip( self. tr("Joint Probability merges Histogram Error and Channel Similarity" )) self.algo_combo.setCurrentIndex(2) self.block_combo = QComboBox() self.block_combo.addItems(["32", "64", "128", "256"]) self.block_combo.setCurrentIndex(1) self.block_combo.setToolTip(self.tr("Size of analyzed blocks")) self.process_button = QPushButton(self.tr("Process")) self.process_button.setToolTip( self.tr("Perform contrast enhancement analysis")) top_layout = QHBoxLayout() top_layout.addWidget(QLabel(self.tr("Algorithm:"))) top_layout.addWidget(self.algo_combo) top_layout.addWidget(QLabel(self.tr("Block size:"))) top_layout.addWidget(self.block_combo) top_layout.addWidget(self.process_button) top_layout.addStretch() self.image = image self.viewer = ImageViewer(self.image, self.image) self.error = self.chsim = self.joint = None self.canceled = False self.process_button.clicked.connect(self.process) self.algo_combo.currentIndexChanged.connect(self.choose) self.block_combo.currentIndexChanged.connect(self.reset) main_layout = QVBoxLayout() main_layout.addLayout(top_layout) main_layout.addWidget(self.viewer) self.setLayout(main_layout)
def __init__(self, parent=None): QtWidgets.QMainWindow.__init__(self, parent) self.setupUi(self) self.cntr, self.numImages = -1, -1 # self.cntr have the info of which image is selected/displayed self.image_viewer = ImageViewer(self.qlabel_image) self.__connectEvents() self.showMaximized() self.videoFrameCount = -1 self.videoLoaded = False self.vidlength = -1 self.nameItemDict = {} self.dataset = None self.imagesList = {} self.folder = None self.locked = True self.refreshLabels()
def __init__(self, image, parent=None): super(MagnifierWidget, self).__init__(parent) self.equalize_radio = QRadioButton(self.tr("Equalization")) self.equalize_radio.setToolTip(self.tr("RGB histogram equalization")) self.contrast_radio = QRadioButton(self.tr("Auto Contrast")) self.contrast_radio.setToolTip(self.tr("Compress luminance tonality")) self.centile_spin = QSpinBox() self.centile_spin.setRange(0, 100) self.centile_spin.setValue(20) self.centile_spin.setSuffix(self.tr(" %")) self.centile_spin.setToolTip(self.tr("Histogram percentile amount")) self.channel_check = QCheckBox(self.tr("By channel")) self.channel_check.setToolTip(self.tr("Independent RGB compression")) self.equalize_radio.setChecked(True) self.last_radio = self.equalize_radio self.image = image self.viewer = ImageViewer(self.image, self.image) self.change() self.viewer.viewChanged.connect(self.process) self.equalize_radio.clicked.connect(self.change) self.contrast_radio.clicked.connect(self.change) self.centile_spin.valueChanged.connect(self.change) self.channel_check.stateChanged.connect(self.change) top_layout = QHBoxLayout() top_layout.addWidget(QLabel(self.tr("Mode:"))) top_layout.addWidget(self.equalize_radio) top_layout.addWidget(self.contrast_radio) top_layout.addWidget(self.centile_spin) top_layout.addWidget(self.channel_check) top_layout.addStretch() main_layout = QVBoxLayout() main_layout.addLayout(top_layout) main_layout.addWidget(self.viewer) self.setLayout(main_layout)
def __init__(self, image, parent=None): super(MagnifierWidget, self).__init__(parent) self.equalize_radio = QRadioButton(self.tr('Equalization')) self.contrast_radio = QRadioButton(self.tr('Auto Contrast')) self.retinex_radio = QRadioButton(self.tr('Human Retina')) self.centile_spin = QSpinBox() self.centile_spin.setRange(0, 100) self.centile_spin.setValue(20) self.centile_spin.setSuffix(self.tr(' %')) self.channel_check = QCheckBox(self.tr('By channel')) self.equalize_radio.setChecked(True) self.last_radio = self.equalize_radio self.image = image self.viewer = ImageViewer(self.image, self.image) self.change() self.viewer.view_changed.connect(self.process) self.equalize_radio.toggled.connect(self.change) self.contrast_radio.toggled.connect(self.change) self.centile_spin.valueChanged.connect(self.change) self.channel_check.stateChanged.connect(self.change) self.retinex_radio.toggled.connect(self.change) top_layout = QHBoxLayout() top_layout.addWidget(QLabel(self.tr('Enhancement:'))) top_layout.addWidget(self.equalize_radio) top_layout.addWidget(self.contrast_radio) top_layout.addWidget(self.centile_spin) top_layout.addWidget(self.channel_check) top_layout.addWidget(self.retinex_radio) top_layout.addStretch() main_layout = QVBoxLayout() main_layout.addLayout(top_layout) main_layout.addWidget(self.viewer) self.setLayout(main_layout)
def __init__(self, image, parent=None): super(EchoWidget, self).__init__(parent) self.radius_spin = QSpinBox() self.radius_spin.setRange(1, 15) self.radius_spin.setSuffix(self.tr(" px")) self.radius_spin.setValue(2) self.radius_spin.setToolTip(self.tr("Laplacian filter radius")) self.contrast_spin = QSpinBox() self.contrast_spin.setRange(0, 100) self.contrast_spin.setSuffix(self.tr(" %")) self.contrast_spin.setValue(85) self.contrast_spin.setToolTip(self.tr("Output tonality compression")) self.gray_check = QCheckBox(self.tr("Grayscale")) self.gray_check.setToolTip(self.tr("Desaturated output mode")) self.image = image self.viewer = ImageViewer(self.image, self.image, None) self.process() self.radius_spin.valueChanged.connect(self.process) self.contrast_spin.valueChanged.connect(self.process) self.gray_check.stateChanged.connect(self.process) params_layout = QHBoxLayout() params_layout.addWidget(QLabel(self.tr("Radius:"))) params_layout.addWidget(self.radius_spin) params_layout.addWidget(QLabel(self.tr("Contrast:"))) params_layout.addWidget(self.contrast_spin) params_layout.addWidget(self.gray_check) params_layout.addStretch() main_layout = QVBoxLayout() main_layout.addLayout(params_layout) main_layout.addWidget(self.viewer) self.setLayout(main_layout)
def __init__(self, image, parent=None): super(GradientWidget, self).__init__(parent) self.intensity_spin = QSpinBox() self.intensity_spin.setRange(0, 127) self.intensity_spin.setValue(90) self.blue_combo = QComboBox() self.blue_combo.addItems( [self.tr('None'), self.tr('Flat'), self.tr('Norm')]) self.invert_check = QCheckBox(self.tr('Invert')) self.equalize_check = QCheckBox(self.tr('Equalize')) self.grad_viewer = ImageViewer(image, image) self.image = image self.process() self.intensity_spin.valueChanged.connect(self.process) self.blue_combo.currentIndexChanged.connect(self.process) self.invert_check.stateChanged.connect(self.process) self.equalize_check.stateChanged.connect(self.process) top_layout = QHBoxLayout() top_layout.addWidget(QLabel(self.tr('Intensity:'))) top_layout.addWidget(self.intensity_spin) top_layout.addWidget(QLabel(self.tr('Blue channel:'))) top_layout.addWidget(self.blue_combo) top_layout.addWidget(self.invert_check) top_layout.addWidget(self.equalize_check) top_layout.addStretch() main_layout = QVBoxLayout() main_layout.addLayout(top_layout) main_layout.addWidget(self.grad_viewer) self.setLayout(main_layout)
def __init__(self, filename, image, parent=None): super(ThumbWidget, self).__init__(parent) temp_file = QTemporaryFile() if temp_file.open(): output = subprocess.check_output( [exiftool_exe(), '-b', '-ThumbnailImage', filename]) temp_name = temp_file.fileName() with open(temp_name, 'wb') as file: file.write(output) thumb = cv.imread(temp_name, cv.IMREAD_COLOR) if thumb is None: self.show_error(self.tr('Thumbnail image not found!')) return # resized = cv.resize(image, thumb.shape[:-1][::-1], interpolation=cv.INTER_AREA) resized = cv.resize(thumb, image.shape[:-1][::-1], interpolation=cv.INTER_LANCZOS4) diff = cv.absdiff(image, resized) # image_aspect = image.shape[1] / image.shape[0] # thumb_aspect = thumb.shape[1] / thumb.shape[0] # if thumb_aspect < image_aspect: # shape = (thumb.shape[1] // image_aspect, thumb.shape[1]) # elif thumb_aspect > image_aspect: # shape = (thumb.shape[0], thumb.shape[0] * image_aspect) # else: # shape = thumb.shape # resized = cv.resize(image, shape, None, 0, 0, interpolation=cv.INTER_AREA) # top = (thumb.shape[0] - resized.shape[0]) / 2 # bottom = top # left = (thumb.shape[1] - resized.shape[1]) / 2 # right = left # padded = cv.copyMakeBorder(resized, top, bottom, left, right, cv.BORDER_CONSTANT) # if padded.shape != thumb.shape: # padded = cv.resize(padded, thumb.shape, interpolation=cv.INTER_AREA) # diff = cv.cvtColor(cv.absdiff(thumb, padded), cv.COLOR_BGR2GRAY) viewer = ImageViewer(resized, diff) layout = QVBoxLayout() layout.addWidget(viewer) self.setLayout(layout)
class ElaWidget(ToolWidget): def __init__(self, image, parent=None): super(ElaWidget, self).__init__(parent) self.quality_spin = QSpinBox() self.quality_spin.setRange(0, 100) self.quality_spin.setSuffix(self.tr(' %')) self.quality_spin.setToolTip(self.tr('JPEG reference quality level')) self.scale_spin = QSpinBox() self.scale_spin.setRange(1, 100) self.scale_spin.setSuffix(' %') self.scale_spin.setToolTip(self.tr('Output multiplicative gain')) self.contrast_spin = QSpinBox() self.contrast_spin.setRange(0, 100) self.contrast_spin.setSuffix(' %') self.contrast_spin.setToolTip(self.tr('Output tonality compression')) self.equalize_check = QCheckBox(self.tr('Equalized')) self.equalize_check.setToolTip(self.tr('Apply histogram equalization')) self.gray_check = QCheckBox(self.tr('Grayscale')) self.gray_check.setToolTip(self.tr('Desaturated output')) default_button = QPushButton(self.tr('Default')) default_button.setToolTip(self.tr('Revert to default parameters')) params_layout = QHBoxLayout() params_layout.addWidget(QLabel(self.tr('Quality:'))) params_layout.addWidget(self.quality_spin) params_layout.addWidget(QLabel(self.tr('Scale:'))) params_layout.addWidget(self.scale_spin) params_layout.addWidget(QLabel(self.tr('Contrast:'))) params_layout.addWidget(self.contrast_spin) params_layout.addWidget(self.equalize_check) params_layout.addWidget(self.gray_check) params_layout.addWidget(default_button) params_layout.addStretch() self.image = image self.original = image.astype(np.float32) / 255 self.viewer = ImageViewer(self.image, self.image) self.default() self.quality_spin.valueChanged.connect(self.process) self.scale_spin.valueChanged.connect(self.process) self.contrast_spin.valueChanged.connect(self.process) self.equalize_check.stateChanged.connect(self.process) self.gray_check.stateChanged.connect(self.process) default_button.clicked.connect(self.default) main_layout = QVBoxLayout() main_layout.addLayout(params_layout) main_layout.addWidget(self.viewer) self.setLayout(main_layout) def process(self): start = time() quality = self.quality_spin.value() scale = self.scale_spin.value() / 20 contrast = int(self.contrast_spin.value() / 100 * 128) equalize = self.equalize_check.isChecked() grayscale = self.gray_check.isChecked() self.scale_spin.setEnabled(not equalize) self.contrast_spin.setEnabled(not equalize) compressed = compress_img(self.image, quality).astype(np.float32) / 255 difference = cv.absdiff(self.original, compressed) if equalize: ela = equalize_img((difference * 255).astype(np.uint8)) else: ela = cv.convertScaleAbs(cv.sqrt(difference) * 255, None, scale) ela = cv.LUT(ela, create_lut(contrast, contrast)) if grayscale: ela = desaturate(ela) self.viewer.update_processed(ela) self.info_message.emit( self.tr('Error Level Analysis = {}'.format(elapsed_time(start)))) def default(self): self.blockSignals(True) self.equalize_check.setChecked(False) self.gray_check.setChecked(False) self.quality_spin.setValue(75) self.scale_spin.setValue(50) self.contrast_spin.setValue(20) self.process() self.blockSignals(False)
class MagnifierWidget(ToolWidget): def __init__(self, image, parent=None): super(MagnifierWidget, self).__init__(parent) self.equalize_radio = QRadioButton(self.tr("Equalization")) self.equalize_radio.setToolTip(self.tr("RGB histogram equalization")) self.contrast_radio = QRadioButton(self.tr("Auto Contrast")) self.contrast_radio.setToolTip(self.tr("Compress luminance tonality")) self.centile_spin = QSpinBox() self.centile_spin.setRange(0, 100) self.centile_spin.setValue(20) self.centile_spin.setSuffix(self.tr(" %")) self.centile_spin.setToolTip(self.tr("Histogram percentile amount")) self.channel_check = QCheckBox(self.tr("By channel")) self.channel_check.setToolTip(self.tr("Independent RGB compression")) self.equalize_radio.setChecked(True) self.last_radio = self.equalize_radio self.image = image self.viewer = ImageViewer(self.image, self.image) self.change() self.viewer.viewChanged.connect(self.process) self.equalize_radio.clicked.connect(self.change) self.contrast_radio.clicked.connect(self.change) self.centile_spin.valueChanged.connect(self.change) self.channel_check.stateChanged.connect(self.change) top_layout = QHBoxLayout() top_layout.addWidget(QLabel(self.tr("Mode:"))) top_layout.addWidget(self.equalize_radio) top_layout.addWidget(self.contrast_radio) top_layout.addWidget(self.centile_spin) top_layout.addWidget(self.channel_check) top_layout.addStretch() main_layout = QVBoxLayout() main_layout.addLayout(top_layout) main_layout.addWidget(self.viewer) self.setLayout(main_layout) def process(self, rect): y1 = rect.top() y2 = rect.bottom() x1 = rect.left() x2 = rect.right() roi = self.image[y1:y2, x1:x2] if self.equalize_radio.isChecked(): self.centile_spin.setEnabled(False) self.channel_check.setEnabled(False) roi = equalize_img(roi) self.last_radio = self.equalize_radio elif self.contrast_radio.isChecked(): self.centile_spin.setEnabled(True) self.channel_check.setEnabled(True) centile = self.centile_spin.value() / 200 if self.channel_check.isChecked(): roi = cv.merge( [cv.LUT(c, auto_lut(c, centile)) for c in cv.split(roi)]) else: roi = cv.LUT( roi, auto_lut(cv.cvtColor(roi, cv.COLOR_BGR2GRAY), centile)) self.last_radio = self.contrast_radio else: self.last_radio.setChecked(True) return processed = np.copy(self.image) processed[y1:y2, x1:x2] = roi self.viewer.update_processed(processed) def change(self): self.process(self.viewer.get_rect())
def __init__(self, image, parent=None): super(PcaWidget, self).__init__(parent) self.component_combo = QComboBox() self.component_combo.addItems([self.tr(f"#{i + 1}") for i in range(3)]) self.distance_radio = QRadioButton(self.tr("Distance")) self.distance_radio.setToolTip(self.tr("Distance from the closest point on selected component")) self.project_radio = QRadioButton(self.tr("Projection")) self.project_radio.setToolTip(self.tr("Projection onto the selected principal component")) self.crossprod_radio = QRadioButton(self.tr("Cross product")) self.crossprod_radio.setToolTip(self.tr("Cross product between input and selected component")) self.distance_radio.setChecked(True) self.last_radio = self.distance_radio self.invert_check = QCheckBox(self.tr("Invert")) self.invert_check.setToolTip(self.tr("Output bitwise complement")) self.equalize_check = QCheckBox(self.tr("Equalize")) self.equalize_check.setToolTip(self.tr("Apply histogram equalization")) rows, cols, chans = image.shape x = np.reshape(image, (rows * cols, chans)).astype(np.float32) mu, ev, ew = cv.PCACompute2(x, np.array([])) p = np.reshape(cv.PCAProject(x, mu, ev), (rows, cols, chans)) x0 = image.astype(np.float32) - mu self.output = [] for i, v in enumerate(ev): cross = np.cross(x0, v) distance = np.linalg.norm(cross, axis=2) / np.linalg.norm(v) project = p[:, :, i] self.output.extend([norm_mat(distance, to_bgr=True), norm_mat(project, to_bgr=True), norm_img(cross)]) table_data = [ [mu[0, 2], mu[0, 1], mu[0, 0]], [ev[0, 2], ev[0, 1], ev[0, 0]], [ev[1, 2], ev[1, 1], ev[1, 0]], [ev[2, 2], ev[2, 1], ev[2, 0]], [ew[2, 0], ew[1, 0], ew[0, 0]], ] table_widget = QTableWidget(5, 4) table_widget.setHorizontalHeaderLabels([self.tr("Element"), self.tr("Red"), self.tr("Green"), self.tr("Blue")]) table_widget.setItem(0, 0, QTableWidgetItem(self.tr("Mean vector"))) table_widget.setItem(1, 0, QTableWidgetItem(self.tr("Eigenvector 1"))) table_widget.setItem(2, 0, QTableWidgetItem(self.tr("Eigenvector 2"))) table_widget.setItem(3, 0, QTableWidgetItem(self.tr("Eigenvector 3"))) table_widget.setItem(4, 0, QTableWidgetItem(self.tr("Eigenvalues"))) for i in range(len(table_data)): modify_font(table_widget.item(i, 0), bold=True) for j in range(len(table_data[i])): table_widget.setItem(i, j + 1, QTableWidgetItem(str(table_data[i][j]))) # item = QTableWidgetItem() # item.setBackgroundColor(QColor(mu[0, 2], mu[0, 1], mu[0, 0])) # table_widget.setItem(0, 4, item) # table_widget.resizeRowsToContents() # table_widget.resizeColumnsToContents() table_widget.setEditTriggers(QAbstractItemView.NoEditTriggers) table_widget.setSelectionMode(QAbstractItemView.SingleSelection) table_widget.setMaximumHeight(190) self.viewer = ImageViewer(image, image, None) self.process() self.component_combo.currentIndexChanged.connect(self.process) self.distance_radio.clicked.connect(self.process) self.project_radio.clicked.connect(self.process) self.crossprod_radio.clicked.connect(self.process) self.invert_check.stateChanged.connect(self.process) self.equalize_check.stateChanged.connect(self.process) top_layout = QHBoxLayout() top_layout.addWidget(QLabel(self.tr("Component:"))) top_layout.addWidget(self.component_combo) top_layout.addWidget(QLabel(self.tr("Mode:"))) top_layout.addWidget(self.distance_radio) top_layout.addWidget(self.project_radio) top_layout.addWidget(self.crossprod_radio) top_layout.addWidget(self.invert_check) top_layout.addWidget(self.equalize_check) top_layout.addStretch() bottom_layout = QHBoxLayout() bottom_layout.addWidget(table_widget) main_layout = QVBoxLayout() main_layout.addLayout(top_layout) main_layout.addWidget(self.viewer) main_layout.addLayout(bottom_layout) self.setLayout(main_layout)
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))
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))
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)
if len(sys.argv) == 1: images = io.ImageCollection('data/webreg_*.jpg') else: images = [io.imread(sys.argv[1]), io.imread(sys.argv[2])] y0, x0 = images[0].shape[:2] y1, x1 = images[1].shape[:2] image = np.zeros((max(y0, y1), x0 + x1)) image[:y0, :x0] = color.rgb2gray(images[0]) image[:y1, x0:] = color.rgb2gray(images[1]) both_shapes = (images[0].shape, images[1].shape) viewer = ImageViewer(image) R = 10 selector_plugin = CorrespondenceSelector(both_shapes, n=4, zoom_radius=R) viewer += selector_plugin warp_viewer = ImageViewer(selector_plugin) warp_plugin = WarpPlugin(images, selector_plugin) warp_viewer += warp_plugin zoom_viewer = ImageViewer(selector_plugin) zoom_plugin = CorrespondenceSelector([(2*R, 2*R), (2*R, 2*R)], n=1) zoom_viewer += zoom_plugin zoom_plugin.add_line(end_points=[[R, R], [3*R, R]]) viewer.show()