use of org.opencv.core.Rect in project Relic_Main by TeamOverdrive.
the class GlyphDetector method processFrame.
@Override
public Mat processFrame(Mat rgba, Mat gray) {
Size initSize = rgba.size();
newSize = new Size(initSize.width * downScaleFactor, initSize.height * downScaleFactor);
rgba.copyTo(workingMat);
Imgproc.resize(workingMat, workingMat, newSize);
if (rotateMat) {
Mat tempBefore = workingMat.t();
// mRgba.t() is the transpose
Core.flip(tempBefore, workingMat, 1);
tempBefore.release();
}
Imgproc.putText(workingMat, newSize.toString() + " - " + speed.toString(), new Point(5, 15), 0, 0.5, new Scalar(0, 255, 0), 1);
Imgproc.cvtColor(workingMat, processed, Imgproc.COLOR_RGB2GRAY);
switch(speed) {
case VERY_FAST:
Imgproc.blur(processed, processed, new Size(2, 2));
Imgproc.bilateralFilter(processed.clone(), processed, 11, 17, 17);
Imgproc.Canny(processed, edges, 15, 45.0);
structure = Imgproc.getStructuringElement(Imgproc.CV_SHAPE_RECT, new Size(3, 3));
Imgproc.morphologyEx(edges, edges, Imgproc.MORPH_CLOSE, structure);
break;
case FAST:
Imgproc.blur(processed, processed, new Size(3, 3));
Imgproc.bilateralFilter(processed.clone(), processed, 11, 17, 17);
Imgproc.Canny(processed, edges, 15, 45.0);
structure = Imgproc.getStructuringElement(Imgproc.CV_SHAPE_RECT, new Size(6, 6));
Imgproc.morphologyEx(edges, edges, Imgproc.MORPH_CLOSE, structure);
break;
case BALANCED:
Imgproc.blur(processed, processed, new Size(4, 4));
Imgproc.bilateralFilter(processed.clone(), processed, 11, 17, 17);
Imgproc.Canny(processed, edges, 15, 45.0);
structure = Imgproc.getStructuringElement(Imgproc.CV_SHAPE_RECT, new Size(7, 7));
Imgproc.morphologyEx(edges, edges, Imgproc.MORPH_CLOSE, structure);
break;
case SLOW:
Imgproc.blur(processed, processed, new Size(6, 6));
Imgproc.bilateralFilter(processed.clone(), processed, 11, 17, 17);
Imgproc.Canny(processed, edges, 15, 45.0);
structure = Imgproc.getStructuringElement(Imgproc.CV_SHAPE_RECT, new Size(10, 10));
Imgproc.morphologyEx(edges, edges, Imgproc.MORPH_CLOSE, structure);
break;
case VERY_SLOW:
Imgproc.blur(processed, processed, new Size(7, 7));
Imgproc.bilateralFilter(processed.clone(), processed, 11, 17, 17);
Imgproc.Canny(processed, edges, 15, 45.0);
structure = Imgproc.getStructuringElement(Imgproc.CV_SHAPE_RECT, new Size(15, 15));
Imgproc.morphologyEx(edges, edges, Imgproc.MORPH_CLOSE, structure);
break;
}
List<MatOfPoint> contours = new ArrayList<>();
Mat hierarchy = new Mat();
Imgproc.findContours(edges, contours, hierarchy, Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_SIMPLE);
hierarchy.release();
double chosenScore = 0;
Rect chosenRect = null;
Collections.sort(contours, new Comparator<MatOfPoint>() {
@Override
public int compare(MatOfPoint matOfPoint, MatOfPoint t1) {
if (Imgproc.contourArea(matOfPoint) > Imgproc.contourArea(t1)) {
return -1;
} else if (Imgproc.contourArea(matOfPoint) < Imgproc.contourArea(t1)) {
return 1;
} else {
return 0;
}
}
});
// Remove First Index which is usually a large square filling the entire screen,
contours.remove(0);
for (MatOfPoint c : contours) {
if (Imgproc.contourArea(c) > 1000) {
Rect rect = Imgproc.boundingRect(c);
double x = rect.x;
double y = rect.y;
double w = rect.width;
double h = rect.height;
Point centerPoint = new Point(x + (w / 2), y + (h / 2));
double cubeRatio = Math.max(Math.abs(h / w), Math.abs(w / h));
double score = 100;
double diffrenceFromPerfect = Math.abs(1 - cubeRatio);
double scoreRatioPunishment = 1 - diffrenceFromPerfect;
double scoreRatio = scoreRatioPunishment * scoreRatioWeight;
score *= scoreRatio;
double distanceFromCenterX = (newSize.width / 2) - centerPoint.x;
double distanceFromCenterY = newSize.height - centerPoint.y;
distanceFromCenterX = Math.abs(distanceFromCenterX / newSize.width);
distanceFromCenterY = Math.abs(distanceFromCenterY / newSize.height);
double scoreDistanceFromCenterXPunishment = 1 - distanceFromCenterX;
double scoreDistanceFromCenterYPunishment = 1 - distanceFromCenterY;
double scoreDistanceFromCenterX = scoreDistanceFromCenterXPunishment * scoreDistanceXWeight;
double scoreDistanceFromCenterY = scoreDistanceFromCenterYPunishment * scoreDistanceYWeight;
score *= scoreDistanceFromCenterX;
score *= scoreDistanceFromCenterY;
double minArea = GetMinArea(contours);
double maxArea = GetMaxArea(contours);
double area = Imgproc.contourArea(c);
double normalizedArea = (area - minArea) / (maxArea - minArea);
double scoreAreaPunishment = normalizedArea;
double scoreArea = scoreAreaPunishment * scoreAreaWeight;
score *= scoreArea;
if (chosenRect == null) {
chosenRect = rect;
chosenScore = score;
}
if (score > chosenScore) {
chosenRect = rect;
chosenScore = score;
}
if (debugDrawRects) {
Imgproc.rectangle(workingMat, new Point(x, y), new Point((x + w), (y + h)), new Scalar(0, 255, 255), 1);
}
if (debugDrawRects) {
String toPrint = String.format("Score: %.2f", score);
Imgproc.putText(workingMat, toPrint, new Point(x + 5, y + 5), 0, 0.5, new Scalar(0, 255, 255));
}
}
}
if (chosenRect != null && chosenScore > minScore) {
double x = chosenRect.x;
double y = chosenRect.y;
double w = chosenRect.width;
double h = chosenRect.height;
Imgproc.rectangle(workingMat, new Point(x, y), new Point((x + w), (y + h)), new Scalar(0, 255, 0), 3);
chosenGlyphPosition = new Point((x + (w / 2)), (y + (h / 2)));
chosenGlyphOffset = newSize.width - (x + (w / 2));
foundRect = false;
} else {
foundRect = true;
}
Imgproc.resize(workingMat, workingMat, initSize);
return workingMat;
}
use of org.opencv.core.Rect in project Relic_Main by TeamOverdrive.
the class JewelDetector method processFrame.
@Override
public Mat processFrame(Mat rgba, Mat gray) {
Size initSize = rgba.size();
newSize = new Size(initSize.width * downScaleFactor, initSize.height * downScaleFactor);
rgba.copyTo(workingMat);
Imgproc.resize(workingMat, workingMat, newSize);
if (rotateMat) {
Mat tempBefore = workingMat.t();
// mRgba.t() is the transpose
Core.flip(tempBefore, workingMat, -1);
tempBefore.release();
}
Mat redConvert = workingMat.clone();
Mat blueConvert = workingMat.clone();
colorFilterRed.process(redConvert, maskRed);
colorFilterBlue.process(blueConvert, maskBlue);
List<MatOfPoint> contoursRed = new ArrayList<>();
Imgproc.findContours(maskRed, contoursRed, hiarchy, Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_SIMPLE);
Imgproc.drawContours(workingMat, contoursRed, -1, new Scalar(230, 70, 70), 2);
Rect chosenRedRect = null;
double chosenRedScore = Integer.MAX_VALUE;
MatOfPoint2f approxCurve = new MatOfPoint2f();
for (MatOfPoint c : contoursRed) {
MatOfPoint2f contour2f = new MatOfPoint2f(c.toArray());
// Processing on mMOP2f1 which is in type MatOfPoint2f
double approxDistance = Imgproc.arcLength(contour2f, true) * 0.02;
Imgproc.approxPolyDP(contour2f, approxCurve, approxDistance, true);
// Convert back to MatOfPoint
MatOfPoint points = new MatOfPoint(approxCurve.toArray());
// Get bounding rect of contour
Rect rect = Imgproc.boundingRect(points);
// You can find this by printing the area of each found rect, then looking and finding what u deem to be perfect.
// Run this with the bot, on a balance board, with jewels in their desired location. Since jewels should mostly be
// in the same position, this hack could work nicely.
double area = Imgproc.contourArea(c);
double areaDiffrence = 0;
switch(detectionMode) {
case MAX_AREA:
areaDiffrence = -area * areaWeight;
break;
case PERFECT_AREA:
areaDiffrence = Math.abs(perfectArea - area);
break;
}
// Just declaring vars to make my life eassy
double x = rect.x;
double y = rect.y;
double w = rect.width;
double h = rect.height;
Point centerPoint = new Point(x + (w / 2), y + (h / 2));
// Get the ratio. We use max in case h and w get swapped??? it happens when u account for rotation
double cubeRatio = Math.max(Math.abs(h / w), Math.abs(w / h));
double ratioDiffrence = Math.abs(cubeRatio - perfectRatio);
double finalDiffrence = (ratioDiffrence * ratioWeight) + (areaDiffrence * areaWeight);
// Think of diffrence as score. 0 = perfect
if (finalDiffrence < chosenRedScore && finalDiffrence < maxDiffrence && area > minArea) {
chosenRedScore = finalDiffrence;
chosenRedRect = rect;
}
if (debugContours && area > 100) {
Imgproc.circle(workingMat, centerPoint, 3, new Scalar(0, 255, 255), 3);
Imgproc.putText(workingMat, "Area: " + area, centerPoint, 0, 0.5, new Scalar(0, 255, 255));
}
}
List<MatOfPoint> contoursBlue = new ArrayList<>();
Imgproc.findContours(maskBlue, contoursBlue, hiarchy, Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_SIMPLE);
Imgproc.drawContours(workingMat, contoursBlue, -1, new Scalar(70, 130, 230), 2);
Rect chosenBlueRect = null;
double chosenBlueScore = Integer.MAX_VALUE;
for (MatOfPoint c : contoursBlue) {
MatOfPoint2f contour2f = new MatOfPoint2f(c.toArray());
// Processing on mMOP2f1 which is in type MatOfPoint2f
double approxDistance = Imgproc.arcLength(contour2f, true) * 0.02;
Imgproc.approxPolyDP(contour2f, approxCurve, approxDistance, true);
// Convert back to MatOfPoint
MatOfPoint points = new MatOfPoint(approxCurve.toArray());
// Get bounding rect of contour
Rect rect = Imgproc.boundingRect(points);
// You can find this by printing the area of each found rect, then looking and finding what u deem to be perfect.
// Run this with the bot, on a balance board, with jewels in their desired location. Since jewels should mostly be
// in the same position, this hack could work nicely.
double area = Imgproc.contourArea(c);
double areaDiffrence = 0;
switch(detectionMode) {
case MAX_AREA:
areaDiffrence = -area * areaWeight;
break;
case PERFECT_AREA:
areaDiffrence = Math.abs(perfectArea - area);
break;
}
// Just declaring vars to make my life eassy
double x = rect.x;
double y = rect.y;
double w = rect.width;
double h = rect.height;
Point centerPoint = new Point(x + (w / 2), y + (h / 2));
// Get the ratio. We use max in case h and w get swapped??? it happens when u account for rotation
double cubeRatio = Math.max(Math.abs(h / w), Math.abs(w / h));
double ratioDiffrence = Math.abs(cubeRatio - 1);
double finalDiffrence = (ratioDiffrence * ratioWeight) + (areaDiffrence * areaWeight);
// Think of diffrence as score. 0 = perfect
if (finalDiffrence < chosenBlueScore && finalDiffrence < maxDiffrence && area > minArea) {
chosenBlueScore = finalDiffrence;
chosenBlueRect = rect;
}
if (debugContours && area > 100) {
Imgproc.circle(workingMat, centerPoint, 3, new Scalar(0, 255, 255), 3);
Imgproc.putText(workingMat, "Area: " + area, centerPoint, 0, 0.5, new Scalar(0, 255, 255));
}
}
if (chosenRedRect != null) {
Imgproc.rectangle(workingMat, new Point(chosenRedRect.x, chosenRedRect.y), new Point(chosenRedRect.x + chosenRedRect.width, chosenRedRect.y + chosenRedRect.height), new Scalar(255, 0, 0), 2);
Imgproc.putText(workingMat, "Red: " + String.format("%.2f", chosenRedScore), new Point(chosenRedRect.x - 5, chosenRedRect.y - 10), Core.FONT_HERSHEY_PLAIN, 1.3, new Scalar(255, 0, 0), 2);
}
if (chosenBlueRect != null) {
Imgproc.rectangle(workingMat, new Point(chosenBlueRect.x, chosenBlueRect.y), new Point(chosenBlueRect.x + chosenBlueRect.width, chosenBlueRect.y + chosenBlueRect.height), new Scalar(0, 0, 255), 2);
Imgproc.putText(workingMat, "Blue: " + String.format("%.2f", chosenBlueScore), new Point(chosenBlueRect.x - 5, chosenBlueRect.y - 10), Core.FONT_HERSHEY_PLAIN, 1.3, new Scalar(0, 0, 255), 2);
}
if (chosenBlueRect != null && chosenRedRect != null) {
if (chosenBlueRect.x < chosenRedRect.x) {
currentOrder = JewelOrder.BLUE_RED;
lastOrder = currentOrder;
} else {
currentOrder = JewelOrder.RED_BLUE;
lastOrder = currentOrder;
}
} else {
currentOrder = JewelOrder.UNKNOWN;
}
Imgproc.putText(workingMat, "Result: " + lastOrder.toString(), new Point(10, newSize.height - 30), 0, 1, new Scalar(255, 255, 0), 1);
Imgproc.putText(workingMat, "Current Track: " + currentOrder.toString(), new Point(10, newSize.height - 10), 0, 0.5, new Scalar(255, 255, 255), 1);
Imgproc.resize(workingMat, workingMat, initSize);
redConvert.release();
blueConvert.release();
Imgproc.putText(workingMat, "DogeCV 1.1 Jewel: " + newSize.toString() + " - " + speed.toString() + " - " + detectionMode.toString(), new Point(5, 30), 0, 1.2, new Scalar(0, 255, 255), 2);
return workingMat;
}
use of org.opencv.core.Rect in project Relic_Main by TeamOverdrive.
the class Converters method Mat_to_vector_Rect.
public static void Mat_to_vector_Rect(Mat m, List<Rect> rs) {
if (rs == null)
throw new java.lang.IllegalArgumentException("rs == null");
int count = m.rows();
if (CvType.CV_32SC4 != m.type() || m.cols() != 1)
throw new java.lang.IllegalArgumentException("CvType.CV_32SC4 != m.type() || m.rows()!=1\n" + m);
rs.clear();
int[] buff = new int[4 * count];
m.get(0, 0, buff);
for (int i = 0; i < count; i++) {
rs.add(new Rect(buff[4 * i], buff[4 * i + 1], buff[4 * i + 2], buff[4 * i + 3]));
}
}
use of org.opencv.core.Rect in project Relic_Main by TeamOverdrive.
the class Converters method vector_Rect_to_Mat.
public static Mat vector_Rect_to_Mat(List<Rect> rs) {
Mat res;
int count = (rs != null) ? rs.size() : 0;
if (count > 0) {
res = new Mat(count, 1, CvType.CV_32SC4);
int[] buff = new int[4 * count];
for (int i = 0; i < count; i++) {
Rect r = rs.get(i);
buff[4 * i] = r.x;
buff[4 * i + 1] = r.y;
buff[4 * i + 2] = r.width;
buff[4 * i + 3] = r.height;
}
res.put(0, 0, buff);
} else {
res = new Mat();
}
return res;
}
use of org.opencv.core.Rect in project FRC2018 by first95.
the class VisualGearLiftFinder method computeHeadingToTarget.
// Take in an image and process it. Call this before calling
public void computeHeadingToTarget() {
if (imageSource.isValid()) {
// imageSource.grabFrame(curFrame);
imageSource.grabFrameNoTimeout(curFrame);
if (!curFrame.empty()) {
pipeline.process(curFrame);
lastHeadingDeterminationSucceeded = false;
// Draw output of pipeline
ArrayList<Rect> boxes = pipeline.filterContoursBbOutput();
Imgproc.drawContours(curFrame, pipeline.filterContoursOutput(), -1, new Scalar(0, 0, 255));
for (Rect bb : boxes) {
Imgproc.rectangle(curFrame, bb.br(), bb.tl(), new Scalar(128, 255, 128));
heightOfObjectInPixels = bb.height;
distanceFromCamToTarget = (FOCAL_LENGTH / bb.height);
}
// If we only see one box then it's not enough information to see the target
if (boxes.size() >= 2) {
// Sort by largest to smallest (in terms of bounding box area)
boxes.sort(new Comparator<Rect>() {
@Override
public int compare(Rect o1, Rect o2) {
// so subtraction works as a shortcut.
return (int) (o2.area() - o1.area());
}
});
// Assume the two largest boxes are the ones to use.
// Find their boundaries.
// start at the right
double left_bound = curFrame.cols();
// start at the left
double right_bound = 0;
// start at the bottom
double top_bound = curFrame.rows();
// start at the top
double bottom_bound = 0;
for (int i = 0; i < 2 && i < NUM_BOXES_TO_CONSIDER; ++i) {
Rect bb = boxes.get(i);
Imgproc.putText(curFrame, "" + i, bb.tl(), 0, 0.75, new Scalar(255, 255, 255));
left_bound = Math.min(left_bound, bb.tl().x);
right_bound = Math.max(right_bound, bb.br().x);
top_bound = Math.min(top_bound, bb.tl().y);
bottom_bound = Math.max(bottom_bound, bb.br().y);
}
Imgproc.rectangle(curFrame, new Point(left_bound, top_bound), new Point(right_bound, bottom_bound), new Scalar(255, 255, 255));
// Confirm that the aspect ratio of the target is what we expect.
double aspect_ratio = (right_bound - left_bound) / (bottom_bound - top_bound);
if (aspect_ratio > TALLEST_ASPECT_RATIO && aspect_ratio < WIDEST_ASPECT_RATIO) {
// Finally, compute the heading
double target_center_in_image = (right_bound + left_bound) / 2.0;
double target_offset_from_center = target_center_in_image - (curFrame.cols() / 2.0);
Imgproc.line(curFrame, new Point(target_center_in_image, 0), new Point(target_center_in_image, curFrame.rows()), new Scalar(0, 255, 0));
SmartDashboard.putNumber("Target center (pixels)", target_offset_from_center);
lastDeterminedHeadingDegrees = target_offset_from_center * DEGREES_PER_PIXEL;
lastHeadingDeterminationSucceeded = true;
SmartDashboard.putString(REASON, "None.");
} else {
SmartDashboard.putString(REASON, "Aspect ratio of " + aspect_ratio + " outside limits.");
}
} else {
SmartDashboard.putString(REASON, "Insufficient contours passing filter");
}
curFrame.copyTo(outputFrame);
} else {
SmartDashboard.putString(REASON, "Sink not valid!");
}
}
}
Aggregations