예제 #1
0
    def __fix_waifu2x_converter_cpp_names(self):
        """
            Waifu2x-Conveter-Cpp (legacy) will output the file names in a format that needs to be fixed for
            dandere2x to work. I believe this is fixed in later versions, hence the TODO
        """

        file_names = []
        for x in range(1, self.context.frame_count):
            file_names.append("output_" + get_lexicon_value(6, x))

        for file in file_names:
            dirty_name = self.context.residual_upscaled_dir + file + '_[NS-L' + str(
                self.context.service_request.denoise_level) + '][x' + str(
                    self.context.service_request.scale_factor
                ) + '.000000]' + ".png"
            clean_name = self.context.residual_upscaled_dir + file + ".png"

            wait_on_either_file(clean_name, dirty_name)

            if file_exists(clean_name):
                pass

            elif file_exists(dirty_name):
                while file_exists(dirty_name):
                    try:
                        rename_file(dirty_name, clean_name)
                    except PermissionError:
                        pass
예제 #2
0
    def __fix_waifu2x_ncnn_vulkan_names(self):
        """
        Waifu2x-ncnn-vulkan will accept a file as "file.jpg" and output as "file.jpg.png".

        Unfortunately, dandere2x wouldn't recognize this, so this function renames each name to the correct naming
        convention. This function will iteratiate through every file needing to be upscaled waifu2x-ncnn-vulkan,
        and change it's name after it's done saving

        Comments:

        - There's a really complicated try / except that exists because, even though a file may exist,
          the file handle may still be used by waifu2x-ncnn-vulkan (it hasn't released it yet). As a result,
          we need to try / except it until it's released, allowing us to rename it.

        """

        file_names = []
        for x in range(1, self.context.frame_count):
            file_names.append("output_" + get_lexicon_value(6, x))

        for file in file_names:
            dirty_name = self.context.residual_upscaled_dir + file + ".png.png"
            clean_name = self.context.residual_upscaled_dir + file + ".png"

            wait_on_either_file(clean_name, dirty_name)

            if file_exists(clean_name):
                pass

            elif file_exists(dirty_name):
                while file_exists(dirty_name):
                    try:
                        rename_file(dirty_name, clean_name)
                    except PermissionError:
                        pass
예제 #3
0
    def __delete_used_files(self, remove_before):
        """
        Delete the files produced by dandere2x up to index_to_remove.

        Author: Tremex
        """

        # load context

        pframe_data_dir = self.context.pframe_data_dir
        residual_data_dir = self.context.residual_data_dir
        fade_data_dir = self.context.fade_data_dir
        input_frames_dir = self.context.input_frames_dir
        noised_image_dir = self.context.noised_input_frames_dir
        residual_upscaled_dir = self.context.residual_upscaled_dir

        # get the files to delete "_r(emove)"

        index_to_remove = str(remove_before - 2)

        prediction_data_file_r = pframe_data_dir + "pframe_" + index_to_remove + ".txt"
        residual_data_file_r = residual_data_dir + "residual_" + index_to_remove + ".txt"
        fade_data_file_r = fade_data_dir + "fade_" + index_to_remove + ".txt"
        input_image_r = input_frames_dir + "frame" + index_to_remove + ".png"
        noised_image = noised_image_dir + "frame" + index_to_remove + ".png"
        upscaled_file_r = residual_upscaled_dir + "output_" + get_lexicon_value(6, int(remove_before)) + ".png"

        # "mark" them-------
        remove = [prediction_data_file_r, residual_data_file_r, noised_image,
                  fade_data_file_r, input_image_r, upscaled_file_r]

        # remove
        threading.Thread(target=self.__delete_files_from_list, args=(remove,), daemon=True, name="mindiskusage").start()
예제 #4
0
    def run(self):
        self.log.info("Run called.")

        for x in range(1, self.con.frame_count):

            # Files needed to create a residual image
            f1 = Frame()
            f1.load_from_string_controller(self.con.input_frames_dir + "frame" + str(x + 1) + ".png",
                                           self.controller)
            # Load the neccecary lists to compute this iteration of residual making
            residual_data = get_list_from_file_and_wait(self.con.residual_data_dir + "residual_" + str(x) + ".txt")

            prediction_data = get_list_from_file_and_wait(self.con.pframe_data_dir + "pframe_" + str(x) + ".txt")

            # Create the output files..
            debug_output_file = self.con.debug_dir + "debug" + str(x + 1) + ".png"
            output_file = self.con.residual_images_dir + "output_" + get_lexicon_value(6, x) + ".png"

            # Save to a temp folder so waifu2x-vulkan doesn't try reading it, then move it
            out_image = self.make_residual_image(self.con, f1, residual_data, prediction_data)

            if out_image.get_res() == (1, 1):
                """
                If out_image is (1,1) in size, then frame_x and frame_x+1 are identical.

                We still need to save an outimage for sake of having N output images for N input images, so we
                save these meaningless files anyways.

                However, these 1x1 can slow whatever waifu2x implementation down, so we 'cheat' d2x 
                but 'fake' upscaling them, so that they don't need to be processed by waifu2x.
                """

                # Location of the 'fake' upscaled image.
                out_image = Frame()
                out_image.create_new(2, 2)
                output_file = self.con.residual_upscaled_dir + "output_" + get_lexicon_value(6, x) + ".png"
                out_image.save_image(output_file)

            else:
                # This image has things to upscale, continue normally
                out_image.save_image_temp(out_location=output_file, temp_location=self.con.temp_image)

            # With this change the wrappers must be modified to not try deleting the non existing residual file
            if self.con.debug is True:
                self.debug_image(block_size=self.con.service_request.block_size, frame_base=f1,
                                 list_predictive=prediction_data, list_residuals=residual_data,
                                 output_location=debug_output_file)
예제 #5
0
    def __init__(self, context: Dandere2xServiceContext,
                 controller: Dandere2xController):
        Thread.__init__(self, name="Remove Upscale Files Thread")
        super().__init__()

        self.context = context
        self.controller = controller

        # make a list of names that will eventually (past or future) be upscaled
        self.list_of_names = []
        for x in range(1, self.context.frame_count):
            self.list_of_names.append("output_" + get_lexicon_value(6, x) +
                                      ".png")
예제 #6
0
    def run(self):
        self.log.info("Started")
        self.pipe.start()

        # Load the genesis image + the first upscaled image.
        frame_previous = Frame()
        frame_previous.load_from_string_controller(
            self.context.merged_dir + "merged_" + str(1) + ".jpg",
            self.controller)

        # Load and pipe the 'first' image before we start the for loop procedure, since all the other images will
        # inductively build off this first frame.
        frame_previous = Frame()
        frame_previous.load_from_string_controller(
            self.context.merged_dir + "merged_" + str(1) + ".jpg",
            self.controller)
        self.pipe.save(frame_previous)

        current_upscaled_residuals = Frame()
        current_upscaled_residuals.load_from_string_controller(
            self.context.residual_upscaled_dir + "output_" +
            get_lexicon_value(6, 1) + ".png", self.controller)

        last_frame = False
        for x in range(1, self.context.frame_count):
            ########################################
            # Pre-loop logic checks and conditions #
            ########################################

            # Check if we're at the last image, which affects the behaviour of the loop.
            if x == self.context.frame_count - 1:
                last_frame = True

            # Pre-load the next iteration of the loop image ahead of time, if we're not on the last frame.
            if not last_frame:
                """ 
                By asynchronously loading frames ahead of time, this provides a small but meaningful
                boost in performance when spanned over N frames. There's some code over head but 
                it's well worth it. 
                """
                background_frame_load = AsyncFrameRead(
                    self.context.residual_upscaled_dir + "output_" +
                    get_lexicon_value(6, x + 1) + ".png", self.controller)
                background_frame_load.start()

            ######################
            # Core Logic of Loop #
            ######################

            # Load the needed vectors to create the merged image.

            prediction_data_list = get_list_from_file_and_wait(
                self.context.pframe_data_dir + "pframe_" + str(x) + ".txt")
            residual_data_list = get_list_from_file_and_wait(
                self.context.residual_data_dir + "residual_" + str(x) + ".txt")
            correction_data_list = get_list_from_file_and_wait(
                self.context.correction_data_dir + "correction_" + str(x) +
                ".txt")
            fade_data_list = get_list_from_file_and_wait(
                self.context.fade_data_dir + "fade_" + str(x) + ".txt")

            # Create the actual image itself.
            current_frame = self.make_merge_image(
                self.context, current_upscaled_residuals, frame_previous,
                prediction_data_list, residual_data_list, correction_data_list,
                fade_data_list)
            ###############
            # Saving Area #
            ###############
            # Directly write the image to the ffmpeg pipe line.
            self.pipe.save(current_frame)

            # Manually write the image if we're preserving frames (this is for enthusiasts / debugging).
            # if self.preserve_frames:
            # if True:
            #     output_file = self.context.merged_dir + "merged_" + str(x + 1) + ".jpg"
            #     background_frame_write = AsyncFrameWrite(current_frame, output_file)
            #     background_frame_write.start()

            #######################################
            # Assign variables for next iteration #
            #######################################
            if not last_frame:
                # We need to wait until the next upscaled image exists before we move on.
                while not background_frame_load.load_complete:
                    wait_on_file(self.context.residual_upscaled_dir +
                                 "output_" + get_lexicon_value(6, x + 1) +
                                 ".png")
            """
            Now that we're all done with the current frame, the current `current_frame` is now the frame_previous
            (with respect to the next iteration). We could obviously manually load frame_previous = Frame(n-1) each
            time, but this is an optimization that makes a substantial difference over N frames.
            """
            frame_previous = current_frame
            current_upscaled_residuals = background_frame_load.loaded_image
            self.controller.update_frame_count(x)

        self.pipe.kill()