001/******************************************************************************* 002 * This software is provided as a supplement to the authors' textbooks on digital 003 * image processing published by Springer-Verlag in various languages and editions. 004 * Permission to use and distribute this software is granted under the BSD 2-Clause 005 * "Simplified" License (see http://opensource.org/licenses/BSD-2-Clause). 006 * Copyright (c) 2006-2023 Wilhelm Burger, Mark J. Burge. All rights reserved. 007 * Visit https://imagingbook.com for additional details. 008 ******************************************************************************/ 009package Ch10_Line_Fitting; 010 011 012import ij.ImagePlus; 013import ij.gui.GenericDialog; 014import ij.gui.NewImage; 015import ij.gui.PointRoi; 016import ij.plugin.PlugIn; 017import ij.process.ImageProcessor; 018import imagingbook.common.color.sets.BasicAwtColor; 019import imagingbook.common.geometry.basic.Pnt2d; 020import imagingbook.common.geometry.fitting.line.utils.LineSampler; 021import imagingbook.common.geometry.line.AlgebraicLine; 022import imagingbook.common.ij.DialogUtils; 023import imagingbook.common.ij.DialogUtils.DialogLabel; 024import imagingbook.common.ij.DialogUtils.DialogStringColumns; 025import imagingbook.common.ij.RoiUtils; 026import imagingbook.common.ij.overlay.ColoredStroke; 027import imagingbook.common.ij.overlay.ShapeOverlayAdapter; 028import imagingbook.common.util.ParameterBundle; 029import imagingbook.core.jdoc.JavaDocHelp; 030 031import static imagingbook.common.ij.DialogUtils.addToDialog; 032import static imagingbook.common.ij.DialogUtils.getFromDialog; 033 034/** 035 * Samples points on a given (ideal) line and creates a new image with the sample points contained in a 036 * {@link PointRoi}. Image size, circle parameters and noise can be specified. The result can be used as a test image 037 * for line fitting. Random seed can be set for repeatable results. 038 * 039 * @author WB 040 * @version 2022/12/08 041 */ 042public class Line_Make_Random implements PlugIn, JavaDocHelp { 043 044 public static class Parameters implements ParameterBundle<Line_Make_Random> { 045 046 @DialogLabel("image title")@DialogStringColumns(12) 047 public String Title = "RandomLine"; // Line_Make_Random.class.getSimpleName(); 048 049 @DialogLabel("image width") 050 public int W = 400; 051 @DialogLabel("image height") 052 public int H = 400; 053 054 @DialogLabel("number of points") 055 public int n = 20; 056 057 @DialogLabel("start point (x1)") 058 public double x1 = 90; 059 @DialogLabel("start point (y1)") 060 public double y1 = 40; 061 @DialogLabel("end point (x2)") 062 public double x2 = 300; 063 @DialogLabel("end point (y2)") 064 public double y2 = 270; 065 066 @DialogLabel("x/y noise sigma") 067 public double sigma = 5.0; 068 @DialogLabel("Random seed (0 = none)") 069 public int seed = 0; 070 071 @DialogLabel("show real line") 072 public boolean ShowRealCurve = true; 073 @DialogLabel("line color") 074 public BasicAwtColor StrokeColor = BasicAwtColor.Green; 075 @DialogLabel("stroke width") 076 public double StrokeWidth = 1.0; 077 }; 078 079 private static Parameters params = new Parameters(); 080 081 082 @Override 083 public void run(String arg) { 084 085 if (!runDialog()) { 086 return; 087 } 088 089 Pnt2d pStart = Pnt2d.from(params.x1, params.y1); 090 Pnt2d pEnd = Pnt2d.from(params.x2, params.y2); 091 AlgebraicLine realLine = AlgebraicLine.from(pStart, pEnd); 092 093 LineSampler ls = new LineSampler(pStart, pEnd, params.seed); 094 Pnt2d[] points = ls.getPoints(params.n, params.sigma); 095 096 ImagePlus im = NewImage.createByteImage(params.Title, params.W, params.H, 1, NewImage.FILL_BLACK); 097 im.setRoi(RoiUtils.toPointRoi(points)); 098 099 ImageProcessor ip = im.getProcessor(); 100 for (Pnt2d p : points) { 101 int u = (int) Math.rint(p.getX()); 102 int v = (int) Math.rint(p.getY()); 103 ip.putPixel(u, v, 255); 104 } 105 ip.invertLut(); 106 107 108 if (params.ShowRealCurve) { 109 ShapeOverlayAdapter ola = new ShapeOverlayAdapter(); 110 ColoredStroke lineStroke = new ColoredStroke(params.StrokeWidth, params.StrokeColor.getColor()); 111 ola.addShape(realLine.getShape(params.W, params.H), lineStroke); 112 im.setOverlay(ola.getOverlay()); 113 } 114 115 im.show(); 116 } 117 118 // ------------------------------------------ 119 120 private boolean runDialog() { 121 GenericDialog gd = new GenericDialog(this.getClass().getSimpleName()); 122 gd.addHelp(getJavaDocUrl()); 123 gd.addMessage(DialogUtils.formatText(50, 124 "This plugin samples points on a given (ideal) line and", 125 "creates a new image with the sample points marked and also", 126 "contained in a ROI (float coordinates)." 127 )); 128 129 addToDialog(params, gd); 130 131 gd.showDialog(); 132 if (gd.wasCanceled()) 133 return false; 134 135 getFromDialog(params, gd); 136 return params.validate(); 137 } 138 139}