private void Image_MouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e) { if (!is_mouse_in) { return; } Point mouse_position = e.GetPosition(image); mouse_position.X /= image.ActualWidth; mouse_position.Y /= image.ActualHeight; selected_x = mouse_position.X * image_width; selected_y = mouse_position.Y * image_height; //LogPanel.Log(mouse_position.ToString()); try { if (points == null) { LogPanel.Log("no points selected."); } ImagePoint nearest_point = points[0]; foreach (var p in points) { if (Math.Pow(p.x - selected_x, 2) + Math.Pow(p.y - selected_y, 2) < Math.Pow(nearest_point.x - selected_x, 2) + Math.Pow(nearest_point.y - selected_y, 2)) { nearest_point = p; } } selected_x = nearest_point.x; selected_y = nearest_point.y; LogPanel.Log($"selected: x = {nearest_point.x}, y = {nearest_point.y}, importance = {nearest_point.importance}."); PointSelected?.Invoke(nearest_point); } finally { DrawDashLines(); } }
protected override MyImageD GetImageDInternal() { MyImageD imgd = new MyImageD(imgd_provider.GetImageD()); var points = points_provider.GetPoints(); LogPanel.Log($"[PlotPoints] {points.Count} points."); if (points.Count > 0) { MyImageD cross_img = new MyImageD(new double[imgd.data.Length], imgd); double mn = points.Min(p => p.importance), mx = points.Max(p => p.importance); foreach (var p in points.Reverse <ImagePoint>()) { Utils.GetHeatColor((p.importance - mn) / (mx - mn), out double r, out double g, out double b); plot_cross(cross_img, p.x, p.y, r, g, b); } Parallel.For(0, imgd.height, i => { for (int j = 0; j < imgd.width; j++) { int k = i * imgd.stride + j * 4; double ratio = cross_img.data[k + 3]; imgd.data[k + 0] = (1 - ratio) * imgd.data[k + 0] + cross_img.data[k + 0]; imgd.data[k + 1] = (1 - ratio) * imgd.data[k + 1] + cross_img.data[k + 1]; imgd.data[k + 2] = (1 - ratio) * imgd.data[k + 2] + cross_img.data[k + 2]; } }); } return(imgd); }
public static void AddSpring(PlaneImage me, PlaneImage other, double from_x, double from_y, double to_x, double to_y) { double dx = (to_x - 0.5 * other.image_provider.GetImageD().width) - (from_x - 0.5 * me.image_provider.GetImageD().width); double dy = (to_y - 0.5 * other.image_provider.GetImageD().height) - (from_y - 0.5 * me.image_provider.GetImageD().height); LogPanel.Log($"dx={dx}, dy={dy}"); me.springs.Add(new Spring(me, other, -dx, -dy)); other.springs.Add(new Spring(other, me, dx, dy)); }
protected override List <ImagePoint> GetPointsInternal() { List <ImagePoint <T> > ans = new List <ImagePoint <T> >(); double scale = 1; StringBuilder sb = new StringBuilder(); for (int i = 0; i < points_providers.Count; i++, scale *= scale_factor) { var points = points_providers[i].GetPoints().Cast <ImagePoint <T> >() .Select(p => new ImagePoint <T>(p.x / scale, p.y / scale, p.importance, p.content)); sb.AppendLine($"{points.Count()} points from scale {scale}"); ans.AddRange(points); } LogPanel.Log(sb.ToString()); return(ans.Cast <ImagePoint>().ToList()); }
async void StartSimulation() { int kase_self = System.Threading.Interlocked.Increment(ref kase); await Task.Run(() => { List <IPointsProvider> points_providers = source_image_panel.GetImages().Select(i => new ImageD_Providers.ImageD_Cache(i.ToImageD()) as IImageD_Provider).Select(i => new PointsProviders.MSOP_DescriptorVector(new PointsProviders.HarrisCornerDetector(i), new MatrixProviders.GrayScale(i)) as IPointsProvider).ToList(); List <IImageD_Provider> image_providers = source_image_panel.GetImages().Select((i, idx) => new ImageD_Providers.PlotPoints(new ImageD_Providers.ImageD_Cache(i.ToImageD()), points_providers[idx]) as IImageD_Provider).ToList(); var provider = new PlaneImages(image_providers, 1000, 600); image_container.Dispatcher.Invoke(() => image_container.Content = new ImageViewer(provider, false)); LogPanel.Log("searching features..."); provider.GetImageD(); LogPanel.Log("matching..."); var points = points_providers.Select(pp => pp.GetPoints().Select(ps => (ps as ImagePoint <PointsProviders.MSOP_DescriptorVector.Descriptor>)).ToList()).ToList(); for (int i = 0; i < points.Count; i++) { for (int j = i + 1; j < points.Count; j++) { List <ImagePoint <PointsProviders.MSOP_DescriptorVector.Descriptor> > p1s = points[i], p2s = points[j]; List <Tuple <double, double, double, double, double> > candidates = new List <Tuple <double, double, double, double, double> >(); foreach (var p1 in p1s) { if (p1.content.try_match(p2s, out ImagePoint p2)) { candidates.Add(Tuple.Create(p1.content.difference((p2 as ImagePoint <PointsProviders.MSOP_DescriptorVector.Descriptor>).content), p1.x, p1.y, p2.x, p2.y)); } } candidates.Sort((p1, p2) => p1.Item1.CompareTo(p2.Item1)); for (int k = 0; k < candidates.Count; k++) { var c = candidates[k]; PlaneImage.AddSpring(provider.images[i], provider.images[j], c.Item2, c.Item3, c.Item4, c.Item5); } } } LogPanel.Log("ok"); while (kase_self == kase) { provider.update_speed(0.1); provider.update_position(); provider.ResetSelf(); provider.GetImageD(); } }); }
public CorrectiveCylinderImages(List <IImageD_Provider> image_providers, int width, int height) : base( image_providers, //image_providers.Select(i=>new ImageD_Providers.PlotPoints(i, get_features_provider(i)) as IImageD_Provider).ToList(), width, height) { points_providers = image_providers.Select(img => get_features_provider(img)).ToList(); { var provider = image_providers[0]; double scale = 1; for (int i = 0; i < 7; i++, scale *= 0.5) { MyImageD img = provider.GetImageD(); LogPanel.Log($"scale={scale}, width={img.width}, height={img.height}, stride={img.stride}, avg={img.data.Sum() / img.data.Length}"); LogPanel.Log(img); provider = new ImageD_Providers.GaussianBlur(provider, 1); provider = new ImageD_Providers.Scale(provider, 0.5); } } }
protected override MyImageD GetImageDInternal() { MyImageD image = new MyMatrix(new double[height, width]).ToGrayImageD(); double min_h = cylinder_images.Min(i => (i.displace_y - 0.5 * i.height) / i.focal_length), max_h = cylinder_images.Max(i => (i.displace_y + 0.5 * i.height) / i.focal_length); LogPanel.Log($"min_h: {min_h}, max_h: {max_h}"); System.Threading.Tasks.Parallel.For(0, height, i => { for (int j = 0; j < width; j++) { double r = 0, g = 0, b = 0; double weight_sum = 0; foreach (var img in cylinder_images) { if (img.sample_pixel(((double)j / width) * 2.0 * Math.PI, (i * max_h + (height - 1 - i) * min_h) / (height - 1), out double _r, out double _g, out double _b, out double distance_to_corner)) { r += distance_to_corner * _r; g += distance_to_corner * _g; b += distance_to_corner * _b; weight_sum += distance_to_corner; } }
private static void Log(object message, LogType logType) { string log = message?.ToString() ?? ""; LogPanel.Log(log, logType); switch (logType) { case LogType.Assert: case LogType.Log: Loader.OnLogMessage(log); break; case LogType.Warning: Loader.OnLogWarning(log); break; case LogType.Error: case LogType.Exception: Loader.OnLogError(log); break; } }
async void StartSimulation() { int kase_self = System.Threading.Interlocked.Increment(ref kase); await Task.Run(() => { var images = source_image_panel.GetImages(); List <IPointsProvider> points_providers = images.Select(i => new ImageD_Providers.ImageD_Cache(i.ToImageD()) as IImageD_Provider).Select(i => new PointsProviders.MSOP_DescriptorVector(new PointsProviders.HarrisCornerDetector(i), new MatrixProviders.GrayScale(i)) as IPointsProvider).ToList(); List <IImageD_Provider> image_providers = images.Select((i, idx) => new ImageD_Providers.PlotPoints(new ImageD_Providers.ImageD_Cache(i.ToImageD()), points_providers[idx]) as IImageD_Provider).ToList(); var global_viewer = new Func <PlaneImages>(() => { return(new PlaneImages(image_providers, 5000, 600)); })(); int n = global_viewer.images.Count; image_container.Dispatcher.Invoke(() => image_container.Content = new ImageViewer(global_viewer, false)); LogPanel.Log("searching features..."); Parallel.For(0, n, i => image_providers[i].GetImageD()); global_viewer.GetImageD(); LogPanel.Log("matching..."); var points = points_providers.Select(pp => pp.GetPoints().Select(ps => (ps as ImagePoint <PointsProviders.MSOP_DescriptorVector.Descriptor>)).ToList()).ToList(); var get_displacement = new Func <int, int, Tuple <double, double, int> >((i, j) => { List <ImagePoint <PointsProviders.MSOP_DescriptorVector.Descriptor> > p1s = points[i], p2s = points[j]; List <Tuple <double, double, double, double> > candidates = new List <Tuple <double, double, double, double> >(); Parallel.For(0, p1s.Count, _ => { var p1 = p1s[_]; if (p1.content.try_match(p2s, out ImagePoint p2)) { IImageD_Provider me = image_providers[i], other = image_providers[j]; lock (candidates) candidates.Add(new Tuple <double, double, double, double>( p1.x - 0.5 * me.GetImageD().width, p1.y - 0.5 * me.GetImageD().height, p2.x - 0.5 * other.GetImageD().width, p2.y - 0.5 * other.GetImageD().height)); //candidates.Add(Tuple.Create(p1.content.difference((p2 as ImagePoint<PointsProviders.MSOP_DescriptorVector.Descriptor>).content), p1.x, p1.y, p2.x, p2.y)); } }); var ans = Utils.VoteInliners(candidates, 10); return(new Tuple <double, double, int>( ans.Average(_ => { var v = candidates[_]; return v.Item3 - v.Item1; }), ans.Average(_ => { var v = candidates[_]; return v.Item4 - v.Item2; }), ans.Count)); }); { bool[] vis = new bool[n]; SortedSet <Tuple <int, int, Tuple <double, double, int> > > edge_list = new SortedSet <Tuple <int, int, Tuple <double, double, int> > >(new comparer1()); var add_edges = new Action <int>(u => { Parallel.For(0, n, i => { if (!vis[i]) { var edge = new Tuple <int, int, Tuple <double, double, int> >(u, i, get_displacement(u, i)); lock (edge_list) edge_list.Add(edge); } }); }); vis[0] = true; global_viewer.images[0].set_position(0, 0); add_edges(0); while (edge_list.Count > 0) { var edge = edge_list.First(); edge_list.Remove(edge); if (vis[edge.Item2]) { continue; } LogPanel.Log($"edge: {edge.Item1} → {edge.Item2}"); vis[edge.Item2] = true; var u = global_viewer.images[edge.Item1]; global_viewer.images[edge.Item2].set_position(u.center_x - edge.Item3.Item1, u.center_y - edge.Item3.Item2); add_edges(edge.Item2); } } global_viewer.move_to_center(); global_viewer.ResetSelf(); global_viewer.GetImageD(); LogPanel.Log("ok"); }); }
// [ αcosθ -αsinθ x' ][x] [xαcosθ-yαsinθ+x'] // [ αsinθ αcosθ y' ][y] = [xαsinθ+yαcosθ+y'] // [ p q 1 ][1] [ xp+qy+1 ] // h=((xαsinθ+yαcosθ+y')/(xp+qy+1))/sqrt(f*f+x*x) // w=t+atan(((xαcosθ-yαsinθ+x')/(xp+qy+1))/f) // params: α, θ, x', y', f, t // have: pairwise (h,w), (H,W) // minimize: β(h-H)^2+(w-W)^2 // // d: β(h-H)(dh-dH)+(w-W)(dw-dW)=0 // down_q=(xp+qy+1)*sqrt(f*f+x*x) // down_f=(xp+qy+1)*f // inside_tan=(xαcosθ-yαsinθ+x')/down_f // one_x_2=1+inside_tan*inside_tan // // dh/dα: (xsinθ+ycosθ)/down_q // dw/dα: ((xcosθ-ysinθ)/down_f)/one_x_2 // dh/dθ: (xαcosθ-yαsinθ)/down_q // dw/dθ: ((-xαsinθ-yαcosθ)/down_f)/one_x_2 // dh/dx': 0 // dw/dx': (1/down_f)/one_x_2 // dh/dy': 1/down_q // dw/dy': 0 // dh/df: ((xαsinθ+yαcosθ+y')/(xp+qy+1))*(-0.5/sqrt(f*f+x*x)^3)*(2*f) // dw/df: (-((xαcosθ-yαsinθ+x')/(xp+qy+1))/f^2)/one_x_2 // dh/dt: 0 // dw/dt: 1 // dh/dp: (-((xαsinθ+yαcosθ+y')/sqrt(f*f+x*x))/(xp+qy+1)^2)*x // dw/dp: x*(-((xαcosθ-yαsinθ+x')/f)/(xp+qy+1)^2)/one_x_2 // dh/dq: (-((xαsinθ+yαcosθ+y')/sqrt(f*f+x*x))/(xp+qy+1)^2)*y // dw/dq: y*(-((xαcosθ-yαsinθ+x')/f)/(xp+qy+1)^2)/one_x_2 /// <summary> /// /// </summary> /// <param name="error_weight_h"></param> /// <param name="matches">matched points of image positions</param> /// <param name="alpha"></param> /// <param name="theta"></param> /// <param name="dx"></param> /// <param name="dy"></param> /// <param name="df"></param> /// <param name="dt"></param> public (Transform, double) get_derivatives(List <Tuple <Tuple <double, double>, Tuple <double, double>, CylinderImage> > matches) { Transform derivative = new Transform(null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); double total_error = 0; foreach (var match in matches) { // w=t+atan(((xαcosθ+yα(scosθ-sinθ)+x')/(xp+qy+1))/f) // h=((xαsinθ+yα(ssinθ+cosθ)+y')/(xp+qy+1))/sqrt(f*f+x*x) (double x, double y) = (match.Item1.Item1 - 0.5 * width, match.Item1.Item2 - 0.5 * height); double pq_term = x * perspective_x + y * perspective_y + 1; double fx_term = Math.Sqrt(focal_length * focal_length + x * x); double sin = Math.Sin(rotation_theta), cos = Math.Cos(rotation_theta); double w_term = scalar_x * x * cos + scalar_y * y * (skew * cos - sin); double dw_term = scalar_x * x * -sin + scalar_y * y * (skew * -sin - cos); double h_term = scalar_x * x * sin + scalar_y * y * (skew * sin + cos); double dh_term = scalar_x * x * cos + scalar_y * y * (skew * cos - sin); double inside_tan = (w_term + displace_x) / pq_term / focal_length; double one_x_2 = 1 + inside_tan * inside_tan; (double w1, double h1) = image_point_to_camera(match.Item1.Item1, match.Item1.Item2); { (double w_check, double h_check) = ( Utils.Mod2PI(center_direction + Math.Atan((w_term + displace_x) / pq_term / focal_length)), (h_term + displace_y) / pq_term / fx_term); double error = Math.Sqrt(Math.Pow(w_check - w1, 2) + Math.Pow(h_check - h1, 2)); if (error >= 1e-9) { LogPanel.Log($"w: {w1}→{w_check}, h: {h1}→{h_check}"); } System.Diagnostics.Trace.Assert(error < 1e-9); } (double w2, double h2) = match.Item3.image_point_to_camera(match.Item2.Item1, match.Item2.Item2); if (w2 - w1 > Math.PI) { w1 += 2.0 * Math.PI; } else if (w1 - w2 > Math.PI) { w2 += 2.0 * Math.PI; } var make = new Func <double, double, double>((dw, dh) => { return(2 * ((w1 - w2) * dw + (h1 - h2) * dh)); //return ((w1 - w2) * dw + (h1 - h2) * dh) / //Math.Sqrt(Math.Pow(w1 - w2, 2) + Math.Pow(h1 - h2, 2)); }); derivative.scalar_x += make(((x * cos / pq_term / focal_length) / one_x_2), (x * sin / pq_term / fx_term)); derivative.scalar_y += make(((y * (skew * cos - sin) / pq_term / focal_length) / one_x_2), (y * (skew * sin + cos) / pq_term / fx_term)); derivative.rotation_theta += make((((dw_term) / pq_term / focal_length) / one_x_2), ((dh_term) / pq_term / fx_term)); derivative.displace_x += make(((1 / pq_term / focal_length) / one_x_2), 0); derivative.displace_y += make(0, (1 / pq_term / fx_term)); derivative.skew += make(((y * cos / pq_term / focal_length) / one_x_2), (y * sin / pq_term / fx_term)); derivative.focal_length += make(((-(w_term + displace_x) / (pq_term * focal_length * focal_length)) / one_x_2), (((h_term + displace_y) / pq_term) * (-0.5 * Math.Pow(focal_length * focal_length + x * x, -1.5)) * (2 * focal_length))); derivative.center_direction += make(1, 0); double dw_perspective = (-(w_term + displace_x) / (focal_length * pq_term * pq_term)) / one_x_2; double dh_perspective = -(h_term + displace_y) / (fx_term * pq_term * pq_term); derivative.perspective_x += make((dw_perspective * x), (dh_perspective * x)); derivative.perspective_y += make((dw_perspective * y), (dh_perspective * y)); total_error += (h1 - h2) * (h1 - h2) + (w1 - w2) * (w1 - w2); } // regularization //const double regularization = 1e-5; //derivative.perspective_x += regularization * 2 * perspective_x; //derivative.perspective_y += regularization * 2 * perspective_y; //total_error += regularization * (perspective_x * perspective_x + perspective_y * perspective_y); return(derivative, total_error); }
private void search_cycle() { System.Text.StringBuilder sb = new System.Text.StringBuilder(); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (j > 0) { sb.Append('\t'); } sb.Append(get_displacement(i, j).Item3); } sb.AppendLine(); } LogPanel.Log("matrix of acceptants:"); LogPanel.Log(sb.ToString()); LogPanel.Log("building matching graph..."); List <List <Tuple <int, Tuple <double, double, int> > > > edges = new List <List <Tuple <int, Tuple <double, double, int> > > >(); for (int i = 0; i < n; i++) { edges.Add(new List <Tuple <int, Tuple <double, double, int> > >()); } Parallel.For(0, n, i => { for (int j = i + 1; j < n; j++) { var dis1 = get_displacement(i, j); var dis2 = get_displacement(j, i); double dx = (dis1.Item1 - dis2.Item1) / 2; double dy = (dis1.Item2 - dis2.Item2) / 2; int acceptants = Math.Min(dis1.Item3, dis2.Item3); if (acceptants >= min_num_inliners) { lock (edges[i]) edges[i].Add(new Tuple <int, Tuple <double, double, int> >(j, new Tuple <double, double, int>(dx, dy, acceptants))); lock (edges[j]) edges[j].Add(new Tuple <int, Tuple <double, double, int> >(i, new Tuple <double, double, int>(-dx, -dy, acceptants))); } //edge_list.Add(new Tuple<int, int, Tuple<double, double, int>>(i, j, new Tuple<double, double, int>(dx, dy, acceptants))); } LogPanel.Log($"finished matching from {i}"); }); LogPanel.Log("searching cycle..."); cycle = new List <int>(); dx_seq = new List <double>(); dy_seq = new List <double>(); { bool[] vis = new bool[n]; int cur = 0; while (true) { cycle.Add(cur); vis[cur] = true; int nxt_cur = -1; double dx = double.MaxValue, dy = 0; foreach (var e in edges[cur]) { if (0 < e.Item2.Item1 && e.Item2.Item1 < dx) { dx = e.Item2.Item1; dy = e.Item2.Item2; nxt_cur = e.Item1; } } dx_seq.Add(dx); dy_seq.Add(dy); cur = nxt_cur; if (cur == -1 || vis[cur]) { LogPanel.Log($"cur: {cur}, visited: " + string.Join(", ", cycle)); if (cur != cycle[0]) { throw new Exception("can't find a loop"); } break; } } } }
private void InitializeViews() { source_image_panel = new SourceImagePanel(); IImageD_Provider main_image = source_image_panel.GetImageD_Provider(0); IImageD_Provider side_image = source_image_panel.GetImageD_Provider(1); IPointsProvider <PointsProviders.MSOP_DescriptorVector.Descriptor> main_feature_points_provider = new PointsProviders.MSOP_DescriptorVector(new PointsProviders.HarrisCornerDetector(main_image), new MatrixProviders.GrayScale(main_image)); IPointsProvider <PointsProviders.MSOP_DescriptorVector.Descriptor> side_feature_points_provider = new PointsProviders.MSOP_DescriptorVector(new PointsProviders.HarrisCornerDetector(side_image), new MatrixProviders.GrayScale(side_image)); IImageD_Provider mp_merge_refined = new ImageD_Providers.PlotPoints( new ImageD_Providers.GrayImageD(new MatrixProviders.GrayScale(main_image)), main_feature_points_provider ); Controls.PointSelect main_features = new Controls.PointSelect(main_image, main_feature_points_provider); Controls.PointSelect side_features = new Controls.PointSelect(side_image, side_feature_points_provider); main_features.PointSelected += selected_point => { var main_descriptor = (selected_point as ImagePoint <PointsProviders.MSOP_DescriptorVector.Descriptor>).content; ImagePoint nearst = null; double first_min = double.MaxValue, second_min = double.MaxValue; foreach (var p in side_features.points) { double dis = main_descriptor.difference((p as ImagePoint <PointsProviders.MSOP_DescriptorVector.Descriptor>).content); if (dis < first_min) { second_min = first_min; first_min = dis; nearst = p; } else if (dis < second_min) { second_min = dis; } } if (first_min / second_min < 0.8) { LogPanel.Log($"nearst feature diff = {main_descriptor.difference((nearst as ImagePoint<PointsProviders.MSOP_DescriptorVector.Descriptor>).content)}"); side_features.ShowPoint(nearst.x, nearst.y); } else { LogPanel.Log($"nearst feature too similar, no match!"); } }; //this.Height = 500; //this.Width = 800; this.Content = new ScrollViewer { HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled, VerticalScrollBarVisibility = ScrollBarVisibility.Visible, Content = new StackPanel { Orientation = Orientation.Vertical, Children = { source_image_panel, new Grid { ColumnDefinitions = { new ColumnDefinition { Width = new GridLength(1,GridUnitType.Star) }, new ColumnDefinition { Width = new GridLength(1,GridUnitType.Star) } }, Children = { new Button { Content = "Run" }.Set(async() =>{ await Task.Run(() => { mp_merge_refined.GetImageD(); }); LogPanel.Log("done."); }).Set(0, 0), new Button { Content = "Reset" }.Set(async() =>{ await Task.Run(() => { mp_merge_refined.Reset(); }); LogPanel.Log("reseted."); }).Set(0, 1) } }, //(new ImageViewer(mp_r)), //(new ImageViewer(mp_hr)), //(new ImageViewer(mp_g)), //(new ImageViewer(mp_hg)), //(new ImageViewer(mp_b)), //(new ImageViewer(mp_hb)), new ImageViewer(mp_merge_refined,false), //new ImageViewer(main_image,false), //new Controls.PointSelect(source_image_panel,new PointsProviders.PointsCache(new List<ImagePoint>{ new ImagePoint(10,10,1),new ImagePoint(100,50,5) })) main_features, side_features } } }; }
async void StartSimulation() { //for (int seed = 0; seed < 100; seed++) //{ // int n = Utils.Rand(10, 100); // double[,] m = Utils.MatrixRandom(n, n,-10,10, seed); // double[,] i = Utils.MatrixInverse(m); // double[,] I = Utils.MatrixIdentity(n); // double[,] p = Utils.MatrixProduct(m, i); // System.Diagnostics.Trace.Assert(Utils.MatrixAreEqual(p, I, 1.0E-8)); //} int kase_self = System.Threading.Interlocked.Increment(ref kase); var image_providers = source_image_panel.GetImages().Select(i => new ImageD_Providers.ImageD_Cache(i.ToImageD()) as IImageD_Provider).ToList(); while (image_providers.Any(p => { var i = p.GetImageD(); return(i.width * i.height > 1000000); })) { LogPanel.Log($"scaling down..."); Parallel.For(0, image_providers.Count, i => { var p = image_providers[i]; image_providers[i] = new ImageD_Providers.ImageD_Cache(new ImageD_Providers.Scale(new ImageD_Providers.GaussianBlur(p, 0.5), 0.5).GetImageD()); }); } var global_viewer = new CorrectiveCylinderImages(image_providers, pixel_width, pixel_height); image_container.Content = new ScrollViewer { HorizontalScrollBarVisibility = ScrollBarVisibility.Auto, VerticalScrollBarVisibility = ScrollBarVisibility.Disabled, Content = new ImageViewer(global_viewer, false) }; await Task.Run(() => { global_viewer.InitializeOnPlane(); // stage1: false false false // stage2: true false false // stage3: false false false (roll back to stage1) // stage4: true true false // stage5: true false false (roll back to stage2) // stage6: false false false (roll back to stage1) // stage7: ... (int, int)prev_freedom = (-1, -1); int freedom = 1, cached_freedom = 1; for (DateTime time = DateTime.MinValue; ;) { //freedom = cached_freedom = 10; if (prev_freedom != (freedom, cached_freedom)) { prev_freedom = (freedom, cached_freedom); LogPanel.Log($"refine #{global_viewer.refine_count+1}: freedom: {freedom} ← {cached_freedom} / {CorrectiveCylinderImages.maximum_freedom}"); } bool verbose = false; if ((DateTime.Now - time).TotalSeconds > 30) { verbose = true; } bool result = global_viewer.Refine(freedom + (Utils.RandDouble() < 0.01 ? (Utils.RandDouble() < 0.5 ? 1 : 2) : 0), verbose); if (!result) { if (freedom > 1) { freedom--; } else { freedom = cached_freedom = cached_freedom + 1; } } else if (freedom < cached_freedom) { cached_freedom = freedom; } if (freedom > CorrectiveCylinderImages.maximum_freedom) { //System.Diagnostics.Trace.Assert(freedom == 7); LogPanel.Log("done. generating image..."); System.Diagnostics.Trace.Assert(!global_viewer.Refine(CorrectiveCylinderImages.maximum_freedom, true)); for (int i = 0; i < global_viewer.cylinder_images.Count; i++) { LogPanel.Log($"params of image[{i}]:"); LogPanel.Log(global_viewer.cylinder_images[i].transform.ToString()); } LogPanel.Log("ok."); return; } //if (verbose) //{ // for (int i = 1; i <= CorrectiveCylinderImages.maximum_freedom; i++) // { // if (!global_viewer.Test(i, false)) LogPanel.Log($"problem entry: {i}"); // else LogPanel.Log($"entry {i} seems ok."); // } //} if (verbose) { time = DateTime.Now; } } }); }