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."); } }
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); }
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; }
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}"); }
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; })); }
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); }
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); }
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); }
public MainWindow() { InitializeComponent(); InitializeViews(); LogPanel.Log("Ready."); }
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(); } }