Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add consistent contour reporting #6

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ vision:
maxArea: 10000
minSolidity: 0.0
maxSolidity: 1.0

maxAreaDifference: 50 #Maximum difference in area between largest contours to
arcLengthPercentage: 0.01

# fieldOfView: [62.2, 48.8] # RPI camera FOV
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/teamtators/vision/config/Config.kt
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class VisionConfig {
var maxArea: Int = 100000
var minSolidity: Double = 0.0
var maxSolidity: Double = 1.0

var maxAreaDifference: Int = 50
var arcLengthPercentage: Double = 0.01

var fieldOfView: Size = Size(62.2, 48.8)
Expand Down
119 changes: 72 additions & 47 deletions src/main/java/org/teamtators/vision/vision/FrameProcessor.kt
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,17 @@ class FrameProcessor @Inject constructor(
&& it.solidity <= config.maxSolidity
}

// Find largest contour by area
val trackingContour = filteredContours.maxBy { it.area }
val trackingContour: ContourInfo?;
if (contours.size >= 2) {
trackingContour = if (Math.abs(contours[0].area - contours[1].area) < config.maxAreaDifference) {
contours[0];
} else {
// Find largest contour by area
contours.maxBy { it.area }
}
} else {
trackingContour = contours.maxBy { it.area }
}

val drawStart = System.nanoTime()
// Draw all contours, with the largest one in a larger thickness
Expand Down Expand Up @@ -161,62 +170,78 @@ class FrameProcessor @Inject constructor(
var newAngle: Double? = null
if (trackingContour != null) {
val center = trackingContour.center
val height = inputMat.height()
val width = inputMat.width()
target = center
val height = inputMat.height()
val width = inputMat.width()
target = center

distance = config.distancePoly.calculate(center.y / height.toDouble())
distance = config.distancePoly.calculate(center.y / height.toDouble())

// val widthInches = distance * Math.tan(config.fieldOfView.width.toRadians() / 2) * 2
// val offsetInches = (center.x / width - .5) * widthInches
// offsetAngle = Math.atan2(offsetInches, distance).toDegrees() + config.horizontalAngleOffset
offsetAngle = (center.x / width - 0.5) * config.fieldOfView.width
newAngle = captureData.turretAngle + offsetAngle
}
val calculateEnd = System.nanoTime()

if (_config.profile) {
val scale = 1
val thresholdTime = (erodeStart - thresholdStart) / scale
val erodeTime = (contoursStart - erodeStart) / scale
val contoursTime = (filterContoursStart - contoursStart) / scale
val filterContoursTime = (drawStart - filterContoursStart) / scale
val drawTime = (calculateStart - drawStart) / scale
val calculateTime = (calculateEnd - calculateStart) / scale
val totalTime = (calculateEnd - erodeStart) / scale
logger.trace("threshold: {}, erode: {}, contours: {}, filter: {}, draw: {}, calculate: {}, total: {}",
thresholdTime, erodeTime, contoursTime, filterContoursTime, drawTime, calculateTime, totalTime)
}
offsetAngle = (center.x / width - 0.5) * config.fieldOfView.width
newAngle = captureData.turretAngle + offsetAngle
}
val calculateEnd = System.nanoTime()

if (_config.profile) {
val scale = 1
val thresholdTime = (erodeStart - thresholdStart) / scale
val erodeTime = (contoursStart - erodeStart) / scale
val contoursTime = (filterContoursStart - contoursStart) / scale
val filterContoursTime = (drawStart - filterContoursStart) / scale
val drawTime = (calculateStart - drawStart) / scale
val calculateTime = (calculateEnd - calculateStart) / scale
val totalTime = (calculateEnd - erodeStart) / scale
logger.trace("threshold: {}, erode: {}, contours: {}, filter: {}, draw: {}, calculate: {}, total: {}",
thresholdTime, erodeTime, contoursTime, filterContoursTime, drawTime, calculateTime, totalTime)
}


return ProcessResult(displayMat, target, distance, offsetAngle, newAngle)
}
return ProcessResult(displayMat, target, distance, offsetAngle, newAngle)
}

private fun drawContour(color: Scalar, contour: ContourInfo, thickness: Int) {
if (config.debug)
displayMat.drawContour(contour.contour, color, thickness)
displayMat.drawRotatedRect(contour.minAreaRect, color = color, thickness = thickness)
displayMat.drawCircle(contour.center, 2, color)
private fun drawContour(color: Scalar, contour: ContourInfo, thickness: Int) {
if (config.debug)
displayMat.drawContour(contour.contour, color, thickness)
displayMat.drawRotatedRect(contour.minAreaRect, color = color, thickness = thickness)
displayMat.drawCircle(contour.center, 2, color)

val fontScale = 0.3
val fontScale = 0.3

val str1 = String.format("area: %.0f", contour.rectArea);
val str1Size = Imgproc.getTextSize(str1, fontFace, fontScale, 1, null)
displayMat.drawText(str1, contour.center + Point(-str1Size.width / 2, -str1Size.height / 2),
fontFace = fontFace, fontScale = fontScale, color = color)
val str1 = String.format("area: %.0f", contour.rectArea);
val str1Size = Imgproc.getTextSize(str1, fontFace, fontScale, 1, null)
displayMat.drawText(str1, contour.center + Point(-str1Size.width / 2, -str1Size.height / 2),
fontFace = fontFace, fontScale = fontScale, color = color)

val str2 = String.format("solidity: %.4f", contour.solidity);
val str2Size = Imgproc.getTextSize(str2, fontFace, fontScale, 1, null)
displayMat.drawText(str2, contour.center + Point(-str1Size.width / 2, str2Size.height / 2),
fontFace = fontFace, fontScale = fontScale, color = color)
}
val str2 = String.format("solidity: %.4f", contour.solidity);
val str2Size = Imgproc.getTextSize(str2, fontFace, fontScale, 1, null)
displayMat.drawText(str2, contour.center + Point(-str1Size.width / 2, str2Size.height / 2),
fontFace = fontFace, fontScale = fontScale, color = color)
}

private fun drawCrosshair(mat: Mat) {
val center = mat.size().toPoint() / 2.0
private fun drawCrosshair(mat: Mat) {
val center = mat.size().toPoint() / 2.0
// val width = mat.size().width
val height = mat.size().height
mat.drawCenterRect(center, 25, 25, overlayColor) //to be replaced with corrected targeting values
val height = mat.size().height
mat.drawCenterRect(center, 25, 25, overlayColor) //to be replaced with corrected targeting values
// mat.drawLine(Point(0.0, center.y), Point(width, center.y), overlayColor)
mat.drawLine(Point(center.x, 0.0), Point(center.x, height), overlayColor)
}
}
mat.drawLine(Point(center.x, 0.0), Point(center.x, height), overlayColor)
}

private fun sortLeftToRight(contours: List<ContourInfo>) {
Collections.sort(contours, { info1: ContourInfo, info2: ContourInfo -> info1.center.x.compareTo(info2.center.x) });
}

private fun sortRightToLeft(contours: List<ContourInfo>) {
Collections.sort(contours, { info1: ContourInfo, info2: ContourInfo -> -info1.center.x.compareTo(info2.center.x) });
}

private fun sortTopToBottom(contours: List<ContourInfo>) {
Collections.sort(contours, { info1: ContourInfo, info2: ContourInfo -> -info1.center.y.compareTo(info2.center.x) });
}

private fun sortBottomToTop(contours: List<ContourInfo>) {
Collections.sort(contours, { info1: ContourInfo, info2: ContourInfo -> info1.center.y.compareTo(info2.center.x) });
}
}