<commit_before>package org.usfirst.frc.team339.Vision;

import java.util.Comparator;
import java.util.Vector;
import com.ni.vision.NIVision;
import com.ni.vision.NIVision.Image;
import org.usfirst.frc.team339.Hardware.Hardware;
import org.usfirst.frc.team339.HardwareInterfaces.KilroyCamera;
import org.usfirst.frc.team339.Vision.operators.ConvexHullOperator;
import org.usfirst.frc.team339.Vision.operators.HSLColorThresholdOperator;
import org.usfirst.frc.team339.Vision.operators.LoadColorImageJPEGOperator;
import org.usfirst.frc.team339.Vision.operators.RemoveSmallObjectsOperator;
import org.usfirst.frc.team339.Vision.operators.SaveBinaryImagePNGOperator;
import org.usfirst.frc.team339.Vision.operators.VisionOperatorInterface;
import edu.wpi.first.wpilibj.image.NIVisionException;

public class ImageProcessor
{

/**
 * A class that holds several statistics about particles.
 * 
 * The measures include:
 * area: The area, in pixels of the blob
 * boundingRectLeft: The x coordinate of the left side of the blob
 * boundingRectTop: The y coordinate on the top of the bounding rectangle of the
 * blob
 * boundingRectRight: The x coordinate of a point which lies on the right side
 * of the bounding rectangle of the blob
 * boundingRectBottom: The y coordinate of a point which lies on the bottom side
 * of the bounding rectangle of the blob
 * center_mass_x: the weighted center of mass of the particle, If the particle
 * were a solid object of uniform density and thickness, this would be the x
 * coord of the balancing point.
 * center_mass_y: the weighted center of mass of the particle, If the particle
 * were a solid object of uniform density and thickness, this would be the y
 * coord of the balancing point.
 * imageHeight: The height of the image containing the blob
 * imageWidth: the width of the image containing the blob
 * boundingRectWidth: the width of the rectangle which would perfectly bound the
 * blob
 * PercentAreaToImageArea: The percent of the image this blob fills
 * ConvexHullArea: The area filled by the convex hull of the image
 * 
 * @author Kilroy
 *
 */
public class ParticleReport implements Comparator<ParticleReport>,
        Comparable<ParticleReport>
{
// TODO: actually initialize these values
// TODO add boundingRectHeight (and aspect ratio?)
public double area;

// double BoundingRectLeft;
// double BoundingRectTop;
// double BoundingRectRight;
// double BoundingRectBottom;
public int boundingRectLeft;

public int boundingRectTop;

public int boundingRectRight;

public int boundingRectBottom;

public int center_mass_x;

public int center_mass_y;

public int imageHeight;

public int imageWidth;

public int boundingRectWidth;

public double PercentAreaToImageArea;

public double ConvexHullArea;

@Override
public int compare (ParticleReport r1, ParticleReport r2)
{
    return (int) (r1.area - r2.area);
}

@Override
public int compareTo (ParticleReport r)
{
    return (int) (r.area - this.area);
}
};

private KilroyCamera camera = null;

private Image currentImage = null;

// @AHK TODO create a visionScript object to further object orient the code?
private VisionScript operators = new VisionScript();

private double offsetFromCenterX;// offset along line orthoganal to the primary
                                 // vector of travel that intersects the center
                                 // potistive towards the starboard, negative
                                 // towards the port

private double offsetFromCenterY;// offset along primary vector of travel
                                 // positive is towards the front, negative
                                 // towards the back

private double cameraFocalLength;


public ParticleReport[] reports = null;

private boolean newImageIsFresh = true;// TODO @AHK use to determine if we
                                       // actually process an image

/**
 * Creates an ImageProcessor object with camera <camera> and a default
 * processing script. The script consists of:
 * 1. LoadColorImageJPEGOperator
 * 2. ColorThresholdOperator
 * 3. RemoveSmallObjectsOperator
 * 4. ConvexHullOperator
 * 5. SaveBinaryImagePNGOperator
 * 
 * @param camera
 *            The KiloryCamera object that corresponds to the camera on the
 *            robot capturing images for processing. DO NOT PASS NULL HERE!
 */
public ImageProcessor (KilroyCamera camera)
{
    // this.operators.add(new SaveColorImageJPEGOperator(
    // "/home/lvuser/images/Test.jpg"));
    // this.camera.getImage().image;
    this.operators.add(new LoadColorImageJPEGOperator(
            "/home/lvuser/images/Firstpic.jpg"));
    this.operators
            .add(new HSLColorThresholdOperator(0, 153, 0, 75, 5, 141));
    this.operators.add(new RemoveSmallObjectsOperator(2, true));
    this.operators.add(new ConvexHullOperator(true));
    this.operators.add(new SaveBinaryImagePNGOperator(
            "/home/lvuser/images/Out.png"));
    this.camera = camera;
}

public ImageProcessor (KilroyCamera camera, VisionScript script)
{
    this.camera = camera;
    this.operators = script;
}

public ImageProcessor (KilroyCamera camera,
        VisionOperatorInterface... ops)
{
    this.camera = camera;
    this.operators = new VisionScript();
    for (VisionOperatorInterface operator : ops)
        {
        this.operators.put(operator);
        }
}

@Deprecated
public ParticleReport[] getParticleAnalysisReports ()
{
    return this.reports;
}


public void applyOperators ()
{
    // Goes through all operators and applies whatever changes they are
    // programmed to apply. The currentImage is replaced with the altered
    // image.
    if (this.currentImage != null && this.newImageIsFresh == true)
        {
        for (int i = 0; i < operators.size(); i++)
            {
            this.currentImage = this.operators.get(i)
                    .operate(this.currentImage);
            }
        }
}

public void replaceVisionScript (VisionScript newScript)
{
    this.operators = newScript;
}

/**
 * Adds a new vision operator to the operator list, in zero-based position
 * <index>.
 * 
 * @param index
 *            The position in the list to add the operator (the list is
 *            traversed in order to process an image)
 * @param operator
 *            The VisionOperator to add to the list.
 * @author <NAME>
 */
public void addOperator (int index, VisionOperatorInterface operator)
{
    this.operators.add(index, operator);<commit_msg>Documented the ImageProcessor class much better and added some TODOs.<commit_after>package org.usfirst.frc.team339.Vision;

import java.util.Comparator;
import java.util.Vector;
import com.ni.vision.NIVision;
import com.ni.vision.NIVision.Image;
import org.usfirst.frc.team339.Hardware.Hardware;
import org.usfirst.frc.team339.HardwareInterfaces.KilroyCamera;
import org.usfirst.frc.team339.Vision.operators.ConvexHullOperator;
import org.usfirst.frc.team339.Vision.operators.HSLColorThresholdOperator;
import org.usfirst.frc.team339.Vision.operators.LoadColorImageJPEGOperator;
import org.usfirst.frc.team339.Vision.operators.RemoveSmallObjectsOperator;
import org.usfirst.frc.team339.Vision.operators.SaveBinaryImagePNGOperator;
import org.usfirst.frc.team339.Vision.operators.VisionOperatorInterface;
import edu.wpi.first.wpilibj.image.NIVisionException;

// TODO a processImageNoUpdate
// TODO the rest of the absolute position methods

public class ImageProcessor
{

/**
 * A class that holds several statistics about particles.
 * 
 * The measures include:
 * area: The area, in pixels of the blob
 * boundingRectLeft: The x coordinate of the left side of the blob
 * boundingRectTop: The y coordinate on the top of the bounding rectangle of the
 * blob
 * boundingRectRight: The x coordinate of a point which lies on the right side
 * of the bounding rectangle of the blob
 * boundingRectBottom: The y coordinate of a point which lies on the bottom side
 * of the bounding rectangle of the blob
 * center_mass_x: the weighted center of mass of the particle, If the particle
 * were a solid object of uniform density and thickness, this would be the x
 * coord of the balancing point.
 * center_mass_y: the weighted center of mass of the particle, If the particle
 * were a solid object of uniform density and thickness, this would be the y
 * coord of the balancing point.
 * imageHeight: The height of the image containing the blob
 * imageWidth: the width of the image containing the blob
 * boundingRectWidth: the width of the rectangle which would perfectly bound the
 * blob
 * PercentAreaToImageArea: The percent of the image this blob fills
 * ConvexHullArea: The area filled by the convex hull of the image
 * 
 * @author Kilroy
 *
 */
public class ParticleReport implements Comparator<ParticleReport>,
        Comparable<ParticleReport>
{
// TODO: actually initialize these values
// TODO add boundingRectHeight (and aspect ratio?)
public double area;

// double BoundingRectLeft;
// double BoundingRectTop;
// double BoundingRectRight;
// double BoundingRectBottom;
public int boundingRectLeft;

public int boundingRectTop;

public int boundingRectRight;

public int boundingRectBottom;

public int center_mass_x;

public int center_mass_y;

public int imageHeight;

public int imageWidth;

public int boundingRectWidth;

public double PercentAreaToImageArea;

public double ConvexHullArea;

@Override
public int compare (ParticleReport r1, ParticleReport r2)
{
    return (int) (r1.area - r2.area);
}

@Override
public int compareTo (ParticleReport r)
{
    return (int) (r.area - this.area);
}
};

private KilroyCamera camera = null;

private Image currentImage = null;

// @AHK TODO create a visionScript object to further object orient the code?
private VisionScript operators = new VisionScript();

private double offsetFromCenterX;// offset along line orthoganal to the primary
                                 // vector of travel that intersects the center
                                 // potistive towards the starboard, negative
                                 // towards the port

private double offsetFromCenterY;// offset along primary vector of travel
                                 // positive is towards the front, negative
                                 // towards the back

private double cameraFocalLength;

/**
 * 
 */
// TODO should this be public? Use a getter, methinks
public ParticleReport[] reports = null;

private boolean newImageIsFresh = true;// TODO @AHK use to determine if we
                                       // actually process an image

/**
 * Creates an ImageProcessor object with camera <camera> and a default
 * processing script. The script consists of:
 * 1. LoadColorImageJPEGOperator
 * 2. ColorThresholdOperator
 * 3. RemoveSmallObjectsOperator
 * 4. ConvexHullOperator
 * 5. SaveBinaryImagePNGOperator
 * 
 * @param camera
 *            The KiloryCamera object that corresponds to the camera on the
 *            robot capturing images for processing. DO NOT PASS NULL HERE!
 */
public ImageProcessor (KilroyCamera camera)
{
    // this.operators.add(new SaveColorImageJPEGOperator(
    // "/home/lvuser/images/Test.jpg"));
    // this.camera.getImage().image;
    this.operators.add(new LoadColorImageJPEGOperator(
            "/home/lvuser/images/Firstpic.jpg"));
    this.operators
            .add(new HSLColorThresholdOperator(0, 153, 0, 75, 5, 141));
    this.operators.add(new RemoveSmallObjectsOperator(2, true));
    this.operators.add(new ConvexHullOperator(true));
    this.operators.add(new SaveBinaryImagePNGOperator(
            "/home/lvuser/images/Out.png"));
    this.camera = camera;
}

/**
 * Creates a new ImageProcessor class with a camera and a custom vision
 * processing script.
 * 
 * @param camera
 *            The IP camera we'll use to capture images.
 * @param script
 *            The processing script object; it will be executed in the order
 *            they are organized in the object.
 */
public ImageProcessor (KilroyCamera camera, VisionScript script)
{
    this.camera = camera;
    this.operators = script;
}

/**
 * Creates a new ImageProcessor class with a camera and a custom vision
 * processing script
 * 
 * @param camera
 *            The IP camera with which we will capture images.
 * @param ops
 *            A parameter list of VisionOperatorInterfaces, passed in order to
 *            the constructor.
 *            The constructor will create a VisionScript object the the
 *            parameter list in the same order it was received.
 */
public ImageProcessor (KilroyCamera camera,
        VisionOperatorInterface... ops)
{
    this.camera = camera;
    this.operators = new VisionScript();
    for (VisionOperatorInterface operator : ops)
        {
        this.operators.put(operator);
        }
}

/**
 * 
 * @return
 *         An array containing ParticleReport objects for all our spotted blobs
 * @deprecated by <NAME>, for reason:
 *             You should no longer need to use actual raw values, use the
 *             position methods such as getYawAngleToTarget, etc.
 */
@Deprecated
public ParticleReport[] getParticleAnalysisReports ()
{
    return this.reports;
}

/**
 * Applies all the operators in the VisionScript to the image and saves the
 * updated image to the currentImage field.
 */
// TODO make private?
public void applyOperators ()
{
    // Goes through all operators and applies whatever changes they are
    // programmed to apply. The currentImage is replaced with the altered
    // image.
    if (this.currentImage != null && this.newImageIsFresh == true)
        {
        for (int i = 0; i < operators.size(); i++)
            {
            this.currentImage = this.operators.get(i)
                    .operate(this.currentImage);
            }
        }
}

/**
 * Takes the current VisionScript controller for the class and replaces it with
 * the provided one.
 * 
 * @param newScript
 *            The VisionScript object with which to replace the processing
 *            script
 * @author
 *         <NAME>
 */
public void replaceVisionScript (VisionScript newScript)
{
    this.operators = newScript;
}

// TODO move the following methods to VisionScript and add a getVisionScript()
// method.
/**
 * Adds a new vision operator to the operator list, in zero-based position
 * <index>.
 * 
 * @param index
 *            The position in the list to add the operator (the list is
 *            traversed in order to process an image)
 * @param operator
 *            The VisionOperator to add to the list.
 * @author <NAME>
 */
public void addOperator (int index, VisionOperatorInterface operator)
{
    this.operators.add(index, operator);
{'fraction_non_alphanumeric': 0.07577512776831345, 'fraction_numerical': 0.006678023850085179, 'mean_word_length': 3.1563296516567543, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 14, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1885258', 'n_tokens_mistral': 4065, 'n_tokens_neox': 3926, 'n_words': 1446}