Пример #1
0
        // cannot process close to the edge yet
        private static img upscale(
            img pic, UInt16?scoring_function_index = null,
            byte?scale     = null, byte?replacement_size_ish = null,
            byte?verbosity = null)
        {
            if (verbosity == null)
            {
                verbosity = 3;
            }
            if (verbosity > 0)
            {
                writer.write_then_inc("upscale");
            }
            if (scoring_function_index == null)
            {
                scoring_function_index = 0;
            }
            if (scale == null)
            {
                scale = 5;
            }
            if (replacement_size_ish == null)
            {
                replacement_size_ish = 3;
            }
            if (verbosity > 1)
            {
                writer.write("scoring function index: " + scoring_function_index);
            }
            var scoring_function = UpScaley.score.get((UInt16)scoring_function_index);

            if (verbosity > 1)
            {
                writer.write("image width: " + pic.RGB.GetLength(0));
                writer.write("image height: " + pic.RGB.GetLength(1));
                writer.write("Scale base image by " + scale + " times.");
            }
            if (scale == 0)
            {
                throw new ArgumentException("Scale cannot be 0.");
            }
            var Base             = expand.bicubic(pic, (float)scale);
            var replacement_size = (UInt16)(scale * replacement_size_ish);

            if (verbosity > 1)
            {
                writer.write("base width: " + Base.RGB.GetLength(0));
                writer.write("base height: " + Base.RGB.GetLength(1));
                writer.write("style width: " + pic.RGB.GetLength(0));
                writer.write("style height: " + pic.RGB.GetLength(1));
                writer.write("replacement size: " + scale + " * " + replacement_size_ish + " = " + replacement_size);
            }
            var result = style_transfer.trans(Base, pic, scoring_function, replacement_size, (byte)verbosity);

            if (verbosity > 0)
            {
                writer.dec();
            }
            return(result);
        }
Пример #2
0
        // code by Tim
        private static RGB bicubic_RGB_interpolator(img image, Int32 x_pos, Int32 y_pos, float x_frac, float y_frac)
        {
            byte  i, j;
            Int16 interpolated_value;
            var   interpolator_patch = new float[4, 4];
            RGB   return_value       = new RGB();

            for (byte c = 0; c < 3; c++)
            {
                for (i = 0; i < 4; i++)
                {
                    for (j = 0; j < 4; j++)
                    {
                        interpolator_patch[i, j] = image[x_pos + i, y_pos + j][c];
                    }
                }

                // Clamping to prevent bad pixels as cubic interpolation can yield values out of range
                interpolated_value = (Int16)bicubic_interpolator(interpolator_patch, x_frac, y_frac);
                if (0 == (0xff00 & interpolated_value))
                {
                    return_value[c] = (byte)interpolated_value;
                }
                else if (0 > interpolated_value)
                {
                    return_value[c] = 0;
                }
                else
                {
                    return_value[c] = 0xff;
                }
            }

            return(return_value);
        }
Пример #3
0
        // code by Tim

        public static img expand(img n, float scale)
        {
            Int32 x, y, x_pos, y_pos, n_width = n.RGB.GetLength(0), n_height = n.RGB.GetLength(1),
                  result_width = (Int32)(n_width * scale), result_height = (Int32)(n_height * scale);

            var result = new img(result_width, result_height);
            var image  = new img(n_width + 2, n_height + 2);

            // arrays run from 0 to n-1, so if we want ends to match, we need to scale appropriately
            float scale_inv_width  = (n_width - 1f) / (result_width - 1f);
            float scale_inv_height = (n_height - 1f) / (result_height - 1f);

            // avoid sampling off edge of image
            float scale_inv = 0.999999f * ((scale_inv_width < scale_inv_height) ? scale_inv_width : scale_inv_height);
            float x_sample, y_sample, x_frac, y_frac;

            for (x = 0; x < n_width; x++)
            {
                image[x + 1, 0] = n[x, 0];
                for (y = 0; y < n_height; y++)
                {
                    image[x + 1, y + 1] = n[x, y];
                }
                image[x + 1, n_height + 1] = n[x, n_height - 1];
            }

            for (y = 0; y < n_height + 2; y++)
            {
                image[0, y]           = image[1, y];
                image[n_width + 1, y] = image[n_width, y];
            }

            for (x = 0; x < result_width; x++)
            {
                x_sample = (float)(x * scale_inv);
                x_pos    = (Int32)x_sample;
                x_frac   = x_sample - (float)x_pos;

                for (y = 0; y < result_height; y++)
                {
                    y_sample = (float)(y * scale_inv);
                    y_pos    = (Int32)y_sample;
                    y_frac   = y_sample - (float)y_pos;

                    result[x, y] = bicubic_RGB_interpolator(image, x_pos, y_pos, x_frac, y_frac);
                }
            }
            return(result);
        }
Пример #4
0
        public static img nearest(img n, float scale)
        {
            Int32 x, y, n_width = n.RGB.GetLength(0), n_height = n.RGB.GetLength(1),
                  result_width = (Int32)(n_width * scale), result_height = (Int32)(n_height * scale);
            var   result = new img(result_width, result_height);
            float scale2 = 1f / scale;

            for (x = 0; x < result_width; x++)
            {
                for (y = 0; y < result_height; y++)
                {
                    result[x, y] = n[(Int32)(x * scale2), (Int32)(y * scale2)];
                }
            }
            return(result);
        }
Пример #5
0
 public static img bicubic(img n, float scale)
 {
     return(bicubic2.expand(n, scale));
 }
Пример #6
0
        static void Main(string[] args)
        {
            writer.write("reading args");
            var    arg_count = args.Length;
            string filename;

            if (arg_count > 0)
            {
                filename = args[0];
            }
            else
            {
                throw new ArgumentException("Filename required as command-line argument.");
            }
            UInt16?scoring_function_index = null;
            byte?  scale = null, replacement_size_ish = null;

            if (arg_count > 1)
            {
                if (args[1] != "_")
                {
                    scoring_function_index = Convert.ToUInt16(args[1]);
                }
                if (arg_count > 2)
                {
                    if (args[2] != "_")
                    {
                        scale = Convert.ToByte(args[2]);
                    }
                    if (arg_count > 3)
                    {
                        if (arg_count == 4)
                        {
                            if (args[3] != "_")
                            {
                                replacement_size_ish = Convert.ToByte(args[3]);
                            }
                        }
                        else
                        {
                            throw new ArgumentException("too many arguments, 4 max");
                        }
                    }
                }
            }
            writer.write("precomputing");
            init();
            var source = "../../../pics/";

            writer.write("loading pic");
            var pic = new System.Drawing.Bitmap(System.Drawing.Image.FromFile(source + filename));
            var pic2 = new img(pic);
            var result = upscale(pic2, scoring_function_index, scale, replacement_size_ish, 4).to_bitmap();

            writer.write("saving result");
            result.Save(source + "result.png", System.Drawing.Imaging.ImageFormat.Png);
            writer.write("clearing up");
            pic.Dispose();
            result.Dispose();
            writer.write("done");
            Console.ReadLine();
        }
Пример #7
0
        // cannot process close to the edge yet
        public static img trans(img Base, img style,
                                Func <img, img, Int32, Int32, Int32, Int32, Int32, float> score,
                                UInt16 replacement_size, byte verbosity = 3)
        {
            if (verbosity > 4)
            {
                throw new ArgumentException("4 is the maximum verbosity");
            }
            if (score == null)
            {
                throw new ArgumentException("A scoring function is required.");
            }
            Int32 replacement_size2 = replacement_size;

            if (replacement_size2 % 2 == 0)
            {
                throw new ArgumentException("replacement_size must be an odd number");
            }
            UInt32 denominator = (UInt32)(verbosity > 3 ? 1000000 : 1000);
            byte   numerator = 1, least_denominator = verbosity > 3 ? (byte)100 : (byte)20, cycle_pos = 0, best_deviations_count = 5;
            Int32  base_x, base_y,
                   base_and_result_width = Base.RGB.GetLength(0), base_and_result_height = Base.RGB.GetLength(1),
                   style_width = style.RGB.GetLength(0), style_height = style.RGB.GetLength(1),
                   base_and_result_width_subtract_replacment_size  = base_and_result_width - replacement_size2,
                   base_and_result_height_subtract_replacment_size = base_and_result_height - replacement_size2,
                   style_width_subtract_replacment_size            = style_width - replacement_size2,
                   style_height_subtract_replacment_size           = style_height - replacement_size2,
                   half_replacement_size = (Int32)(replacement_size2 * 0.5f);
            var    result = new img(base_and_result_width, base_and_result_height);
            UInt64 pixel_count = 0, expected_pixels = (UInt64)(base_and_result_width_subtract_replacment_size *
                                                               base_and_result_height_subtract_replacment_size);

            if (verbosity > 0)
            {
                writer.write_then_inc("style transfer");
            }
            var region_comparisons = (UInt64)base_and_result_width_subtract_replacment_size *
                                     (UInt64)base_and_result_height_subtract_replacment_size *
                                     (UInt64)style_width_subtract_replacment_size *
                                     (UInt64)style_height_subtract_replacment_size;

            if (verbosity > 1)
            {
                writer.write("replacement_size: " + replacement_size);
                writer.write("The load is about " +
                             (UInt64)Math.Round(region_comparisons * (UInt64)replacement_size * (UInt64)replacement_size * 0.000000001f) +
                             " billion pixel pair comparisons.");
            }
            if (verbosity > 2)
            {
                writer.write("Or (" + (UInt64)Math.Round(region_comparisons * 0.000001f) +
                             " million region comparisons) or (" + (UInt64)Math.Round(expected_pixels * 0.001f) +
                             " thousand pixels of base/result resolved (" + expected_pixels + ")).");
                writer.write("base and result width: " + base_and_result_width);
                writer.write("base and result height: " + base_and_result_height);
                writer.write("style width: " + style_width);
                writer.write("style height: " + style_height);
                writer.write("base and result width subtract replacment size: " + base_and_result_width_subtract_replacment_size);
                writer.write("base and result height subtract replacment size: " + base_and_result_height_subtract_replacment_size);
                writer.write("style width subtract replacment size: " + style_width_subtract_replacment_size);
                writer.write("style height subtract replacment size: " + style_height_subtract_replacment_size);
            }

            for (base_x = 0; base_x < base_and_result_width_subtract_replacment_size; base_x++)
            {
                for (base_y = 0; base_y < base_and_result_height_subtract_replacment_size; base_y++)
                {
                    if (verbosity > 1)
                    {
                        while ((float)pixel_count / expected_pixels > (float)numerator / denominator)
                        {
                            writer.write("" + numerator + " / " + denominator);
                            if (denominator == least_denominator)
                            {
                                numerator++;
                            }
                            else
                            {
                                denominator = (UInt32)(denominator * (cycle_pos % 3 == 1 ? 0.4f : 0.5f));
                            }
                            cycle_pos++;
                        }
                    }
                    pixel_count++;

                    var best_deviations_rgb = new RGB[style_width_subtract_replacment_size, best_deviations_count];
                    var best_deviations     = new float[style_width_subtract_replacment_size, best_deviations_count];
                    {
                        byte pos, pos2;
                        for (pos = 0; pos < style_width_subtract_replacment_size; pos++)
                        {
                            for (pos2 = 0; pos2 < best_deviations_count; pos2++)
                            {
                                best_deviations[pos, pos2] = float.MaxValue;
                            }
                        }
                    }

                    Int32 pass = 0, worst_x = 0;
                    var   best_columns       = new Int32[best_deviations_count];
                    var   best_columns_value = new float[best_deviations_count];
                    var   mut = new Mutex();

                    // OpenCL/CUDA (or GLSL even) here, proposal 'a'.
                    System.Threading.Tasks.Parallel.For(0, style_width_subtract_replacment_size, style_x =>
                    {
                        // GPU proposal 'b'.
                        byte pos;
                        float best_value = float.MaxValue;
                        Int32 worst_pos  = 0;
                        for (Int32 style_y = 0; style_y < style_height_subtract_replacment_size; style_y++)
                        {
                            // GPU proposal 'c', see col_sim_inc5 in Score.cs for proposal 'd'.
                            float deviation = score(Base, style, base_x, base_y, style_x, style_y, replacement_size2);
                            // end 'c'
                            pass++;

                            if (deviation <= best_deviations[style_x, worst_pos])
                            {
                                best_deviations_rgb[style_x, worst_pos] = style[style_x + half_replacement_size, style_y + half_replacement_size];
                                best_deviations[style_x, worst_pos]     = deviation;
                                for (pos = 0; pos < best_deviations_count; pos++)
                                {
                                    if (best_deviations[style_x, pos] > best_deviations[style_x, worst_pos])
                                    {
                                        worst_pos = pos;
                                    }
                                }

                                // Need the best value, as the best columns are those containing by the best matches.
                                if (deviation < best_value)
                                {
                                    best_value = deviation;
                                }
                            }
                        }
                        // end 'b'

                        // code by Tim
                        {
                            mut.WaitOne();

                            // The n best elements are contained in the n best columns, as ordered by best match in that column.
                            if (best_value < best_columns_value[worst_x])
                            {
                                // Replace the worst x with a better one (mutex avoids race condition).
                                best_columns[worst_x]       = style_x;
                                best_columns_value[worst_x] = best_value;
                                // Find the new worst x.
                                for (pos = 0; pos < best_deviations_count; pos++)
                                {
                                    if (best_columns_value[pos] > best_columns_value[worst_x])
                                    {
                                        worst_x = pos;
                                    }
                                }
                            }

                            mut.ReleaseMutex();
                        }
                    });
                    // end 'a'

                    result[base_x + half_replacement_size, base_y + half_replacement_size] =
                        RGB_from_candidate_matches(best_deviations, best_deviations_rgb, best_columns);
                }
            }

            if (verbosity > 0)
            {
                writer.write("Pixels of base/result calculated: " + pixel_count);
                if (pixel_count < expected_pixels)
                {
                    writer.write("ERROR: Skipped some pixels?");
                }
                if (pixel_count > expected_pixels)
                {
                    writer.write("ERROR: Duplicated pixels?");
                }
                writer.dec();
            }

            return(result);
        }