def test_alignment(self):
        """
        Tests if the ImageSet info is correct except the image, as this is a little unpredictable
        """
        rand_im = (np.random.rand(225, 225, 4) * 255).astype(np.uint8)
        rand_im[:, :, -1] = 1
        input_im = np.zeros((4,) + rand_im.shape, dtype=np.uint8)
        for i in range(0, input_im.shape[0]):
            input_im[i] = rand_im

        input_im[1, :-2, :] = input_im[1, 2:, :]
        input_im[1, -3:, :] = 0
        input_im[3] = np.rot90(input_im[3])

        input_im_set = ImageSet(input_im)
        input_im_set.original_shape = input_im.shape[1:]
        input_im_set.shutter_speed = np.array([1, 2, 3, 4])

        expected_im_set = ImageSet(input_im)  # ignoring the returned image here
        expected_im_set.original_shape = (222, 222, 4)
        expected_im_set.shutter_speed = input_im_set.shutter_speed.copy()

        output_image_set = input_im_set.aligned_image_set()

        self.assertEqual(expected_im_set.original_shape, output_image_set.original_shape)
        self.assertTrue(np.array_equal(expected_im_set.shutter_speed, output_image_set.shutter_speed))
Esempio n. 2
0
class App(QWidget):
    """
    A widget representing the main app GUI
    """
    def __init__(self):
        super().__init__()
        self.title = 'Stimat'
        self.main_image = PlotCanvas(width=5, height=4)
        self.original_image_set = ImageSet([])
        self.edited_image = None
        self.hdr_image = None
        self.filter_widgets = list()
        self.filter_layout = QVBoxLayout()
        self.add_global_filter_button = QPushButton("Legg til globalt filter",
                                                    self)
        self.add_lum_filter_button = QPushButton("Legg til luminans filter",
                                                 self)
        self.add_gaussian_button = QPushButton("Legg til gaussian filter",
                                               self)
        self.add_bilateral_button = QPushButton("Legg til bilateral filter",
                                                self)
        self.add_gradient_compression_button = QPushButton(
            "Legg til gradient comp. filter", self)
        self.save_image_button = QPushButton("Lagre bilde", self)
        self.align_image_button = QPushButton("Opplinjer Bildesett", self)
        self.status_label = QLabel("Ingen bilder er lastet inn")
        self.init_ui()

    def init_ui(self):
        """
        Setup all the ui in the widget
        """
        self.setup_image()
        self.filter_layout = QVBoxLayout()

        open_image_button = QPushButton(
            "Last inn bilde (velg flere for HDR-rekonstruksjon)", self)
        open_image_button.clicked.connect(self.select_file)

        self.add_global_filter_button.clicked.connect(self.add_global_filter)
        self.add_global_filter_button.setEnabled(False)

        self.add_lum_filter_button.clicked.connect(self.add_lum_filter)
        self.add_lum_filter_button.setEnabled(False)

        self.add_gaussian_button.clicked.connect(self.add_gaussian_filter)
        self.add_gaussian_button.setEnabled(False)

        self.add_bilateral_button.clicked.connect(self.add_bilateral_filter)
        self.add_bilateral_button.setEnabled(False)

        self.add_gradient_compression_button.clicked.connect(
            self.add_gradient_compression_filter)
        self.add_gradient_compression_button.setEnabled(False)

        self.save_image_button.clicked.connect(self.save_image)
        self.save_image_button.setEnabled(False)

        self.align_image_button.clicked.connect(self.align_image_set)
        self.align_image_button.setEnabled(False)

        self.status_label.setStyleSheet("background: orange")
        self.status_label.setContentsMargins(10, 3, 10, 3)

        button_layout = QVBoxLayout()
        button_layout.addWidget(self.status_label)
        button_layout.addWidget(open_image_button)
        button_layout.addWidget(self.add_global_filter_button)
        button_layout.addWidget(self.add_lum_filter_button)
        button_layout.addWidget(self.add_gaussian_button)
        button_layout.addWidget(self.add_bilateral_button)
        button_layout.addWidget(self.add_gradient_compression_button)
        button_layout.addWidget(self.save_image_button)
        button_layout.addWidget(self.align_image_button)
        button_layout.setAlignment(Qt.AlignCenter)

        group_box = QGroupBox("Innstillinger")
        group_box.setLayout(button_layout)
        group_box.setMaximumWidth(400)

        self.filter_layout.addStretch()

        filter_box = QGroupBox("Filter")
        filter_box.setLayout(self.filter_layout)

        scroll = QScrollArea()
        scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        scroll.setWidgetResizable(True)
        scroll.setWidget(filter_box)
        scroll.setMaximumWidth(400)

        action_layout = QVBoxLayout()
        action_layout.addWidget(group_box)
        action_layout.addWidget(scroll)

        main_layout = QHBoxLayout()
        main_layout.setAlignment(Qt.AlignLeading)
        main_layout.addWidget(self.main_image)
        main_layout.addLayout(action_layout)

        self.setLayout(main_layout)
        self.setWindowTitle(self.title)
        self.show()

    def setup_image(self):
        """
        Setup the image GUI
        """
        self.main_image = PlotCanvas(width=5, height=4)

    def align_image_set(self):
        """
        Aligns the chosen image set (if any)
        """
        if self.original_image_set is not None:
            try:
                self.original_image_set = self.original_image_set.aligned_image_set(
                )
                self.hdr_image = self.original_image_set.hdr_image(10)
                self.update_image_with_filter()
            except:
                self.status_label.setText(
                    "Ups! Det skjedde en feil ved rendering")
                self.status_label.setStyleSheet("background: red")

    def add_global_filter(self):
        """
        Adds a global filter to the layout
        """
        new_filter = FilterWidget(self.update_image_with_filter,
                                  self.remove_filter)
        self.filter_widgets.append(new_filter)
        self.filter_layout.addWidget(new_filter)

    def add_lum_filter(self):
        """
        Adds a luminance filter to the layout
        """
        new_filter = LumimanceFilterWidget(self.update_image_with_filter,
                                           self.remove_filter)
        self.filter_widgets.append(new_filter)
        self.filter_layout.addWidget(new_filter)

    def add_gaussian_filter(self):
        """
        Adds a gaussian filter to the layout
        """
        new_filter = GaussianFilterWidget(self.update_image_with_filter,
                                          self.remove_filter)
        self.filter_widgets.append(new_filter)
        self.filter_layout.addWidget(new_filter)
        self.update_image_with_filter()

    def add_bilateral_filter(self):
        """
        Adds a bilateral filter to the layout
        """
        new_filter = BilateralFilterWidget(self.update_image_with_filter,
                                           self.remove_filter)
        self.filter_widgets.append(new_filter)
        self.filter_layout.addWidget(new_filter)
        self.update_image_with_filter()

    def add_gradient_compression_filter(self):
        """
        Adds a gradient compression filter to the layout
        """
        new_filter = GradientCompressionFilterWidget(
            self.update_image_with_filter, self.remove_filter)
        self.filter_widgets.append(new_filter)
        self.filter_layout.addWidget(new_filter)
        self.update_image_with_filter()

    def remove_filter(self, filter_widget):
        """
        Removes a filter widget

        :param filter_widget: The filter widget to remove
        :type filter_widget: QWidget
        """
        filter_widget.deleteLater()
        self.filter_layout.removeWidget(filter_widget)
        self.filter_widgets.remove(filter_widget)
        self.update_image_with_filter()

    def apply_filters(self):
        """
        Applies all the filtes on the hdr image

        :return: A new image with the selected filters
        """
        if self.hdr_image is not None:
            self.edited_image = self.hdr_image.copy()
        else:
            self.edited_image = self.original_image_set.images[0].copy() / 255

        for filter_widget in self.filter_widgets:
            self.edited_image = filter_widget.apply_filter(self.edited_image)

        return (self.edited_image - self.edited_image.min()) / (
            self.edited_image.max() - self.edited_image.min())

    def update_image_with_filter(self):
        """
        Updates the image with the selected filter and effects
        """
        self.main_image.plot_image(self.apply_filters())

    def select_file(self):
        """
        Selects a set of files and generates a HDR image
        """
        file_name, ok = QFileDialog.getOpenFileNames(
            self, "Velg bilde", "", "PNG (*.png);;EXR (*.exr)")

        if ok:
            self.add_global_filter_button.setEnabled(True)
            self.add_lum_filter_button.setEnabled(True)
            self.add_gaussian_button.setEnabled(True)
            self.add_bilateral_button.setEnabled(True)
            self.add_gradient_compression_button.setEnabled(True)
            self.save_image_button.setEnabled(True)

            try:
                if file_name[0].endswith(".exr"):
                    self.original_image_set = None
                    self.hdr_image = read_image(file_name[0])
                    self.align_image_button.setEnabled(False)
                else:
                    image_info = list(
                        map(
                            lambda file: (file, file.rsplit("_", 1)[-1].
                                          replace(".png", "")), file_name))
                    self.original_image_set = ImageSet(image_info)
                    self.hdr_image = self.original_image_set.hdr_image(10)
                    self.align_image_button.setEnabled(True)

                self.update_image_with_filter()
                self.status_label.setText("Bilde ble lastet inn")
                self.status_label.setStyleSheet("background: green")
            except:
                self.status_label.setText(
                    "Ups! Det skjedde en feil ved innlasting av bildet")
                self.status_label.setStyleSheet("background: red")

    def save_image(self):
        """
        Saves a image to a path that is selected by the user
        """
        file_name, ok = QFileDialog.getSaveFileName(
            self, "Lagre bilde", "", "PNG (*.png);;EXR (*.exr)")

        if ok and file_name and self.hdr_image.any():
            try:
                imwrite(file_name, self.edited_image)
                self.status_label.setText("Bilde ble lagret")
                self.status_label.setStyleSheet("background: green")
            except:
                self.status_label.setText(
                    "Ups! Det skjedde en feil ved lagring av bildet")
                self.status_label.setStyleSheet("background: red")