Go to Post Innovating for the sake of innovating, reinventing the wheel is probably the second biggest pitfall you can fall into when designing an FRC robot, if the wheel is already a very optimized, good solution. - Chris is me [more]
Home
Go Back   Chief Delphi > Technical > Programming > Java
CD-Media   CD-Spy  
portal register members calendar search Today's Posts Mark Forums Read FAQ rules

 
Reply
Thread Tools Rate Thread Display Modes
  #1   Spotlight this post!  
Unread 03-02-2017, 20:33
Jakkits_ Jakkits_ is offline
Registered User
FRC #4013
 
Join Date: Jan 2017
Location: Florida
Posts: 3
Jakkits_ is an unknown quantity at this point
Having trouble with GRIP vision processing

Our team is trying to do vision processing using GRIP, and to do so, we are trying to calculate the centerX value of a rectangle around a contour, but the code for forming the rectangle keeps giving us an error:

ERROR 1 ERROR Unhandled exception: java.lang.IndexOutOfBoundsException: Index: 0, Size: 0 at [java.util.ArrayList.rangeCheck(Arraylist.java:638) , java.util.ArrayList.get(ArrayList.java:414), org.usfirst.frc.team4013.robot.GripPipelinethree.. process(GripPipelinethree.java:75), org.usfirst.frc.team4013.robot.Robot.teleopPeriodi c(Robot.java:110), edu.wpi.first.wpilibj.IterativeRobot.startCompetit ion(IterativeRobot.java:130), edu.wpi.first.wpilibj.RobotBase.main(RobotBase.jav a:247)] edu.wpi.first.wpilibj.RobotBase.main(RobotBase.jav a:249)

I think the error is showing that the rectangle is being constructed with a width of zero, and we don't know why.

If I'm wrong about the error, or if anyone sees anything in the code that could be messing up the rectangle, please let me know.

The code for the GRIP pipeline is below(that is the bit of code that keeps giving us the error, we think):

Code:
package org.usfirst.frc.team4013.robot;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.HashMap;
import org.opencv.imgproc.Imgproc;

import edu.wpi.first.wpilibj.networktables.NetworkTable;
import edu.wpi.first.wpilibj.vision.VisionPipeline;
import edu.wpi.first.wpilibj.vision.VisionRunner;
import edu.wpi.first.wpilibj.vision.VisionThread;

import org.opencv.core.*;
import org.opencv.core.Core.*;
import org.opencv.features2d.FeatureDetector;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.*;
import org.opencv.objdetect.*;

/**
* GripPipeline class.
*
* <p>An OpenCV pipeline generated by GRIP.
*
* @author GRIP
*/
public class GripPipeline implements VisionPipeline {
	            
	private VisionThread visionThread;
	private double centerX = 0.0;

	//Outputs
	private Mat hsvThresholdOutput = new Mat();
	private ArrayList<MatOfPoint> findContoursOutput = new ArrayList<MatOfPoint>();
	public ArrayList<MatOfPoint> filterContoursOutput = new ArrayList<MatOfPoint>();
	
	static {
		System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
	}

	/**
	 * This is the primary method that runs the entire pipeline and updates the outputs.
	 */
	@Override	public void process(Mat source0) {
		// Step HSV_Threshold0:
		Mat hsvThresholdInput = source0;
		double[] hsvThresholdHue = {36.66666666666666, 46.66666666666666};
		double[] hsvThresholdSaturation = {0.0, 5.0};
		double[] hsvThresholdValue = {245.0, 255.0};
		hsvThreshold(hsvThresholdInput, hsvThresholdHue, hsvThresholdSaturation, hsvThresholdValue, hsvThresholdOutput);

		// Step Find_Contours0:
		Mat findContoursInput = hsvThresholdOutput;
		boolean findContoursExternalOnly = false;
		findContours(findContoursInput, findContoursExternalOnly, findContoursOutput);

		// Step Filter_Contours0:
		ArrayList<MatOfPoint> filterContoursContours = findContoursOutput;
		double filterContoursMinArea = 1000.0;
		double filterContoursMinPerimeter = 0;
		double filterContoursMinWidth = 0;
		double filterContoursMaxWidth = 1000;
		double filterContoursMinHeight = 0;
		double filterContoursMaxHeight = 100.0;
		double[] filterContoursSolidity = {0.0, 100};
		double filterContoursMaxVertices = 1000000;
		double filterContoursMinVertices = 0;
		double filterContoursMinRatio = 0;
		double filterContoursMaxRatio = 1000;
		filterContours(filterContoursContours, filterContoursMinArea, filterContoursMinPerimeter, filterContoursMinWidth, filterContoursMaxWidth, filterContoursMinHeight, filterContoursMaxHeight, filterContoursSolidity, filterContoursMaxVertices, filterContoursMinVertices, filterContoursMinRatio, filterContoursMaxRatio, filterContoursOutput);
		
		Rect r = Imgproc.boundingRect(filterContoursOutput().get(0)); 
            centerX = r.x + (r.width / 2);
		NetworkTable.getTable("GRIP").putNumber("centerX", centerX);
	}

	/**
	 * This method is a generated getter for the output of a HSV_Threshold.
	 * @return Mat output from HSV_Threshold.
	 */
	public Mat hsvThresholdOutput() {
		return hsvThresholdOutput;
	}

	/**
	 * This method is a generated getter for the output of a Find_Contours.
	 * @return ArrayList<MatOfPoint> output from Find_Contours.
	 */
	public ArrayList<MatOfPoint> findContoursOutput() {
		return findContoursOutput;
	}

	/**
	 * This method is a generated getter for the output of a Filter_Contours.
	 * @return ArrayList<MatOfPoint> output from Filter_Contours.
	 */
	public ArrayList<MatOfPoint> filterContoursOutput() {
		return filterContoursOutput;
	}


	/**
	 * Segment an image based on hue, saturation, and value ranges.
	 *
	 * @param input The image on which to perform the HSL threshold.
	 * @param hue The min and max hue
	 * @param sat The min and max saturation
	 * @param val The min and max value
	 * @param output The image in which to store the output.
	 */
	private void hsvThreshold(Mat input, double[] hue, double[] sat, double[] val,
	    Mat out) {
		Imgproc.cvtColor(input, out, Imgproc.COLOR_BGR2HSV);
		Core.inRange(out, new Scalar(hue[0], sat[0], val[0]),
			new Scalar(hue[1], sat[1], val[1]), out);
	}

	/**
	 * Sets the values of pixels in a binary image to their distance to the nearest black pixel.
	 * @param input The image on which to perform the Distance Transform.
	 * @param type The Transform.
	 * @param maskSize the size of the mask.
	 * @param output The image in which to store the output.
	 */
	private void findContours(Mat input, boolean externalOnly,
		List<MatOfPoint> contours) {
		Mat hierarchy = new Mat();
		contours.clear();
		int mode;
		if (externalOnly) {
			mode = Imgproc.RETR_EXTERNAL;
		}
		else {
			mode = Imgproc.RETR_LIST;
		}
		int method = Imgproc.CHAIN_APPROX_SIMPLE;
		Imgproc.findContours(input, contours, hierarchy, mode, method);
	}


	/**
	 * Filters out contours that do not meet certain criteria.
	 * @param inputContours is the input list of contours
	 * @param output is the the output list of contours
	 * @param minArea is the minimum area of a contour that will be kept
	 * @param minPerimeter is the minimum perimeter of a contour that will be kept
	 * @param minWidth minimum width of a contour
	 * @param maxWidth maximum width
	 * @param minHeight minimum height
	 * @param maxHeight maximimum height
	 * @param Solidity the minimum and maximum solidity of a contour
	 * @param minVertexCount minimum vertex Count of the contours
	 * @param maxVertexCount maximum vertex Count
	 * @param minRatio minimum ratio of width to height
	 * @param maxRatio maximum ratio of width to height
	 */
	private void filterContours(List<MatOfPoint> inputContours, double minArea,
		double minPerimeter, double minWidth, double maxWidth, double minHeight, double
		maxHeight, double[] solidity, double maxVertexCount, double minVertexCount, double
		minRatio, double maxRatio, List<MatOfPoint> output) {
		final MatOfInt hull = new MatOfInt();
		output.clear();
		//operation
		for (int i = 0; i < inputContours.size(); i++) {
			final MatOfPoint contour = inputContours.get(i);
			final Rect bb = Imgproc.boundingRect(contour);
			if (bb.width < minWidth || bb.width > maxWidth) continue;
			if (bb.height < minHeight || bb.height > maxHeight) continue;
			final double area = Imgproc.contourArea(contour);
			if (area < minArea) continue;
			if (Imgproc.arcLength(new MatOfPoint2f(contour.toArray()), true) < minPerimeter) continue;
			Imgproc.convexHull(contour, hull);
			MatOfPoint mopHull = new MatOfPoint();
			mopHull.create((int) hull.size().height, 1, CvType.CV_32SC2);
			for (int j = 0; j < hull.size().height; j++) {
				int index = (int)hull.get(j, 0)[0];
				double[] point = new double[] { contour.get(index, 0)[0], contour.get(index, 0)[1]};
				mopHull.put(j, 0, point);
			}
			final double solid = 100 * area / Imgproc.contourArea(mopHull);
			if (solid < solidity[0] || solid > solidity[1]) continue;
			if (contour.rows() < minVertexCount || contour.rows() > maxVertexCount)	continue;
			final double ratio = bb.width / (double)bb.height;
			if (ratio < minRatio || ratio > maxRatio) continue;
			output.add(contour);
		}
	}




}
Reply With Quote
  #2   Spotlight this post!  
Unread 03-02-2017, 20:50
soundfx's Avatar
soundfx soundfx is offline
Registered User
AKA: Aaron J
FRC #3238 (Cyborg Ferrets)
Team Role: Programmer
 
Join Date: Jan 2016
Rookie Year: 2014
Location: Anacortes, WA
Posts: 21
soundfx is an unknown quantity at this point
Re: Having trouble with GRIP vision processing

I believe the error is indicating that your list is not actually populated, meaning that there are no contours being found and placed into that list. I'm not sure exactly what would be causing that, but make sure to check your parameters and tune them accordingly.
__________________


"I got 99 problems but 0.999 ain't 1."
~Orteil
Reply With Quote
  #3   Spotlight this post!  
Unread 04-02-2017, 13:39
Jakkits_ Jakkits_ is offline
Registered User
FRC #4013
 
Join Date: Jan 2017
Location: Florida
Posts: 3
Jakkits_ is an unknown quantity at this point
Re: Having trouble with GRIP vision processing

In GRIP, it's finding the contours with the same parameters that we've set, and everything seems to be working properly aside from the GRIP pipeline in the Eclipse code, but we'll look into it, thanks.
Reply With Quote
  #4   Spotlight this post!  
Unread 04-02-2017, 20:49
SamCarlberg's Avatar
SamCarlberg SamCarlberg is online now
GRIP, WPILib. 2084 alum
FRC #2084
Team Role: Mentor
 
Join Date: Nov 2015
Rookie Year: 2009
Location: MA
Posts: 161
SamCarlberg is a splendid one to beholdSamCarlberg is a splendid one to beholdSamCarlberg is a splendid one to beholdSamCarlberg is a splendid one to beholdSamCarlberg is a splendid one to beholdSamCarlberg is a splendid one to beholdSamCarlberg is a splendid one to behold
Re: Having trouble with GRIP vision processing

This line is absolutely the problem:

Code:
Rect r = Imgproc.boundingRect(filterContoursOutput().get(0));
You have to do bounds checking before getting data from lists

Judging by the stacktrace, it looks like you're also calling the vision processing code directly from teleopPeriodic... do not do this. This kind of vision processing will take about 80ms, or four times longer than the refresh rate of the teleopPeriodic function. Your robot will very rarely respond to user input, or sensors, or update motors, or...

You need to read this ScreenSteps page and understand it.
__________________
WPILib
GRIP, RobotBuilder
Reply With Quote
  #5   Spotlight this post!  
Unread 06-02-2017, 16:17
Jakkits_ Jakkits_ is offline
Registered User
FRC #4013
 
Join Date: Jan 2017
Location: Florida
Posts: 3
Jakkits_ is an unknown quantity at this point
Re: Having trouble with GRIP vision processing

Thanks, we actually just fixed the problem of not checking the pipeline first, and we aren't running this vision processing code in teleop, just in autonomous.
Reply With Quote
Reply


Thread Tools
Display Modes Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump


All times are GMT -5. The time now is 09:43.

The Chief Delphi Forums are sponsored by Innovation First International, Inc.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright © Chief Delphi