예제 #1
0
파일: gradient.py 프로젝트: nsidere/sherloq
 def process(self):
     start = time()
     intensity = int(self.intensity_spin.value() / 100 * 127)
     invert = self.invert_check.isChecked()
     equalize = self.equalize_check.isChecked()
     self.intensity_spin.setEnabled(not equalize)
     blue_mode = self.blue_combo.currentIndex()
     if invert:
         dx = (-self.dx).astype(np.float32)
         dy = (-self.dy).astype(np.float32)
     else:
         dx = (+self.dx).astype(np.float32)
         dy = (+self.dy).astype(np.float32)
     dx_abs = np.abs(dx)
     dy_abs = np.abs(dy)
     red = ((dx / np.max(dx_abs) * 127) + 127).astype(np.uint8)
     green = ((dy / np.max(dy_abs) * 127) + 127).astype(np.uint8)
     if blue_mode == 0:
         blue = np.zeros_like(red)
     elif blue_mode == 1:
         blue = np.full_like(red, 255)
     elif blue_mode == 2:
         blue = norm_mat(dx_abs + dy_abs)
     elif blue_mode == 3:
         blue = norm_mat(np.linalg.norm(cv.merge((red, green)), axis=2))
     else:
         blue = None
     gradient = cv.merge([blue, green, red])
     if equalize:
         gradient = equalize_img(gradient)
     elif intensity > 0:
         gradient = cv.LUT(gradient, create_lut(intensity, intensity))
     self.viewer.update_processed(gradient)
     self.info_message.emit(
         self.tr(f"Luminance Gradient = {elapsed_time(start)}"))
예제 #2
0
    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)}"))
예제 #3
0
 def ssim(x, y):
     c1 = 6.5025
     c2 = 58.5225
     k = (11, 11)
     s = 1.5
     x2 = x**2
     y2 = y**2
     xy = x * y
     mu_x = cv.GaussianBlur(x, k, s)
     mu_y = cv.GaussianBlur(y, k, s)
     mu_x2 = mu_x**2
     mu_y2 = mu_y**2
     mu_xy = mu_x * mu_y
     s_x2 = cv.GaussianBlur(x2, k, s) - mu_x2
     s_y2 = cv.GaussianBlur(y2, k, s) - mu_y2
     s_xy = cv.GaussianBlur(xy, k, s) - mu_xy
     t1 = 2 * mu_xy + c1
     t2 = 2 * s_xy + c2
     t3 = t1 * t2
     t1 = mu_x2 + mu_y2 + c1
     t2 = s_x2 + s_y2 + c2
     t1 *= t2
     ssim_map = cv.divide(t3, t1)
     ssim = cv.mean(ssim_map)[0]
     return ssim, 255 - norm_mat(ssim_map, to_bgr=True)
예제 #4
0
    def load(self):
        filename, basename, reference = load_image(self)
        if filename is None:
            return
        if reference.shape != self.evidence.shape:
            QMessageBox.critical(
                self, self.tr("Error"),
                self.tr("Evidence and reference must have the same size!"))
            return
        self.reference = reference
        self.reference_viewer.set_title(self.tr(f"Reference: {basename}"))
        self.difference = norm_mat(cv.absdiff(self.evidence, self.reference))

        self.comp_label.setEnabled(True)
        self.normal_radio.setEnabled(True)
        self.difference_radio.setEnabled(True)
        self.ssim_radio.setEnabled(False)
        self.butter_radio.setEnabled(False)
        self.gray_check.setEnabled(True)
        self.equalize_check.setEnabled(True)
        self.metric_button.setEnabled(True)
        for i in range(self.table_widget.rowCount()):
            self.table_widget.setItem(i, 1, QTableWidgetItem())
        self.normal_radio.setChecked(True)
        self.table_widget.setEnabled(False)
        self.change()
예제 #5
0
 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('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)
예제 #6
0
    def estimate_noise(self):
        if self.noise is None:
            start = time()
            self.noise_button.setText(
                self.tr('Estimating noise, please wait...'))
            modify_font(self.noise_button, bold=False, italic=True)
            QCoreApplication.processEvents()

            qf = estimate_qf(self.image)
            self.noise = genNoiseprint(self.image0, qf, model_name='net')
            vmin, vmax, _, _ = cv.minMaxLoc(self.noise[34:-34, 34:-34])
            self.noise_viewer.update_processed(
                norm_mat(self.noise.clip(vmin, vmax), to_bgr=True))
            elapsed = time() - start

            self.noise_button.setText(
                self.tr('Noise estimated ({:.1f} s)'.format(elapsed)))
            modify_font(self.noise_button, bold=False, italic=False)
            self.map_button.setEnabled(True)
            self.noise_button.setCheckable(True)
        self.noise_button.setChecked(True)
예제 #7
0
파일: planes.py 프로젝트: nsidere/sherloq
    def preprocess(self):
        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)).astype(
                np.uint8)
        else:
            img = self.image[:, :, 3 - channel]

        self.planes = [
            norm_mat(cv.bitwise_and(np.full_like(img, 2**b), img), to_bgr=True)
            for b in range(8)
        ]

        # rows, cols = img.shape
        # bits = 8
        # data = [np.binary_repr(img[i][j], width=bits) for i in range(rows) for j in range(cols)]
        # self.planes = [
        #     (np.array([int(i[b]) for i in data], dtype=np.uint8) * 2 ** (bits - b - 1)).reshape(
        #         (rows, cols)) for b in range(bits)]

        self.process()
예제 #8
0
    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)
예제 #9
0
    def __init__(self, image, parent=None):
        super(StereoWidget, self).__init__(parent)

        gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
        small = cv.resize(gray, None, None, 1, 0.5)
        start = 10
        end = small.shape[1] // 3
        diff = np.fromiter([
            cv.mean(cv.absdiff(small[:, i:], small[:, :-i]))[0]
            for i in range(start, end)
        ], np.float32)
        _, maximum, _, argmax = cv.minMaxLoc(np.ediff1d(diff))
        if maximum < 2:
            error_label = QLabel(self.tr("Unable to detect stereogram!"))
            modify_font(error_label, bold=True)
            error_label.setStyleSheet("color: #FF0000")
            error_label.setAlignment(Qt.AlignCenter)
            main_layout = QVBoxLayout()
            main_layout.addWidget(error_label)
            self.setLayout(main_layout)
            return

        offset = argmax[1] + start
        a = image[:, offset:]
        b = image[:, :-offset]
        self.pattern = norm_img(cv.absdiff(a, b))
        temp = cv.cvtColor(self.pattern, cv.COLOR_BGR2GRAY)
        thr, _ = cv.threshold(temp, 0, 255, cv.THRESH_TRIANGLE)
        self.silhouette = cv.medianBlur(
            gray_to_bgr(cv.threshold(temp, thr, 255, cv.THRESH_BINARY)[1]), 3)
        a = cv.cvtColor(a, cv.COLOR_BGR2GRAY)
        b = cv.cvtColor(b, cv.COLOR_BGR2GRAY)
        flow = cv.calcOpticalFlowFarneback(a, b, None, 0.5, 5, 15, 5, 5, 1.2,
                                           cv.OPTFLOW_FARNEBACK_GAUSSIAN)[:, :,
                                                                          0]
        self.depth = gray_to_bgr(norm_mat(flow))
        flow = np.repeat(cv.normalize(flow, None, 0, 1,
                                      cv.NORM_MINMAX)[:, :, np.newaxis],
                         3,
                         axis=2)
        self.shaded = cv.normalize(
            self.pattern.astype(np.float32) * flow, None, 0, 255,
            cv.NORM_MINMAX).astype(np.uint8)
        self.viewer = ImageViewer(self.pattern, None, export=True)

        self.pattern_radio = QRadioButton(self.tr("Pattern"))
        self.pattern_radio.setChecked(True)
        self.pattern_radio.setToolTip(
            self.tr("Difference between raw and aligned image"))
        self.silhouette_radio = QRadioButton(self.tr("Silhouette"))
        self.silhouette_radio.setToolTip(
            self.tr("Apply threshold to discovered pattern"))
        self.depth_radio = QRadioButton(self.tr("Depth"))
        self.depth_radio.setToolTip(
            self.tr("Estimate 3D depth using optical flow"))
        self.shaded_radio = QRadioButton(self.tr("Shaded"))
        self.shaded_radio.setToolTip(
            self.tr("Combine pattern and depth information"))

        self.silhouette_radio.clicked.connect(self.process)
        self.pattern_radio.clicked.connect(self.process)
        self.depth_radio.clicked.connect(self.process)
        self.shaded_radio.clicked.connect(self.process)

        top_layout = QHBoxLayout()
        top_layout.addWidget(QLabel(self.tr("Mode:")))
        top_layout.addWidget(self.pattern_radio)
        top_layout.addWidget(self.silhouette_radio)
        top_layout.addWidget(self.depth_radio)
        top_layout.addWidget(self.shaded_radio)
        top_layout.addStretch()
        main_layout = QVBoxLayout()
        main_layout.addLayout(top_layout)
        main_layout.addWidget(self.viewer)
        self.setLayout(main_layout)