예제 #1
0
        public void OpenImages()
        {
            LogPanel.Log("Opening images...");
            var dialog = new OpenFileDialog {
                Multiselect = true
            };

            if (dialog.ShowDialog() == true)
            {
                var ans = dialog.FileNames;
                if (ans != null)
                {
                    images = new List <MyImage>();
                    foreach (var f in ans)
                    {
                        LogPanel.Log(f);
                        images.Add(new MyImage(f));
                    }
                    images = images.OrderBy(v => v.exposure).ToList();
                    LogPanel.Log($"{ans.Length} files selected.");
                    ShowImages();
                }
                else
                {
                    LogPanel.Log("No files selected.");
                }
            }
            else
            {
                LogPanel.Log("Canceled.");
            }
        }
예제 #2
0
        protected override byte[] Solve(MyImageD image)
        {
            byte[] ans = new byte[image.data.Length];
            double Le  = 0;

            for (int i = 0; i < image.height; i++)
            {
                for (int j = 0; j < image.width; j++)
                {
                    int k = i * image.stride + j * 4;
                    if (!(image.data[k + 0] + image.data[k + 1] + image.data[k + 2] >= 0))
                    {
                        LogPanel.Log($"Weird: {image.data[k + 0]}, {image.data[k + 1]}, {image.data[k + 2]}");
                    }
                    Le += Math.Log(1 + image.data[k + 0] + image.data[k + 1] + image.data[k + 2]);
                }
            }
            //LogPanel.Log($"Sum of Log(Lw): {Le}");
            Le = Math.Exp(Le / (image.height * image.width));
            LogPanel.Log($"alpha = {alpha}, Lwhite = {Lwhite}, Le = {Le}");
            for (int i = 0; i < image.height; i++)
            {
                for (int j = 0; j < image.width; j++)
                {
                    int k = i * image.stride + j * 4;
                    ans[k + 0] = HeatToByte(alpha, Le, image.data[k + 0]);
                    ans[k + 1] = HeatToByte(alpha, Le, image.data[k + 1]);
                    ans[k + 2] = HeatToByte(alpha, Le, image.data[k + 2]);
                    ans[k + 3] = 255;
                }
            }
            return(ans);
        }
예제 #3
0
파일: App.xaml.cs 프로젝트: fsps60312/HDR2
 private void App_DispatcherUnhandledException1(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
 {
     // Process unhandled exception
     LogPanel.Log($"App: [Unhandled Exception]\n{e.Exception}");
     // Prevent default unhandled exception processing
     e.Handled = true;
 }
예제 #4
0
        public void SaveImage()
        {
            var dialog = new Microsoft.Win32.SaveFileDialog();

            if (dialog.ShowDialog() != true)
            {
                LogPanel.Log("Canceled."); return;
            }
            var stream = dialog.OpenFile();

            image.ToBitmapSource().Save(stream);
            LogPanel.Log($"Saved as {dialog.FileName}");
        }
예제 #5
0
        public async Task <MyImage> ProcessImage(List <MyImage> images)
        {
            HDRSolver hdr = null;

            foreach (var p in radio_HDR)
            {
                if (p.Key.IsChecked == true)
                {
                    hdr = p.Value(); break;
                }
            }
            if (hdr == null)
            {
                LogPanel.Log("No HDR selected."); return(null);
            }
            ToneMappingSolver tone = null;

            foreach (var p in radio_ToneMapping)
            {
                if (p.Key.IsChecked == true)
                {
                    tone = p.Value(); break;
                }
            }
            if (tone == null)
            {
                LogPanel.Log("No Tone-Mapping selected."); return(null);
            }
            return(await Task.Run(() =>
            {
                LogPanel.Log("Running HDR...");
                foreach (var image in images)
                {
                    hdr.AddImage(image);
                }
                MyImageD heat_map = hdr.RunHDR();
                LogPanel.Log("Running Tone Mapping...");
                MyImage ans = tone.RunToneMapping(heat_map);
                LogPanel.Log("OK.");
                return ans;
            }));
        }
예제 #6
0
        static double GetImageExposure(string filename)
        {
            var directories = ImageMetadataReader.ReadMetadata(filename);
            var ToDouble    = new Func <string, double>(s =>
            {
                if (s.EndsWith(" sec"))
                {
                    s = s.Remove(s.Length - " sec".Length);
                    if (s.IndexOf('/') == -1)
                    {
                        return(double.Parse(s));
                    }
                    else
                    {
                        var t = s.Split('/');
                        if (t.Length == 2)
                        {
                            return(double.Parse(t[0]) / double.Parse(t[1]));
                        }
                    }
                }
                return(double.NaN);
            });

            counter++;
            foreach (var directory in directories)
            {
                foreach (var tag in directory.Tags)
                {
                    if (counter <= 1)
                    {
                        LogPanel.Log($"directory: {directory.Name} \ttag: {tag.Name} \tdescription: {tag.Description}");
                    }
                    if (directory.Name == "Exif SubIFD" && tag.Name == "Exposure Time")
                    {
                        return(ToDouble(tag.Description));
                    }
                }
            }
            return(double.NaN);
        }
예제 #7
0
 public List <MyImage> GetImages()
 {
     if (images == null)
     {
         LogPanel.Log("Warning: [SourceImagePanel] images == null");
     }
     if (images.Count >= 1 && double.IsNaN(images[0].exposure))
     {
         LogPanel.Log("Warning: [SourceImagePanel] image file doesn't contain exposure time information, generating according to power of 2...");
         //images.Sort((a, b) =>
         //{
         //    int ans = 0;
         //    int height = a.height, width = a.width,stride=a.stride;
         //    for (int i = 0; i < height; i++)
         //    {
         //        for (int j = 0; j < width; j++)
         //        {
         //            int k = i * stride + j * 4;
         //            if (!(a.data[k + 0] == 255 && a.data[k + 1] == 0 && a.data[k + 2] == 0) &&
         //                !(b.data[k + 0] == 255 && b.data[k + 1] == 0 && b.data[k + 2] == 0))
         //            {
         //                int a_c = a.data[k + 0] + a.data[k + 1] + a.data[k + 2];
         //                int b_c = b.data[k + 0] + b.data[k + 1] + b.data[k + 2];
         //                var c= a_c.CompareTo(b_c);
         //                ans += c > 0 ? 1 : c < 0 ? -1 : 0;
         //            }
         //        }
         //    }
         //    return ans;
         //});
         double exposure = 1;
         foreach (var img in images)
         {
             img.SetExposure(exposure);
             exposure /= 2;
         }
         ShowImages();
     }
     return(images);
 }
예제 #8
0
        protected override byte[] Solve(MyImageD image)
        {
            double mx = double.MinValue, mn = double.MaxValue;

            for (int i = 0; i < image.height; i++)
            {
                for (int j = 0; j < image.width; j++)
                {
                    int    k = i * image.stride + j * 4;
                    double v = Math.Log10(1 + image.data[k + 0] + image.data[k + 1] + image.data[k + 2]);
                    if (v > mx)
                    {
                        mx = v;
                    }
                    if (v < mn)
                    {
                        mn = v;
                    }
                }
            }
            LogPanel.Log($"min heat: {Math.Pow(10, mn).ToString("E")}");
            LogPanel.Log($"max heat: {Math.Pow(10, mx).ToString("E")}");
            byte[] ans = new byte[image.data.Length];
            for (int i = 0; i < image.height; i++)
            {
                for (int j = 0; j < image.width; j++)
                {
                    int    k = i * image.stride + j * 4;
                    double v = Math.Log10(1 + image.data[k + 0] + image.data[k + 1] + image.data[k + 2]);
                    GetHeatColor((v - mn) / (mx - mn), out byte r, out byte g, out byte b);
                    ans[k + 0] = b;
                    ans[k + 1] = g;
                    ans[k + 2] = r;
                    ans[k + 3] = 255;
                }
            }
            return(ans);
        }
예제 #9
0
 public MainWindow()
 {
     InitializeComponent();
     InitializeViews();
     LogPanel.Log("Ready.");
 }
예제 #10
0
        private void Optimize()
        {
            for (int i = 0; i < g_mapping.Length; i++)
            {
                g_mapping[i] = i;
            }
            E = 0;
            Dictionary <double, int[]> data = new Dictionary <double, int[]>();

            foreach (var img in images)
            {
                if (!data.ContainsKey(img.exposure))
                {
                    data.Add(img.exposure, new int[256]);
                }
                var s = img.data;
                for (int i = 0; i < height; i++)
                {
                    for (int j = 0; j < width; j++)
                    {
                        int  k = i * stride + j * 4;
                        byte b = s[k + 0];
                        byte g = s[k + 1];
                        byte r = s[k + 2];
                        if (!(r == 0 && g == 0 && b == 255))
                        {
                            ++data[img.exposure][r];
                            ++data[img.exposure][g];
                            ++data[img.exposure][b];
                        }
                    }
                }
            }
            /// arg min sum(w(z)*(g(z)-E*t)^2)
            /// = arg min sum(w(z)*(g(z)g(z)-2g(z)Et+EEtt))
            /// dE: sum(w(z)*(-2g(z)t+2Ett))=0
            ///     sum(w(z)ttE-w(z)g(z)t)=0
            /// dg: sum(w(z)*(2g(z)-2Et), for g of specular z)=0
            ///     sum(g(z)-Et)=0
            var optimize_E = new Action(() =>
            {
                double a = 0, b = 0; // ax=b
                foreach (var p in data)
                {
                    double exposure = p.Key;
                    var cnts        = p.Value;
                    for (byte z = 0; ; z++)
                    {
                        if (cnts[z] > 0)
                        {
                            Trace.Assert(!double.IsNaN(g_mapping[z]));
                            a += cnts[z] * w(z, exposure) * exposure * exposure;
                            b += cnts[z] * w(z, exposure) * g_mapping[z] * exposure;
                        }
                        if (z == 255)
                        {
                            break;
                        }
                    }
                }
                E = b / a;
            });
            var optimize_g = new Action(() =>
            {
                for (byte z = 0; ; z++)
                {
                    double a = 0, b = 0;//ax=b, x is g(z)
                    foreach (var p in data)
                    {
                        double exposure = p.Key;
                        var cnts        = p.Value;
                        a += cnts[z];
                        b += cnts[z] * E * exposure;
                    }
                    if (a != 0)
                    {
                        g_mapping[z] = b / a;
                    }
                    else
                    {
                        g_mapping[z] = double.NaN;
                    }
                    if (z == 255)
                    {
                        break;
                    }
                }
                Trace.Assert(!double.IsNaN(g_mapping[128]));
                double avg = g_mapping[128];
                for (int z = 0; z < 256; z++)
                {
                    g_mapping[z] /= avg;
                }
            });

            LogPanel.Log($"Converging from E = {E}");
            for (double origin_E = E + 1; Math.Abs(origin_E - E) > 1e-9;)
            {
                origin_E = E;
                optimize_E();
                LogPanel.Log($"E = {E}");
                optimize_g();
            }
        }