I’m using the org.bytedeco:opencv-platform
maven port to use opencv in kotlin.
Main.kt:
fun main() = runBlocking {
// Load native libraries, mainly opencv
Loader.load(opencv_java::class.java)
println("Attempting a connection to the robot")
val client = RobotClient()
// Camera properties
val ballCamProps = MatOfInt(
Videoio.CAP_PROP_FRAME_WIDTH, 480,
Videoio.CAP_PROP_FRAME_HEIGHT, 640
)
println("Creating trackers")
val ballCam = BallTracker(VideoCapture(-1, Videoio.CAP_ANY, ballCamProps), client)
println("Running trackers")
ballCam.runAsync()
println("Starting video stream")
while(true) {
if(!ballCam.currentFrame.empty()){
ballCam.imstream(ballCam.currentFrame);
} else {
throw Exception("Current frame is empty")
}
}
BallTracker.kt:
class BallTracker(cap: VideoCapture, net: RobotClient): AsyncPipeline {
var currentFrame = Mat()
override val client = net
private val mutex = Mutex()
private val _capture = cap
private fun process(img: Mat, range: Pair<Scalar, Scalar>): Mat {
...
}
private fun track(threshed: Mat): Map<String, Double> {
...
}
override fun runAsync() = GlobalScope.async {
val blue = Pair<Scalar, Scalar>(
Scalar(92.0, 139.0, 76.0),
Scalar(115.0, 210.0, 175.0)
)
val red = Pair<Scalar, Scalar>(
Scalar(165.0, 92.0, 52.0),
Scalar(175.0, 218.0, 213.0)
)
while(_capture.isOpened) {
mutex.withLock {
if(_capture.read(currentFrame)) {
val processed = process(currentFrame, blue)
val trackerData = track(processed)
} else {
throw Exception("Unable to read frame from camera")
}
}
}
throw Exception("Unable to open camera")
}
suspend fun imstream(img: Mat) {
mutex.withLock {
HighGui.imshow("Ball cam", img)
}
}
}
I’m not familer with opencv in java and in c++ I’d normally use the <<
operator to read from a camera