/** * Computes the energy of each segment individually */ void computeSegmentEnergy( GrowQueue_I32 corners ) { if( energySegment.length < corners.size() ) { energySegment = new double[ corners.size() ]; } for (int i = 0,j=corners.size()-1; i < corners.size(); j=i,i++) { energySegment[j] = computeSegmentEnergy(corners, j, i); } }
/** * If not touching the border then the number of corners must be 4. If touching the border there must be * at least 3 corners not touching the border. 7 corners at most. If there were 8 then all sides of a square * would be touching the border. No more than 3 corners since that's the most number of non-border corners * a square can have. */ @Override public boolean filterPixelPolygon(List<Point2D_I32> externalUndist, List<Point2D_I32> externalDist, GrowQueue_I32 splits, boolean touchesBorder) { if( touchesBorder ) { if( splits.size() > 7 || splits.size() < 3) return false; int totalRegular = 0; for (int i = 0; i < splits.size(); i++) { Point2D_I32 p = externalDist.get(splits.get(i)); if( !(p.x == 0 || p.y == 0 || p.x == width-1 || p.y == height-1)) totalRegular++; } return totalRegular > 0 && totalRegular <= 4; // should be 3, but noise/imprecision in corner can make it 4 } else { return splits.size() == 4; } } }
@Override public void setTo( GrowQueue_I32 original ) { resize(original.size); System.arraycopy(original.data, 0, data, 0, size()); }
@Override public void setTo( GrowQueue_I32 original ) { resize(original.size); System.arraycopy(original.data, 0, data, 0, size()); }
@Override public int getTotalSuperpixels() { return alg.getRegionSizes().size(); }
/** * Returns the total energy after removing a corner * @param removed index of the corner that is being removed * @param corners list of corner indexes */ protected double energyRemoveCorner( int removed , GrowQueue_I32 corners ) { double total = 0; int cornerA = CircularIndex.addOffset(removed, -1 , corners.size()); int cornerB = CircularIndex.addOffset(removed, 1 , corners.size()); total += computeSegmentEnergy(corners, cornerA, cornerB); if( cornerA > cornerB ) { for (int i = cornerB; i < cornerA; i++) total += energySegment[i]; } else { for (int i = 0; i < cornerA; i++) { total += energySegment[i]; } for (int i = cornerB; i < corners.size(); i++) { total += energySegment[i]; } } return total; }
/** * Look for two corners which point to the same point and removes one of them from the corner list */ void removeDuplicates( GrowQueue_I32 corners ) { // remove duplicates for (int i = 0; i < corners.size(); i++) { Point2D_I32 a = contour.get(corners.get(i)); // start from the top so that removing a corner doesn't mess with the for loop for (int j = corners.size()-1; j > i; j--) { Point2D_I32 b = contour.get(corners.get(j)); if( a.x == b.x && a.y == b.y ) { // this is still ok if j == 0 because it wrapped around. 'i' will now be > size corners.remove(j); } } } }
@Override public boolean process(List<Point2D_I32> list) { splits.reset(); this.contour = list; if( list.size() <= 2 ) { // can't do anything with two or less points return false; } this.minimumSideLengthPixel = (int)Math.ceil(contour.size()* minimumSideLengthFraction); // initial segmentation splits.add(0); splitPixels(0, list.size() - 1); splits.add(list.size()-1); for( int i = 0; i < maxIterations; i++ ) { boolean changed = mergeSegments(); if( !changed && !splitSegments() ) break; if( splits.size() <= 2 || splits.size() >= abortSplits ) break; } return true; }
private void findBestPoints(int x, int y, List<Point2D_F64> pts , List<Integer> selected ) { double bestDist = clickDistance*clickDistance; GrowQueue_I32 bestIndexes = new GrowQueue_I32(20); for( int i = 0; i < pts.size(); i++ ) { if( !isValidPoint(i) ) continue; Point2D_F64 p = pts.get(i); double d = UtilPoint2D_F64.distanceSq(p.x, p.y, x, y); if( d < bestDist ) { bestDist = d; bestIndexes.reset(); bestIndexes.add(i); } else if( Math.abs(d - bestDist) < 0.01 ) { bestIndexes.add(i); } } if( bestIndexes.size() > 0 ) { int indexRight = bestIndexes.get(0); } for (int i = 0; i < bestIndexes.size(); i++) { selected.add(bestIndexes.get(i)); } }
private void findBestPoints(int x, int y, List<Point2D_F64> pts , List<Integer> selected ) { double bestDist = clickDistance*clickDistance; GrowQueue_I32 bestIndexes = new GrowQueue_I32(20); for( int i = 0; i < pts.size(); i++ ) { if( !isValidPoint(i) ) continue; Point2D_F64 p = pts.get(i); double d = UtilPoint2D_F64.distanceSq(p.x, p.y, x, y); if( d < bestDist ) { bestDist = d; bestIndexes.reset(); bestIndexes.add(i); } else if( Math.abs(d - bestDist) < 0.01 ) { bestIndexes.add(i); } } if( bestIndexes.size() > 0 ) { int indexRight = bestIndexes.get(0); } for (int i = 0; i < bestIndexes.size(); i++) { selected.add(bestIndexes.get(i)); } }
/** * All the corners should be in increasing order from the first anchor. */ boolean sanityCheckCornerOrder( int numLines, GrowQueue_I32 corners ) { int contourAnchor0 = corners.get(anchor0); int previous = 0; for (int i = 1; i < numLines; i++) { int contourIndex = corners.get(CircularIndex.addOffset(anchor0, i, corners.size())); int pixelsFromAnchor0 = CircularIndex.distanceP(contourAnchor0, contourIndex, contour.size()); if (pixelsFromAnchor0 < previous) { return false; } else { previous = pixelsFromAnchor0; } } return true; }
/** * Adds edges to node info and computes their orientation */ void addEdgesToInfo(List<Node> cluster) { for (int i = 0; i < cluster.size(); i++) { Node n = cluster.get(i); NodeInfo infoA = listInfo.get(i); EllipseRotated_F64 a = infoA.ellipse; // create the edges and order them based on their direction for (int j = 0; j < n.connections.size(); j++) { NodeInfo infoB = listInfo.get( indexOf(cluster, n.connections.get(j))); EllipseRotated_F64 b = infoB.ellipse; Edge edge = infoA.edges.grow(); edge.target = infoB; edge.angle = Math.atan2( b.center.y - a.center.y , b.center.x - a.center.x ); } sorter.sort(infoA.edges.data, infoA.edges.size); } }
/** * Merges lines together if the common corner is close to a common line * @return true the list being changed */ protected boolean mergeSegments() { // See if merging will cause a degenerate case if( splits.size() <= 3 ) return false; boolean change = false; work.reset(); for( int i = 0; i < splits.size; i++ ) { int start = splits.data[i]; int end = splits.data[(i+2)%splits.size]; if( selectSplitOffset(start,circularDistance(start,end)) < 0 ) { // merge the two lines by not adding it change = true; } else { work.add(splits.data[(i + 1)%splits.size]); } } // swap the two lists GrowQueue_I32 tmp = work; work = splits; splits = tmp; return change; }
public boolean refine(Polygon2D_F64 input, List<Point2D_I32> contour , GrowQueue_I32 splits, Polygon2D_F64 refined) { if( refined.size() != splits.size() ) throw new IllegalArgumentException("Miss match between number of splits and polygon order"); for (int cornerS = 0; cornerS < splits.size(); cornerS++) { int indexLeft = pickEndIndex(cornerS, 1); int indexRight = pickEndIndex(cornerS, -1);
for (int j = 0; j < zerosOut.size(); j++) { binary.data[ zerosOut.get(j)] = 0;
@Override public void segment(T input, GrayS32 output) { InputSanityCheck.checkSameShape(input,output); converted.reshape(input.width,input.height); GConvertImage.convert(input,converted); // segment the image alg.process(converted); alg.removeWatersheds(); numRegions = alg.getTotalRegions(); GrayS32 pixelToRegion = alg.getOutput(); // Merge small regions together if( pruneSmall != null ) { regionMemberCount.resize(numRegions); regionColor.resize(numRegions); ImageSegmentationOps.countRegionPixels(pixelToRegion,numRegions,regionMemberCount.data); pruneSmall.process(converted,pixelToRegion,regionMemberCount,regionColor); numRegions = regionMemberCount.size(); } output.setTo(pixelToRegion); }
@Test public void splitData_withData() { List<double[]> points = createPoints(2, 1,2 , 3,5 , -3,4); GrowQueue_I32 data = new GrowQueue_I32(); for( int i = 0; i < points.size(); i++ ) data.add(i); AxisSplitterMedian<double[]> alg = new AxisSplitterMedian<>(distance,new DummyRule(1)); alg.splitData(points,data,left,leftData,right,rightData); assertEquals(1,left.size()); assertEquals(1,right.size()); assertEquals(1,leftData.size()); assertEquals(1,rightData.size()); assertEquals(1,alg.getSplitAxis(),1e-8); assertEquals(-3,alg.getSplitPoint()[0],1e-8); assertTrue(data.get(2) == alg.getSplitIndex()); assertTrue(data.get(0) == leftData.get(0)); assertTrue(data.get(1) == rightData.get(0)); }