Search in sources :

Example 31 with Point2D_I32

use of georegression.struct.point.Point2D_I32 in project BoofCV by lessthanoptimal.

the class SplitMergeLineFitLoop method selectSplitOffset.

/**
 * Finds the point between indexStart and the end point which is the greater distance from the line
 * (set up prior to calling).  Returns the index of the element with a distances greater than tolerance, otherwise -1
 *
 * @return Selected offset from start of the split. -1 if no split was selected
 */
protected int selectSplitOffset(int indexStart, int length) {
    int bestOffset = -1;
    int indexEnd = (indexStart + length) % N;
    Point2D_I32 startPt = contour.get(indexStart);
    Point2D_I32 endPt = contour.get(indexEnd);
    line.p.set(startPt.x, startPt.y);
    line.slope.set(endPt.x - startPt.x, endPt.y - startPt.y);
    double bestDistanceSq = splitThresholdSq(contour.get(indexStart), contour.get(indexEnd));
    // adjusting using 'minimumSideLengthPixel' to ensure it doesn't create a new line which is too short
    // 1 is the minimum so that you don't split on the same corner
    int minLength = Math.max(1, minimumSideLengthPixel);
    length -= minLength;
    for (int i = minLength; i <= length; i++) {
        Point2D_I32 b = contour.get((indexStart + i) % N);
        point2D.set(b.x, b.y);
        double dist = Distance2D_F64.distanceSq(line, point2D);
        if (dist >= bestDistanceSq) {
            bestDistanceSq = dist;
            bestOffset = i;
        }
    }
    return bestOffset;
}
Also used : UtilPoint2D_I32(georegression.geometry.UtilPoint2D_I32) Point2D_I32(georegression.struct.point.Point2D_I32)

Example 32 with Point2D_I32

use of georegression.struct.point.Point2D_I32 in project BoofCV by lessthanoptimal.

the class ShapeFittingOps method averageCircle_I32.

/**
 * Computes a circle which has it's center at the mean position of the provided points and radius is equal to the
 * average distance of each point from the center.  While fast to compute the provided circle is not a best
 * fit circle by any reasonable metric, except for special cases.
 *
 * @param points (Input) Set of unordered points. Not modified.
 * @param optional (Optional) Used internally to store the distance of each point from the center.  Can be null.
 * @param outputStorage (Output/Optional) Storage for results.  If null then a new circle instance will be returned.
 * @return The found circle fit.
 */
public static FitData<Circle2D_F64> averageCircle_I32(List<Point2D_I32> points, GrowQueue_F64 optional, FitData<Circle2D_F64> outputStorage) {
    if (outputStorage == null) {
        outputStorage = new FitData<>(new Circle2D_F64());
    }
    if (optional == null) {
        optional = new GrowQueue_F64();
    }
    Circle2D_F64 circle = outputStorage.shape;
    int N = points.size();
    // find center of the circle by computing the mean x and y
    int sumX = 0, sumY = 0;
    for (int i = 0; i < N; i++) {
        Point2D_I32 p = points.get(i);
        sumX += p.x;
        sumY += p.y;
    }
    optional.reset();
    double centerX = circle.center.x = sumX / (double) N;
    double centerY = circle.center.y = sumY / (double) N;
    double meanR = 0;
    for (int i = 0; i < N; i++) {
        Point2D_I32 p = points.get(i);
        double dx = p.x - centerX;
        double dy = p.y - centerY;
        double r = Math.sqrt(dx * dx + dy * dy);
        optional.push(r);
        meanR += r;
    }
    meanR /= N;
    circle.radius = meanR;
    // compute radius variance
    double variance = 0;
    for (int i = 0; i < N; i++) {
        double diff = optional.get(i) - meanR;
        variance += diff * diff;
    }
    outputStorage.error = variance / N;
    return outputStorage;
}
Also used : Circle2D_F64(georegression.struct.trig.Circle2D_F64) Point2D_I32(georegression.struct.point.Point2D_I32) GrowQueue_F64(org.ddogleg.struct.GrowQueue_F64)

Example 33 with Point2D_I32

use of georegression.struct.point.Point2D_I32 in project BoofCV by lessthanoptimal.

the class MergeRegionMeanShift method markMergeRegions.

/**
 * Takes the mode of a region and searches the local area around it for other regions.  If the region's mode
 * is also within the local area its color is checked to see if it's similar enough.  If the color is similar
 * enough then the two regions are marked for merger.
 */
protected void markMergeRegions(FastQueue<float[]> regionColor, FastQueue<Point2D_I32> modeLocation, GrayS32 pixelToRegion) {
    for (int targetId = 0; targetId < modeLocation.size; targetId++) {
        float[] color = regionColor.get(targetId);
        Point2D_I32 location = modeLocation.get(targetId);
        int x0 = location.x - searchRadius;
        int x1 = location.x + searchRadius + 1;
        int y0 = location.y - searchRadius;
        int y1 = location.y + searchRadius + 1;
        // ensure that all pixels it examines are inside the image
        if (x0 < 0)
            x0 = 0;
        if (x1 > pixelToRegion.width)
            x1 = pixelToRegion.width;
        if (y0 < 0)
            y0 = 0;
        if (y1 > pixelToRegion.height)
            y1 = pixelToRegion.height;
        // look at the local neighborhood
        for (int y = y0; y < y1; y++) {
            for (int x = x0; x < x1; x++) {
                int candidateId = pixelToRegion.unsafe_get(x, y);
                // see if it is the same region
                if (candidateId == targetId)
                    continue;
                // see if the mode is near by
                Point2D_I32 p = modeLocation.get(candidateId);
                if (p.distance2(location) <= maxSpacialDistanceSq) {
                    // see if the color is similar
                    float[] candidateColor = regionColor.get(candidateId);
                    float colorDistance = SegmentMeanShiftSearch.distanceSq(color, candidateColor);
                    if (colorDistance <= maxColorDistanceSq) {
                        // mark the two regions as merged
                        markMerge(targetId, candidateId);
                    }
                }
            }
        }
    }
}
Also used : Point2D_I32(georegression.struct.point.Point2D_I32)

Example 34 with Point2D_I32

use of georegression.struct.point.Point2D_I32 in project BoofCV by lessthanoptimal.

the class MergeSmallRegions method checkAdjacentAround.

private void checkAdjacentAround(int x, int y, int indexImg, GrayS32 pixelToRegion) {
    int regionA = pixelToRegion.data[indexImg];
    for (int i = 0; i < connect.length; i++) {
        Point2D_I32 p = connect[i];
        if (!pixelToRegion.isInBounds(x + p.x, y + p.y))
            continue;
        int regionB = pixelToRegion.data[indexImg + p.y * pixelToRegion.stride + p.x];
        if (regionA != regionB) {
            boolean pruneA = segmentPruneFlag.data[regionA];
            boolean pruneB = segmentPruneFlag.data[regionB];
            if (pruneA) {
                Node n = pruneGraph.get(segmentToPruneID.get(regionA));
                n.connect(regionB);
            }
            if (pruneB) {
                Node n = pruneGraph.get(segmentToPruneID.get(regionB));
                n.connect(regionA);
            }
        }
    }
}
Also used : Point2D_I32(georegression.struct.point.Point2D_I32)

Example 35 with Point2D_I32

use of georegression.struct.point.Point2D_I32 in project BoofCV by lessthanoptimal.

the class SegmentMeanShiftSearchGray method findPeak.

/**
 * Uses mean-shift to find the peak.  Returns the peak as an index in the image data array.
 *
 * @param gray The color value which mean-shift is trying to find a region which minimises it
 */
protected void findPeak(float cx, float cy, float gray) {
    history.reset();
    history.grow().set(cx, cy);
    for (int i = 0; i < maxIterations; i++) {
        float total = 0;
        float sumX = 0, sumY = 0, sumGray = 0;
        int kernelIndex = 0;
        float x0 = cx - radiusX;
        float y0 = cy - radiusY;
        // If it is not near the image border it can use faster techniques
        if (interpolate.isInFastBounds(x0, y0) && interpolate.isInFastBounds(x0 + widthX - 1, y0 + widthY - 1)) {
            for (int yy = 0; yy < widthY; yy++) {
                for (int xx = 0; xx < widthX; xx++) {
                    float ds = spacialTable[kernelIndex++];
                    float pixelGray = interpolate.get_fast(x0 + xx, y0 + yy);
                    float dc = pixelGray - gray;
                    dc = dc * dc / maxColorDistanceSq;
                    float weight = dc > 1 ? 0 : weight((ds + dc) / 2f);
                    total += weight;
                    sumX += weight * (xx + x0);
                    sumY += weight * (yy + y0);
                    sumGray += weight * pixelGray;
                }
            }
        } else {
            // Perform more sanity checks here for the image edge.  Edge pixels are handled by skipping them
            for (int yy = 0; yy < widthY; yy++) {
                float sampleY = y0 + yy;
                // make sure it is inside the image
                if (sampleY < 0) {
                    kernelIndex += widthX;
                    continue;
                } else if (sampleY > image.height - 1) {
                    break;
                }
                for (int xx = 0; xx < widthX; xx++, kernelIndex++) {
                    float sampleX = x0 + xx;
                    // make sure it is inside the image
                    if (sampleX < 0 || sampleX > image.width - 1) {
                        continue;
                    }
                    float ds = spacialTable[kernelIndex];
                    float pixelGray = interpolate.get(x0 + xx, y0 + yy);
                    float dc = pixelGray - gray;
                    dc = dc * dc / maxColorDistanceSq;
                    float weight = dc > 1 ? 0 : weight((ds + dc) / 2f);
                    total += weight;
                    sumX += weight * (xx + x0);
                    sumY += weight * (yy + y0);
                    sumGray += weight * pixelGray;
                }
            }
        }
        if (total == 0)
            break;
        float peakX = sumX / total;
        float peakY = sumY / total;
        if (fast) {
            history.grow().set(peakX, peakY);
            // see if it has already been here before
            int px = (int) (peakX + 0.5f);
            int py = (int) (peakY + 0.5f);
            int index = pixelToMode.getIndex(px, py);
            int modeIndex = pixelToMode.data[index];
            if (modeIndex != -1) {
                // it already knows the solution so stop searching
                Point2D_I32 modeP = modeLocation.get(modeIndex);
                this.modeX = modeP.x;
                this.modeY = modeP.y;
                return;
            }
        }
        float dx = peakX - cx;
        float dy = peakY - cy;
        cx = peakX;
        cy = peakY;
        gray = sumGray / total;
        if (Math.abs(dx) < convergenceTol && Math.abs(dy) < convergenceTol) {
            break;
        }
    }
    this.modeX = cx;
    this.modeY = cy;
    this.meanGray = gray;
}
Also used : Point2D_I32(georegression.struct.point.Point2D_I32)

Aggregations

Point2D_I32 (georegression.struct.point.Point2D_I32)153 Test (org.junit.Test)64 ArrayList (java.util.ArrayList)41 GrowQueue_I32 (org.ddogleg.struct.GrowQueue_I32)21 Point2D_F64 (georegression.struct.point.Point2D_F64)11 EdgeContour (boofcv.alg.feature.detect.edge.EdgeContour)8 GrayF32 (boofcv.struct.image.GrayF32)8 GrayS32 (boofcv.struct.image.GrayS32)7 Contour (boofcv.alg.filter.binary.Contour)6 TupleDesc_F64 (boofcv.struct.feature.TupleDesc_F64)6 GrayU8 (boofcv.struct.image.GrayU8)6 PackedSetsPoint2D_I32 (boofcv.struct.PackedSetsPoint2D_I32)5 RectangleLength2D_I32 (georegression.struct.shapes.RectangleLength2D_I32)5 UtilPoint2D_I32 (georegression.geometry.UtilPoint2D_I32)4 Polygon2D_F64 (georegression.struct.shapes.Polygon2D_F64)4 EdgeSegment (boofcv.alg.feature.detect.edge.EdgeSegment)3 Corner (boofcv.alg.shapes.polyline.splitmerge.PolylineSplitMerge.Corner)3 FactoryDescribeImageDense (boofcv.factory.feature.dense.FactoryDescribeImageDense)3 PointIndex_I32 (boofcv.struct.PointIndex_I32)3 LineGeneral2D_F64 (georegression.struct.line.LineGeneral2D_F64)3