001/*
002 * Copyright (C) Photon Vision.
003 *
004 * This program is free software: you can redistribute it and/or modify
005 * it under the terms of the GNU General Public License as published by
006 * the Free Software Foundation, either version 3 of the License, or
007 * (at your option) any later version.
008 *
009 * This program is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
012 * GNU General Public License for more details.
013 *
014 * You should have received a copy of the GNU General Public License
015 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
016 */
017
018package org.photonvision.vision.pipe.impl;
019
020import java.util.ArrayList;
021import java.util.List;
022import org.opencv.imgproc.Imgproc;
023import org.photonvision.vision.opencv.CVShape;
024import org.photonvision.vision.opencv.Contour;
025import org.photonvision.vision.opencv.ContourShape;
026import org.photonvision.vision.pipe.CVPipe;
027
028public class FindPolygonPipe
029        extends CVPipe<List<Contour>, List<CVShape>, FindPolygonPipe.FindPolygonPipeParams> {
030    List<CVShape> shapeList = new ArrayList<>();
031
032    /*
033     * Runs the process for the pipe.
034     *
035     * @param in Input for pipe processing.
036     * @return Result of processing.
037     */
038    @Override
039    protected List<CVShape> process(List<Contour> in) {
040        shapeList.forEach(CVShape::release);
041        shapeList.clear();
042        shapeList = new ArrayList<>();
043
044        for (Contour contour : in) {
045            shapeList.add(getShape(contour));
046        }
047
048        return shapeList;
049    }
050
051    private CVShape getShape(Contour in) {
052        int corners = getCorners(in);
053        return new CVShape(in, ContourShape.fromSides(corners));
054    }
055
056    private int getCorners(Contour contour) {
057        var approx =
058                contour.getApproxPolyDp(
059                        (100 - params.accuracyPercentage) / 100.0 * Imgproc.arcLength(contour.getMat2f(), true),
060                        true);
061
062        // The height of the resultant approximation is the number of vertices
063        return (int) approx.size().height;
064    }
065
066    public static class FindPolygonPipeParams {
067        private final double accuracyPercentage;
068
069        // Should be a value between 0-100
070        public FindPolygonPipeParams(double accuracyPercentage) {
071            this.accuracyPercentage = accuracyPercentage;
072        }
073    }
074}