Major pipeline optimizations, moved grabFrame in to vision thread

This commit is contained in:
Banks Troutman
2019-11-26 02:55:05 -05:00
parent 4bebc3d063
commit f6e56ce930
15 changed files with 236 additions and 289 deletions

View File

@@ -89,11 +89,10 @@ public class CVPipeline2d extends CVPipeline<CVPipeline2dResult, CVPipeline2dSet
if (cameraCapture == null) {
throw new RuntimeException("Pipeline was not initialized before being run!");
}
if(inputMat.cols() <= 1) {
if (inputMat.cols() <= 1) {
throw new RuntimeException("Input Mat is empty!");
}
pipelineTimeStringBuilder = new StringBuilder();
inputMat.copyTo(rawCameraMat);

View File

@@ -9,6 +9,7 @@ public abstract class CVPipelineResult<T> {
public final boolean hasTarget;
public final Mat outputMat;
public final long processTime;
public long imageTimestamp = 0;
public CVPipelineResult(List<T> targets, Mat outputMat, long processTime) {
this.targets = targets;
@@ -16,4 +17,8 @@ public abstract class CVPipelineResult<T> {
this.outputMat = outputMat;
this.processTime = processTime;
}
public void setTimestamp(long timestamp) {
imageTimestamp = timestamp;
}
}

View File

@@ -30,6 +30,7 @@ public class BlurPipe implements Pipe<Mat, Mat> {
try {
Imgproc.blur(processBuffer, processBuffer, new Size(blurSize, blurSize));
processBuffer.copyTo(outputMat);
processBuffer.release();
} catch (CvException e) {
System.err.println("(BlurPipe) Exception thrown by OpenCV: \n" + e.getMessage());
}
@@ -37,10 +38,7 @@ public class BlurPipe implements Pipe<Mat, Mat> {
input.copyTo(outputMat);
}
long processTime = System.nanoTime() - processStartNanos;
Pair<Mat, Long> output = Pair.of(outputMat, processTime);
processBuffer.release();
return output;
return Pair.of(outputMat, processTime);
}
}

View File

@@ -43,30 +43,32 @@ public class Collect2dTargetsPipe implements Pipe<List<RotatedRect>, List<CVPipe
targets.clear();
input.forEach(r -> {
CVPipeline2d.Target2d t = new CVPipeline2d.Target2d();
t.rawPoint = r;
switch (calibrationMode) {
case None:
t.calibratedX = camProps.centerX;
t.calibratedY = camProps.centerY;
break;
case Single:
t.calibratedX = calibrationPoint.get(0).doubleValue();
t.calibratedY = calibrationPoint.get(1).doubleValue();
break;
case Dual:
t.calibratedX = (r.center.y - calibrationB) / calibrationM;
t.calibratedY = (r.center.x * calibrationM) + calibrationB;
break;
if (input.size() > 0) {
for (RotatedRect r : input) {
CVPipeline2d.Target2d t = new CVPipeline2d.Target2d();
t.rawPoint = r;
switch (calibrationMode) {
case None:
t.calibratedX = camProps.centerX;
t.calibratedY = camProps.centerY;
break;
case Single:
t.calibratedX = calibrationPoint.get(0).doubleValue();
t.calibratedY = calibrationPoint.get(1).doubleValue();
break;
case Dual:
t.calibratedX = (r.center.y - calibrationB) / calibrationM;
t.calibratedY = (r.center.x * calibrationM) + calibrationB;
break;
}
t.pitch = calculatePitch(r.center.y, t.calibratedY);
t.yaw = calculateYaw(r.center.x, t.calibratedX);
t.area = r.size.area();
targets.add(t);
}
t.pitch = calculatePitch(r.center.y, t.calibratedY);
t.yaw = calculateYaw(r.center.x, t.calibratedX);
t.area = r.size.area();
targets.add(t);
});
}
long processTime = System.nanoTime() - processStartNanos;
return Pair.of(targets, processTime);

View File

@@ -17,6 +17,7 @@ public class Draw2dContoursPipe implements Pipe<Pair<Mat, List<RotatedRect>>, Ma
private final Draw2dContoursSettings settings;
private CaptureStaticProperties camProps;
private Mat processBuffer = new Mat();
private Mat outputMat = new Mat();
public Draw2dContoursPipe(Draw2dContoursSettings settings, CaptureStaticProperties camProps) {
@@ -32,48 +33,51 @@ public class Draw2dContoursPipe implements Pipe<Pair<Mat, List<RotatedRect>>, Ma
public Pair<Mat, Long> run(Pair<Mat, List<RotatedRect>> input) {
long processStartNanos = System.nanoTime();
outputMat = input.getLeft();
if (settings.showCrosshair || settings.showCentroid || settings.showMaximumBox || settings.showRotatedBox) {
input.getLeft().copyTo(processBuffer);
if (input.getRight() != null && !input.getRight().isEmpty()) {
for (RotatedRect r : input.getRight()) {
if (r == null) continue;
if (input.getRight().size() > 0) {
for (RotatedRect r : input.getRight()) {
if (r == null) continue;
List<MatOfPoint> drawnContour = new ArrayList<>();
Point[] vertices = new Point[4];
r.points(vertices);
MatOfPoint contour = new MatOfPoint(vertices);
drawnContour.add(contour);
List<MatOfPoint> drawnContour = new ArrayList<>();
Point[] vertices = new Point[4];
r.points(vertices);
MatOfPoint contour = new MatOfPoint(vertices);
drawnContour.add(contour);
if (settings.showCentroid) {
Imgproc.circle(outputMat, r.center, 3, Helpers.colorToScalar(settings.centroidColor));
}
if (settings.showCentroid) {
Imgproc.circle(processBuffer, r.center, 3, Helpers.colorToScalar(settings.centroidColor));
}
if (settings.showRotatedBox) {
Imgproc.drawContours(outputMat, drawnContour, 0, Helpers.colorToScalar(settings.rotatedBoxColor), settings.boxOutlineSize);
}
if (settings.showRotatedBox) {
Imgproc.drawContours(processBuffer, drawnContour, 0, Helpers.colorToScalar(settings.rotatedBoxColor), settings.boxOutlineSize);
}
if (settings.showMaximumBox) {
Rect box = Imgproc.boundingRect(contour);
Imgproc.rectangle(outputMat, new Point(box.x, box.y), new Point((box.x + box.width), (box.y + box.height)), Helpers.colorToScalar(settings.maximumBoxColor), settings.boxOutlineSize);
if (settings.showMaximumBox) {
Rect box = Imgproc.boundingRect(contour);
Imgproc.rectangle(processBuffer, new Point(box.x, box.y), new Point((box.x + box.width), (box.y + box.height)), Helpers.colorToScalar(settings.maximumBoxColor), settings.boxOutlineSize);
}
}
}
}
if (settings.showCrosshair) {
Point xMax = new Point(camProps.centerX + 10, camProps.centerY);
Point xMin = new Point(camProps.centerX - 10, camProps.centerY);
Point yMax = new Point(camProps.centerX, camProps.centerY + 10);
Point yMin = new Point(camProps.centerX, camProps.centerY - 10);
if (outputMat != null && outputMat.cols() > 0) {
Imgproc.line(outputMat, xMax, xMin, Helpers.colorToScalar(settings.crosshairColor), 2);
Imgproc.line(outputMat, yMax, yMin, Helpers.colorToScalar(settings.crosshairColor), 2);
if (settings.showCrosshair) {
Point xMax = new Point(camProps.centerX + 10, camProps.centerY);
Point xMin = new Point(camProps.centerX - 10, camProps.centerY);
Point yMax = new Point(camProps.centerX, camProps.centerY + 10);
Point yMin = new Point(camProps.centerX, camProps.centerY - 10);
Imgproc.line(processBuffer, xMax, xMin, Helpers.colorToScalar(settings.crosshairColor), 2);
Imgproc.line(processBuffer, yMax, yMin, Helpers.colorToScalar(settings.crosshairColor), 2);
}
processBuffer.copyTo(outputMat);
processBuffer.release();
} else {
input.getLeft().copyTo(outputMat);
}
long processTime = System.nanoTime() - processStartNanos;
Pair<Mat, Long> output = Pair.of(outputMat, processTime);
outputMat.release();
return output;
return Pair.of(outputMat, processTime);
}
public static class Draw2dContoursSettings {

View File

@@ -30,20 +30,24 @@ public class ErodeDilatePipe implements Pipe<Mat, Mat> {
public Pair<Mat, Long> run(Mat input) {
long processStartNanos = System.nanoTime();
input.copyTo(processBuffer);
if (erode || dilate) {
input.copyTo(processBuffer);
if (erode) {
Imgproc.erode(processBuffer, processBuffer, kernel);
}
if (erode) {
Imgproc.erode(processBuffer, processBuffer, kernel);
}
if (dilate) {
Imgproc.erode(processBuffer, processBuffer, kernel);
if (dilate) {
Imgproc.erode(processBuffer, processBuffer, kernel);
}
processBuffer.copyTo(outputMat);
processBuffer.release();
} else {
input.copyTo(outputMat);
}
long processTime = System.nanoTime() - processStartNanos;
processBuffer.copyTo(outputMat);
Pair<Mat, Long> output = Pair.of(outputMat, processTime);
processBuffer.release();
return output;
return Pair.of(outputMat, processTime);
}
}

View File

@@ -40,30 +40,32 @@ public class FilterContoursPipe implements Pipe<List<MatOfPoint>, List<MatOfPoin
filteredContours.clear();
for (MatOfPoint Contour : input) {
try {
double contourArea = Imgproc.contourArea(Contour);
double AreaRatio = (contourArea / camProps.imageArea) * 100;
double minArea = (MathHandler.sigmoid(area.get(0)));
double maxArea = (MathHandler.sigmoid(area.get(1)));
if (AreaRatio < minArea || AreaRatio > maxArea) {
continue;
if (input.size() > 0) {
for (MatOfPoint Contour : input) {
try {
double contourArea = Imgproc.contourArea(Contour);
double AreaRatio = (contourArea / camProps.imageArea) * 100;
double minArea = (MathHandler.sigmoid(area.get(0)));
double maxArea = (MathHandler.sigmoid(area.get(1)));
if (AreaRatio < minArea || AreaRatio > maxArea) {
continue;
}
var rect = Imgproc.minAreaRect(new MatOfPoint2f(Contour.toArray()));
double minExtent = (extent.get(0).doubleValue() * rect.size.area()) / 100;
double maxExtent = (extent.get(1).doubleValue() * rect.size.area()) / 100;
if (contourArea <= minExtent || contourArea >= maxExtent) {
continue;
}
Rect bb = Imgproc.boundingRect(Contour);
double aspectRatio = ((double)bb.width / bb.height);
if (aspectRatio < ratio.get(0).doubleValue() || aspectRatio > ratio.get(1).doubleValue()) {
continue;
}
filteredContours.add(Contour);
} catch (Exception e) {
System.err.println("Error while filtering contours");
e.printStackTrace();
}
var rect = Imgproc.minAreaRect(new MatOfPoint2f(Contour.toArray()));
double minExtent = (extent.get(0).doubleValue() * rect.size.area()) / 100;
double maxExtent = (extent.get(1).doubleValue() * rect.size.area()) / 100;
if (contourArea <= minExtent || contourArea >= maxExtent) {
continue;
}
Rect bb = Imgproc.boundingRect(Contour);
double aspectRatio = ((double)bb.width / bb.height);
if (aspectRatio < ratio.get(0).doubleValue() || aspectRatio > ratio.get(1).doubleValue()) {
continue;
}
filteredContours.add(Contour);
} catch (Exception e) {
System.err.println("Error while filtering contours");
e.printStackTrace();
}
}

View File

@@ -41,56 +41,59 @@ public class GroupContoursPipe implements Pipe<List<MatOfPoint>, List<RotatedRec
groupedContours.clear();
List<MatOfPoint> sorted = new ArrayList<>(input);
sorted.sort(sortByMomentsX);
if (input.size() > 0) {
Collections.reverse(sorted);
List<MatOfPoint> sorted = new ArrayList<>(input);
sorted.sort(sortByMomentsX);
switch (group) {
case Single: {
input.forEach(c -> {
MatOfPoint2f contour = new MatOfPoint2f();
contour.fromArray(c.toArray());
if (contour.cols() != 0 && contour.rows() != 0) {
RotatedRect rect = Imgproc.minAreaRect(contour);
groupedContours.add(rect);
}
});
break;
}
case Dual: {
for (var i = 0; i < input.size(); i++) {
List<Point> finalContourList = new ArrayList<>(input.get(i).toList());
try {
MatOfPoint firstContour = input.get(i);
MatOfPoint secondContour = input.get(i + 1);
if (isIntersecting(firstContour, secondContour)) {
finalContourList.addAll(secondContour.toList());
} else {
finalContourList.clear();
continue;
}
intersectMatA.release();
intersectMatB.release();
firstContour.release();
secondContour.release();
Collections.reverse(sorted);
switch (group) {
case Single: {
input.forEach(c -> {
MatOfPoint2f contour = new MatOfPoint2f();
contour.fromList(finalContourList);
contour.fromArray(c.toArray());
if (contour.cols() != 0 && contour.rows() != 0) {
RotatedRect rect = Imgproc.minAreaRect(contour);
groupedContours.add(rect);
}
} catch (IndexOutOfBoundsException e) {
System.err.println("GroupContours: WTF");
finalContourList.clear();
}
});
break;
}
case Dual: {
for (var i = 0; i < input.size(); i++) {
List<Point> finalContourList = new ArrayList<>(input.get(i).toList());
try {
MatOfPoint firstContour = input.get(i);
MatOfPoint secondContour = input.get(i + 1);
if (isIntersecting(firstContour, secondContour)) {
finalContourList.addAll(secondContour.toList());
} else {
finalContourList.clear();
continue;
}
intersectMatA.release();
intersectMatB.release();
firstContour.release();
secondContour.release();
MatOfPoint2f contour = new MatOfPoint2f();
contour.fromList(finalContourList);
if (contour.cols() != 0 && contour.rows() != 0) {
RotatedRect rect = Imgproc.minAreaRect(contour);
groupedContours.add(rect);
}
} catch (IndexOutOfBoundsException e) {
System.err.println("GroupContours: WTF");
finalContourList.clear();
}
}
break;
}
break;
}
}

View File

@@ -38,11 +38,11 @@ public class HsvPipe implements Pipe<Mat, Mat> {
System.err.println("(HsvPipe) Exception thrown by OpenCV: \n" + e.getMessage());
}
long processTime = System.nanoTime() - processStartNanos;
processBuffer.copyTo(outputMat);
Pair<Mat, Long> output = Pair.of(outputMat, processTime);
processBuffer.release();
return output;
long processTime = System.nanoTime() - processStartNanos;
return Pair.of(outputMat, processTime);
}
}

View File

@@ -28,15 +28,27 @@ public class RotateFlipPipe implements Pipe<Mat, Mat> {
public Pair<Mat, Long> run(Mat input) {
long processStartNanos = System.nanoTime();
input.copyTo(processBuffer);
boolean shouldFlip = !flip.equals(ImageFlipMode.NONE);
boolean shouldRotate = !rotation.equals(ImageRotation.DEG_0);
Core.flip(processBuffer, processBuffer, flip.value);
Core.rotate(processBuffer, processBuffer, rotation.value);
if (shouldFlip || shouldRotate) {
input.copyTo(processBuffer);
if (shouldFlip) {
Core.flip(processBuffer, processBuffer, flip.value);
}
if (shouldRotate) {
Core.rotate(processBuffer, processBuffer, rotation.value);
}
processBuffer.copyTo(outputMat);
processBuffer.release();
} else {
input.copyTo(outputMat);
}
long processTime = System.nanoTime() - processStartNanos;
processBuffer.copyTo(outputMat);
Pair<Mat, Long> output = Pair.of(outputMat, processTime);
processBuffer.release();
return output;
return Pair.of(outputMat, processTime);
}
}

View File

@@ -44,32 +44,35 @@ public class SortContoursPipe implements Pipe<List<RotatedRect>, List<RotatedRec
long processStartNanos = System.nanoTime();
sortedContours.clear();
sortedContours.addAll(input);
switch (sort) {
case Largest:
sortedContours.sort(SortByLargestComparator);
break;
case Smallest:
sortedContours.sort(SortBySmallestComparator);
break;
case Highest:
sortedContours.sort(SortByHighestComparator);
break;
case Lowest:
sortedContours.sort(SortByLowestComparator);
break;
case Leftmost:
sortedContours.sort(SortByLeftmostComparator);
break;
case Rightmost:
sortedContours.sort(SortByRightmostComparator);
break;
case Centermost:
sortedContours.sort(SortByCentermostComparator);
break;
default:
break;
if (input.size() > 0) {
sortedContours.addAll(input);
switch (sort) {
case Largest:
sortedContours.sort(SortByLargestComparator);
break;
case Smallest:
sortedContours.sort(SortBySmallestComparator);
break;
case Highest:
sortedContours.sort(SortByHighestComparator);
break;
case Lowest:
sortedContours.sort(SortByLowestComparator);
break;
case Leftmost:
sortedContours.sort(SortByLeftmostComparator);
break;
case Rightmost:
sortedContours.sort(SortByRightmostComparator);
break;
case Centermost:
sortedContours.sort(SortByCentermostComparator);
break;
default:
break;
}
}
long processTime = System.nanoTime() - processStartNanos;

View File

@@ -27,19 +27,21 @@ public class SpeckleRejectPipe implements Pipe<List<MatOfPoint>, List<MatOfPoint
despeckledContours.clear();
double averageArea = 0.0;
if (input.size() > 0) {
double averageArea = 0.0;
for (MatOfPoint c : input) {
averageArea += Imgproc.contourArea(c);
}
for (MatOfPoint c : input) {
averageArea += Imgproc.contourArea(c);
}
averageArea /= input.size();
averageArea /= input.size();
double minAllowedArea = minPercentOfAvg / 100.0 * averageArea;
double minAllowedArea = minPercentOfAvg / 100.0 * averageArea;
for (MatOfPoint c : input) {
if (Imgproc.contourArea(c) >= minAllowedArea) {
despeckledContours.add(c);
for (MatOfPoint c : input) {
if (Imgproc.contourArea(c) >= minAllowedArea) {
despeckledContours.add(c);
}
}
}