I am trying to develop a plug-in that will analyze each of the
detected blobs in the image, find the boundary points for the particle and the Convex Hull and find the maximum intrusion distance. I want to use this as an agglomerate detector in those cases where the watershed algorithm is unreliable. The problem is that when I get the Convex Hull, there are a minimum number of points and the algorithm (understandably) fails. I would like to get the interpolated points for the Convex Hull Polygon. I am pasting my code, the original test image (model.jpg), the model image analyzed with my ImageJ plugin (model-ana.jpg) and the image (det-model.jpg) analyzed with a closed source package (that I would like to replace with ImageJ) where I can get the full resolution boundary of the Convex Hull - and the algorithm works as expected... I would appreciate any pointers... Best regards, John Minter My plug-in: import ij.*; import ij.plugin.*; import ij.plugin.filter.*; import ij.plugin.Animator.*; import ij.process.*; import ij.gui.*; import ij.measure.*; import ij.text.*; import java.util.*; import java.awt.*; import java.awt.event.*; import ij.plugin.*; /* * Adapted from shape descriptor */ public class Single_Particle_Detector implements PlugInFilter { /** Display results in the ImageJ console. */ public static final int SHOW_RESULTS = 1; public static final int SHOW_OUTLINES = 4; public static final int EXCLUDE_EDGE_PARTICLES = 8; public static final int SHOW_SIZE_DISTRIBUTION = 16; public static final int SHOW_PROGRESS = 32; public static final int CLEAR_WORKSHEET = 64; public static final int RECORD_STARTS = 128; public static final int DISPLAY_SUMMARY = 256; public static final int SHOW_NONE = 512; // public static final int FLOOD_FILL=1024; public static final int SHOW_MASKS = 4096; protected static final int NOTHING = 0; protected static final int OUTLINES = 1; protected static final int MASKS = 2; protected static final int ELLIPSES = 3; protected static final int INCLUDE_HOLES = 1024; private double m_dMinSize = 0., m_dMaxSize=9999999.; private ResultsTable m_rt = new ResultsTable(); private ImagePlus m_imp; public int setup(String arg, ImagePlus imp) { // Ask to process stacks. // SNAPSHOT: We always need a snapshot, also if not needed for // undo (e.g. in case of a stack). m_imp=imp; return IJ.setupDialog(imp, DOES_8G | DOES_16 | SNAPSHOT); } public void run(ImageProcessor ip) { if (IJ.versionLessThan("1.43d")) return; if (m_imp.isInvertedLut()) { IJ.run("Invert"); IJ.run("Invert LUT"); } String iName = m_imp.getTitle(); IJ.run("Colors...", "foreground=white background=white selection=yellow"); Calibration cal = m_imp.getCalibration(); float ps = (float) cal.pixelWidth; int measurements = Analyzer.getMeasurements(); // defined in Set // Measurements dialog Analyzer.setMeasurements(0); // make sure area, perimeter, and rect are measured measurements = Analyzer.AREA + Analyzer.PERIMETER + Analyzer.RECT; int options = 0; Analyzer.setMeasurements(measurements); ParticleAnalyzer pa = new ParticleAnalyzer(options, measurements, m_rt, m_dMinSize, m_dMaxSize); pa.analyze(m_imp, ip); filterImage(m_rt, m_imp, ps); m_rt.show("analysis of " + iName); } void filterImage(ResultsTable objRt, ImagePlus objImp, float fCal) { Roi objRoi; FloatPolygon objFloatPoly; Polygon objPolyHull; int nParticles = objRt.getCounter(); int nBlobPolyPts, nHullPolyPts; int iXo, iYo; float fXo, fYo; float fAreaSqPx; double dMaxIntr, dEcd; double dMinD,dBlobX,dBlobY,dHullX,dHullY,dDeltaX, dDeltaY, dDist; float[] a = objRt.getColumn(ResultsTable.AREA); // get area measurements int iColEcd = objRt.getFreeColumn("ECD"); int iColBay = objRt.getFreeColumn("Max Intr"); for (int ii=0; ii<a.length; ii++){ fAreaSqPx = a[ii]/(fCal*fCal); dEcd = 2.0 * Math.sqrt(a[ii]/Math.PI); if( fAreaSqPx < 5000. || fAreaSqPx > 50.) { fXo = (float) objRt.getValue("BX", ii); fXo /= fCal; iXo = (int) fXo; fYo = (float) objRt.getValue("BY", ii); fYo /= fCal; iYo = (int) fYo; // Let the Wand to find the blob, then get the ROI IJ.doWand(iXo, iYo); objRoi = objImp.getRoi(); // get the Convex Hull as a polygon // and store the coordinates objPolyHull = objRoi.getConvexHull(); nHullPolyPts=objPolyHull.npoints; int xh[] = new int[nHullPolyPts]; int yh[] = new int[nHullPolyPts]; for (int i=0; i<nHullPolyPts; i++) xh[i] = objPolyHull.xpoints[i]; for (int i=0; i<nHullPolyPts; i++) yh[i] = objPolyHull.ypoints[i]; // get the blob as a polygon // and store the coordinates Polygon objPolyBlob = objRoi.getPolygon(); nBlobPolyPts=objPolyBlob.npoints; int xb[] = new int[nBlobPolyPts]; int yb[] = new int[nBlobPolyPts]; // closest point on the hull... int ch[] = new int[nBlobPolyPts]; for (int i=0; i<nBlobPolyPts; i++) xb[i] = objPolyBlob.xpoints[i]; for (int i=0; i<nBlobPolyPts; i++) yb[i] = objPolyBlob.ypoints[i]; // compute the minimum distance from each // point on the blob to the Convex Hull double minDist[] = new double[nBlobPolyPts]; for (int i=0; i<nBlobPolyPts; i++) { dMinD = 9999999.0; dBlobX = (double) xb[i]; dBlobY = (double) yb[i]; for (int j=0; j<nHullPolyPts; j++) { dHullX = (double) xh[j]; dHullY = (double) yh[j]; dDeltaX = dHullX - dBlobX; dDeltaY = dHullY - dBlobY; dDist = Math.sqrt(dDeltaX*dDeltaX + dDeltaY*dDeltaY); if(dDist < dMinD ) { dMinD = dDist; ch[i] = j; } }; minDist[i]=dMinD; } dMaxIntr = -1; int iMinDistPtBlob=0, iMinDistPtHull=0; for (int i=0; i<nBlobPolyPts; i++) { if(minDist[i] > dMaxIntr) { dMaxIntr = minDist[i]; iMinDistPtBlob = i; iMinDistPtHull=ch[i]; } } objImp.getProcessor().drawLine(xb[iMinDistPtBlob], yb[iMinDistPtBlob], xh[iMinDistPtHull], yh[iMinDistPtHull]); objRt.setValue(iColEcd, ii, dEcd); objRt.setValue(iColBay, ii, dMaxIntr*fCal); IJ.showStatus("blob: "+ ii + " Max Intrusion = " + dMaxIntr + ", Processing..."); // IJ.run("Clear", "slice"); } } // objRt.updateResults(); IJ.run("Select None"); } } ![]() ![]() ![]() |
Thank you so much, Wayne. The addition you suggested did the trick!
Best regards, John Minter On Sat, Mar 10, 2012 at 9:20 PM, Rasband, Wayne (NIH/NIMH) [E] <[hidden email]> wrote: > Hi John, > > Your plugin should work better if you add these three lines > > PolygonRoi hullRoi = new PolygonRoi(objPolyHull, Roi.POLYGON); > hullRoi.fitSplineForStraightening(); > objPolyHull = hullRoi.getPolygon(); > > after this one > > objPolyHull = objRoi.getConvexHull(); > > The fitSplineForStraightening() method creates a spline fitted polygon that has points spaced one pixel apart. > > Best regards, > > -wayne > > > > > > On Mar 10, 2012, at 3:38 PM, John Minter wrote: > >> I am trying to develop a plug-in that will analyze each of the >> detected blobs in the image, find the boundary points for the particle >> and the Convex Hull and find the maximum intrusion distance. I want to >> use this as an agglomerate detector in those cases where the watershed >> algorithm is unreliable. The problem is that when I get the Convex >> Hull, there are a minimum number of points and the algorithm >> (understandably) fails. I would like to get the interpolated points >> for the Convex Hull Polygon. >> >> I am pasting my code, the original test image (model.jpg), the model >> image analyzed with my ImageJ plugin (model-ana.jpg) and the image >> (det-model.jpg) analyzed with a closed source package (that I would >> like to replace with ImageJ) where I can get the full resolution >> boundary of the Convex Hull - and the algorithm works as expected... I >> would appreciate any pointers... >> >> Best regards, >> John Minter >> >> My plug-in: >> >> import ij.*; >> import ij.plugin.*; >> import ij.plugin.filter.*; >> import ij.plugin.Animator.*; >> import ij.process.*; >> import ij.gui.*; >> import ij.measure.*; >> import ij.text.*; >> import java.util.*; >> import java.awt.*; >> import java.awt.event.*; >> import ij.plugin.*; >> >> /* >> * Adapted from shape descriptor >> */ >> >> public class Single_Particle_Detector implements PlugInFilter { >> /** Display results in the ImageJ console. */ >> public static final int SHOW_RESULTS = 1; >> public static final int SHOW_OUTLINES = 4; >> public static final int EXCLUDE_EDGE_PARTICLES = 8; >> public static final int SHOW_SIZE_DISTRIBUTION = 16; >> public static final int SHOW_PROGRESS = 32; >> public static final int CLEAR_WORKSHEET = 64; >> public static final int RECORD_STARTS = 128; >> public static final int DISPLAY_SUMMARY = 256; >> public static final int SHOW_NONE = 512; >> // public static final int FLOOD_FILL=1024; >> public static final int SHOW_MASKS = 4096; >> >> protected static final int NOTHING = 0; >> protected static final int OUTLINES = 1; >> protected static final int MASKS = 2; >> protected static final int ELLIPSES = 3; >> protected static final int INCLUDE_HOLES = 1024; >> >> private double m_dMinSize = 0., m_dMaxSize=9999999.; >> >> private ResultsTable m_rt = new ResultsTable(); >> private ImagePlus m_imp; >> >> public int setup(String arg, ImagePlus imp) { >> // Ask to process stacks. >> // SNAPSHOT: We always need a snapshot, also if not needed for >> // undo (e.g. in case of a stack). >> m_imp=imp; >> return IJ.setupDialog(imp, DOES_8G | DOES_16 | SNAPSHOT); >> } >> >> >> public void run(ImageProcessor ip) { >> if (IJ.versionLessThan("1.43d")) >> return; >> >> if (m_imp.isInvertedLut()) { >> IJ.run("Invert"); >> IJ.run("Invert LUT"); >> } >> >> String iName = m_imp.getTitle(); >> >> IJ.run("Colors...", >> "foreground=white background=white selection=yellow"); >> Calibration cal = m_imp.getCalibration(); >> float ps = (float) cal.pixelWidth; >> >> int measurements = Analyzer.getMeasurements(); // defined in Set >> // Measurements dialog >> Analyzer.setMeasurements(0); >> >> // make sure area, perimeter, and rect are measured >> >> measurements = Analyzer.AREA + Analyzer.PERIMETER + Analyzer.RECT; >> int options = 0; >> Analyzer.setMeasurements(measurements); >> ParticleAnalyzer pa = new ParticleAnalyzer(options, measurements, m_rt, >> m_dMinSize, m_dMaxSize); >> pa.analyze(m_imp, ip); >> filterImage(m_rt, m_imp, ps); >> m_rt.show("analysis of " + iName); >> >> } >> >> >> void filterImage(ResultsTable objRt, ImagePlus objImp, float fCal) { >> Roi objRoi; >> FloatPolygon objFloatPoly; >> Polygon objPolyHull; >> int nParticles = objRt.getCounter(); >> int nBlobPolyPts, nHullPolyPts; >> int iXo, iYo; >> float fXo, fYo; >> float fAreaSqPx; >> double dMaxIntr, dEcd; >> double dMinD,dBlobX,dBlobY,dHullX,dHullY,dDeltaX, dDeltaY, dDist; >> >> float[] a = objRt.getColumn(ResultsTable.AREA); // get area measurements >> int iColEcd = objRt.getFreeColumn("ECD"); >> int iColBay = objRt.getFreeColumn("Max Intr"); >> >> for (int ii=0; ii<a.length; ii++){ >> fAreaSqPx = a[ii]/(fCal*fCal); >> dEcd = 2.0 * Math.sqrt(a[ii]/Math.PI); >> if( fAreaSqPx < 5000. || fAreaSqPx > 50.) { >> fXo = (float) objRt.getValue("BX", ii); >> fXo /= fCal; >> iXo = (int) fXo; >> fYo = (float) objRt.getValue("BY", ii); >> fYo /= fCal; >> iYo = (int) fYo; >> // Let the Wand to find the blob, then get the ROI >> IJ.doWand(iXo, iYo); >> objRoi = objImp.getRoi(); >> // get the Convex Hull as a polygon >> // and store the coordinates >> objPolyHull = objRoi.getConvexHull(); >> nHullPolyPts=objPolyHull.npoints; >> int xh[] = new int[nHullPolyPts]; >> int yh[] = new int[nHullPolyPts]; >> for (int i=0; i<nHullPolyPts; i++) >> xh[i] = objPolyHull.xpoints[i]; >> for (int i=0; i<nHullPolyPts; i++) >> yh[i] = objPolyHull.ypoints[i]; >> >> // get the blob as a polygon >> // and store the coordinates >> Polygon objPolyBlob = objRoi.getPolygon(); >> nBlobPolyPts=objPolyBlob.npoints; >> int xb[] = new int[nBlobPolyPts]; >> int yb[] = new int[nBlobPolyPts]; >> // closest point on the hull... >> int ch[] = new int[nBlobPolyPts]; >> for (int i=0; i<nBlobPolyPts; i++) >> xb[i] = objPolyBlob.xpoints[i]; >> for (int i=0; i<nBlobPolyPts; i++) >> yb[i] = objPolyBlob.ypoints[i]; >> >> // compute the minimum distance from each >> // point on the blob to the Convex Hull >> double minDist[] = new double[nBlobPolyPts]; >> for (int i=0; i<nBlobPolyPts; i++) { >> dMinD = 9999999.0; >> dBlobX = (double) xb[i]; >> dBlobY = (double) yb[i]; >> for (int j=0; j<nHullPolyPts; j++) { >> dHullX = (double) xh[j]; >> dHullY = (double) yh[j]; >> dDeltaX = dHullX - dBlobX; >> dDeltaY = dHullY - dBlobY; >> dDist = Math.sqrt(dDeltaX*dDeltaX + dDeltaY*dDeltaY); >> if(dDist < dMinD ) { >> dMinD = dDist; >> ch[i] = j; >> } >> }; >> minDist[i]=dMinD; >> } >> dMaxIntr = -1; >> >> int iMinDistPtBlob=0, iMinDistPtHull=0; >> for (int i=0; i<nBlobPolyPts; i++) { >> if(minDist[i] > dMaxIntr) { >> dMaxIntr = minDist[i]; >> iMinDistPtBlob = i; >> iMinDistPtHull=ch[i]; >> } >> } >> objImp.getProcessor().drawLine(xb[iMinDistPtBlob], >> yb[iMinDistPtBlob], >> xh[iMinDistPtHull], >> yh[iMinDistPtHull]); >> >> objRt.setValue(iColEcd, ii, dEcd); >> objRt.setValue(iColBay, ii, dMaxIntr*fCal); >> >> IJ.showStatus("blob: "+ ii + " Max Intrusion = " + dMaxIntr + ", >> Processing..."); >> // IJ.run("Clear", "slice"); >> } >> } >> // objRt.updateResults(); >> IJ.run("Select None"); >> } >> } >> <model.jpg><model-ana.jpg><det-model.jpg> > |
In reply to this post by John Minter-3
On Saturday 10 Mar 2012 20:38:50 John Minter wrote:
> and the Convex Hull and find the maximum intrusion distance. I want to > use this as an agglomerate detector in those cases where the watershed > algorithm is unreliable. The problem is that when I get the Convex > Hull, there are a minimum number of points and the algorithm > (understandably) fails. I do not have the answer to your question, hopefully somebody else will, but I just wondered if the algorithm would work as expected: From the comments in the code: > // get the Convex Hull as a polygon > // get the blob as a polygon > // compute the minimum distance from each > // point on the blob to the Convex Hull I think that you need to make sure that you are on the correct side of the convex hull. Measuring to all points in the convex hull to find the smallest distance is not enough. Assume a distorted "B" shape, where the indent on the right is very deep and closer to the vertical stroke on the left than to the convex hull on the side of the indent. You won't get the distance you expect, but one that goes through the blob (and which would be erroneous). Cheers Gabriel |
You are correct. I don't recall running into the situation you
described, since most of the particles I deal with are more or less spheroidal - all are concave. I need to think about the algorithm some more. I really appreciate how the folks on the mailing list help me clarify my thinking. I'm the last person who does quantitative microscopy and image analysis in my present postion - I miss having knowledgeable coworkers as sounding boards for ideas... Best regards, John On Sun, Mar 11, 2012 at 9:30 AM, Gabriel Landini <[hidden email]> wrote: > On Saturday 10 Mar 2012 20:38:50 John Minter wrote: > I think that you need to make sure that you are on the correct side of the > convex hull. Measuring to all points in the convex hull to find the smallest > distance is not enough. > Assume a distorted "B" shape, where the indent on the right is very deep and > closer to the vertical stroke on the left than to the convex hull on the side > of the indent. You won't get the distance you expect, but one that goes > through the blob (and which would be erroneous). > > Cheers > Gabriel |
In reply to this post by John Minter-3
On Mar 10, 2012, at 3:38 PM, John Minter wrote:
> I am trying to develop a plug-in that will analyze each of the > detected blobs in the image, find the boundary points for the particle > and the Convex Hull and find the maximum intrusion distance. I want to > use this as an agglomerate detector in those cases where the watershed > algorithm is unreliable. The problem is that when I get the Convex > Hull, there are a minimum number of points and the algorithm > (understandably) fails. I would like to get the interpolated points > for the Convex Hull Polygon. The ImageJ 1.46i daily build has an Edit>Selection>Interpolate command that converts the current selection into one with interpolated points spaced one pixel apart. This command uses the Roi.getInterpolatedPolygon() method, which returns a FloatPolygon containing a version of the selection with points spaced one pixel apart. To view the interpolated points, use the Interpolate command on small selections created on images zoomed 1200% or greater. Here is a macro that uses the Interpolate command to get the pixel values along a line, similar to what the Analyze>Plot Profile command does: run("Interpolate"); //edit>selection>interpolate getSelectionCoordinates(x, y); values = newArray(x.length); for (i=0; i<x.length; i++) values[i] = getPixel(x[i], y[i]); Plot.create("Profile Plot", "x", "y", values); Unlike the Plot Profile command, this macro also plots profiles along the boundary of area selections. And here is a JavaScript version the uses the Roi.getInterpolatedPolygon() method: imp = IJ.getImage(); ip = imp.getProcessor(); roi = imp.getRoi(); p = roi.getInterpolatedPolygon(); values = new Array(p.npoints); for (i=0; i<p.npoints; i++) values[i] = ip.getPixelValue(p.xpoints[i], p.ypoints[i]); plot = new Plot("", "Profile Plot", "X", "Y", null, values); plot.show(); It uses a new JavaScript-compatible Plot constructor that has a dummy String argument. -wayne > > I am pasting my code, the original test image (model.jpg), the model > image analyzed with my ImageJ plugin (model-ana.jpg) and the image > (det-model.jpg) analyzed with a closed source package (that I would > like to replace with ImageJ) where I can get the full resolution > boundary of the Convex Hull - and the algorithm works as expected... I > would appreciate any pointers... > > Best regards, > John Minter > > My plug-in: > > import ij.*; > import ij.plugin.*; > import ij.plugin.filter.*; > import ij.plugin.Animator.*; > import ij.process.*; > import ij.gui.*; > import ij.measure.*; > import ij.text.*; > import java.util.*; > import java.awt.*; > import java.awt.event.*; > import ij.plugin.*; > > /* > * Adapted from shape descriptor > */ > > public class Single_Particle_Detector implements PlugInFilter { > /** Display results in the ImageJ console. */ > public static final int SHOW_RESULTS = 1; > public static final int SHOW_OUTLINES = 4; > public static final int EXCLUDE_EDGE_PARTICLES = 8; > public static final int SHOW_SIZE_DISTRIBUTION = 16; > public static final int SHOW_PROGRESS = 32; > public static final int CLEAR_WORKSHEET = 64; > public static final int RECORD_STARTS = 128; > public static final int DISPLAY_SUMMARY = 256; > public static final int SHOW_NONE = 512; > // public static final int FLOOD_FILL=1024; > public static final int SHOW_MASKS = 4096; > > protected static final int NOTHING = 0; > protected static final int OUTLINES = 1; > protected static final int MASKS = 2; > protected static final int ELLIPSES = 3; > protected static final int INCLUDE_HOLES = 1024; > > private double m_dMinSize = 0., m_dMaxSize=9999999.; > > private ResultsTable m_rt = new ResultsTable(); > private ImagePlus m_imp; > > public int setup(String arg, ImagePlus imp) { > // Ask to process stacks. > // SNAPSHOT: We always need a snapshot, also if not needed for > // undo (e.g. in case of a stack). > m_imp=imp; > return IJ.setupDialog(imp, DOES_8G | DOES_16 | SNAPSHOT); > } > > > public void run(ImageProcessor ip) { > if (IJ.versionLessThan("1.43d")) > return; > > if (m_imp.isInvertedLut()) { > IJ.run("Invert"); > IJ.run("Invert LUT"); > } > > String iName = m_imp.getTitle(); > > IJ.run("Colors...", > "foreground=white background=white selection=yellow"); > Calibration cal = m_imp.getCalibration(); > float ps = (float) cal.pixelWidth; > > int measurements = Analyzer.getMeasurements(); // defined in Set > // Measurements dialog > Analyzer.setMeasurements(0); > > // make sure area, perimeter, and rect are measured > > measurements = Analyzer.AREA + Analyzer.PERIMETER + Analyzer.RECT; > int options = 0; > Analyzer.setMeasurements(measurements); > ParticleAnalyzer pa = new ParticleAnalyzer(options, measurements, m_rt, > m_dMinSize, m_dMaxSize); > pa.analyze(m_imp, ip); > filterImage(m_rt, m_imp, ps); > m_rt.show("analysis of " + iName); > > } > > > void filterImage(ResultsTable objRt, ImagePlus objImp, float fCal) { > Roi objRoi; > FloatPolygon objFloatPoly; > Polygon objPolyHull; > int nParticles = objRt.getCounter(); > int nBlobPolyPts, nHullPolyPts; > int iXo, iYo; > float fXo, fYo; > float fAreaSqPx; > double dMaxIntr, dEcd; > double dMinD,dBlobX,dBlobY,dHullX,dHullY,dDeltaX, dDeltaY, dDist; > > float[] a = objRt.getColumn(ResultsTable.AREA); // get area measurements > int iColEcd = objRt.getFreeColumn("ECD"); > int iColBay = objRt.getFreeColumn("Max Intr"); > > for (int ii=0; ii<a.length; ii++){ > fAreaSqPx = a[ii]/(fCal*fCal); > dEcd = 2.0 * Math.sqrt(a[ii]/Math.PI); > if( fAreaSqPx < 5000. || fAreaSqPx > 50.) { > fXo = (float) objRt.getValue("BX", ii); > fXo /= fCal; > iXo = (int) fXo; > fYo = (float) objRt.getValue("BY", ii); > fYo /= fCal; > iYo = (int) fYo; > // Let the Wand to find the blob, then get the ROI > IJ.doWand(iXo, iYo); > objRoi = objImp.getRoi(); > // get the Convex Hull as a polygon > // and store the coordinates > objPolyHull = objRoi.getConvexHull(); > nHullPolyPts=objPolyHull.npoints; > int xh[] = new int[nHullPolyPts]; > int yh[] = new int[nHullPolyPts]; > for (int i=0; i<nHullPolyPts; i++) > xh[i] = objPolyHull.xpoints[i]; > for (int i=0; i<nHullPolyPts; i++) > yh[i] = objPolyHull.ypoints[i]; > > // get the blob as a polygon > // and store the coordinates > Polygon objPolyBlob = objRoi.getPolygon(); > nBlobPolyPts=objPolyBlob.npoints; > int xb[] = new int[nBlobPolyPts]; > int yb[] = new int[nBlobPolyPts]; > // closest point on the hull... > int ch[] = new int[nBlobPolyPts]; > for (int i=0; i<nBlobPolyPts; i++) > xb[i] = objPolyBlob.xpoints[i]; > for (int i=0; i<nBlobPolyPts; i++) > yb[i] = objPolyBlob.ypoints[i]; > > // compute the minimum distance from each > // point on the blob to the Convex Hull > double minDist[] = new double[nBlobPolyPts]; > for (int i=0; i<nBlobPolyPts; i++) { > dMinD = 9999999.0; > dBlobX = (double) xb[i]; > dBlobY = (double) yb[i]; > for (int j=0; j<nHullPolyPts; j++) { > dHullX = (double) xh[j]; > dHullY = (double) yh[j]; > dDeltaX = dHullX - dBlobX; > dDeltaY = dHullY - dBlobY; > dDist = Math.sqrt(dDeltaX*dDeltaX + dDeltaY*dDeltaY); > if(dDist < dMinD ) { > dMinD = dDist; > ch[i] = j; > } > }; > minDist[i]=dMinD; > } > dMaxIntr = -1; > > int iMinDistPtBlob=0, iMinDistPtHull=0; > for (int i=0; i<nBlobPolyPts; i++) { > if(minDist[i] > dMaxIntr) { > dMaxIntr = minDist[i]; > iMinDistPtBlob = i; > iMinDistPtHull=ch[i]; > } > } > objImp.getProcessor().drawLine(xb[iMinDistPtBlob], > yb[iMinDistPtBlob], > xh[iMinDistPtHull], > yh[iMinDistPtHull]); > > objRt.setValue(iColEcd, ii, dEcd); > objRt.setValue(iColBay, ii, dMaxIntr*fCal); > > IJ.showStatus("blob: "+ ii + " Max Intrusion = " + dMaxIntr + ", > Processing..."); > // IJ.run("Clear", "slice"); > } > } > // objRt.updateResults(); > IJ.run("Select None"); > } > } > <model.jpg><model-ana.jpg><det-model.jpg> |
Free forum by Nabble | Edit this page |