Add orx-boofcv
This commit is contained in:
22
orx-boofcv/build.gradle
Normal file
22
orx-boofcv/build.gradle
Normal file
@@ -0,0 +1,22 @@
|
||||
sourceSets {
|
||||
demo {
|
||||
java {
|
||||
srcDirs = ["src/demo/kotlin"]
|
||||
compileClasspath += main.getCompileClasspath()
|
||||
runtimeClasspath += main.getRuntimeClasspath()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def boofcvVersion = "0.34"
|
||||
|
||||
dependencies {
|
||||
|
||||
compile("org.boofcv:boofcv-core:$boofcvVersion")
|
||||
|
||||
demoImplementation("org.openrndr:openrndr-core:$openrndrVersion")
|
||||
demoImplementation("org.openrndr:openrndr-extensions:$openrndrVersion")
|
||||
demoRuntimeOnly("org.openrndr:openrndr-gl3:$openrndrVersion")
|
||||
demoRuntimeOnly("org.openrndr:openrndr-gl3-natives-$openrndrOS:$openrndrVersion")
|
||||
demoImplementation(sourceSets.getByName("main").output)
|
||||
}
|
||||
187
orx-boofcv/src/main/kotlin/Binding.kt
Normal file
187
orx-boofcv/src/main/kotlin/Binding.kt
Normal file
@@ -0,0 +1,187 @@
|
||||
package org.openrndr.boofcv.binding
|
||||
|
||||
import boofcv.struct.image.GrayF32
|
||||
import boofcv.struct.image.GrayF64
|
||||
import boofcv.struct.image.GrayU8
|
||||
import boofcv.struct.image.Planar
|
||||
import org.openrndr.color.ColorRGBa
|
||||
import org.openrndr.draw.ColorBuffer
|
||||
import org.openrndr.draw.ColorFormat
|
||||
import org.openrndr.draw.ColorType
|
||||
import org.openrndr.draw.colorBuffer
|
||||
import kotlin.experimental.and
|
||||
|
||||
fun ColorBuffer.toGrayF32() : GrayF32 {
|
||||
val p = GrayF32(width, height)
|
||||
shadow.download()
|
||||
|
||||
var offset = 0
|
||||
for (y in 0 until height) {
|
||||
for (x in 0 until width) {
|
||||
val c = shadow.read(x, y)
|
||||
p.data[offset] = (c.r * 255).toFloat()
|
||||
offset++
|
||||
}
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
fun ColorBuffer.toGrayF64() : GrayF64 {
|
||||
val p = GrayF64(width, height)
|
||||
shadow.download()
|
||||
|
||||
var offset = 0
|
||||
for (y in 0 until height) {
|
||||
for (x in 0 until width) {
|
||||
val c = shadow.read(x, y)
|
||||
p.data[offset] = (c.r * 255)
|
||||
offset++
|
||||
}
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
fun ColorBuffer.toPlanarF32() : Planar<GrayF32> {
|
||||
val p = Planar<GrayF32>(GrayF32::class.java, width, height, format.componentCount)
|
||||
shadow.download()
|
||||
|
||||
val bands = p.bands
|
||||
|
||||
var offset = 0
|
||||
for (y in 0 until height) {
|
||||
for (x in 0 until width) {
|
||||
val c = shadow.read(x, y)
|
||||
bands[0].data[offset] = (c.r * 255).toFloat()
|
||||
bands[1].data[offset] = (c.g * 255).toFloat()
|
||||
bands[2].data[offset] = (c.b * 255).toFloat()
|
||||
offset++
|
||||
}
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
fun ColorBuffer.toPlanarU8() : Planar<GrayU8> {
|
||||
val p = Planar<GrayU8>(GrayU8::class.java, width, height, format.componentCount)
|
||||
shadow.download()
|
||||
|
||||
val bands = p.bands
|
||||
|
||||
var offset = 0
|
||||
for (y in 0 until height) {
|
||||
for (x in 0 until width) {
|
||||
val c = shadow.read(x, y)
|
||||
bands[0].data[offset] = (c.r * 255).toByte()
|
||||
bands[1].data[offset] = (c.g * 255).toByte()
|
||||
bands[2].data[offset] = (c.b * 255).toByte()
|
||||
offset++
|
||||
}
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
fun ColorBuffer.toGrayU8() : GrayU8 {
|
||||
val p = GrayU8(width, height)
|
||||
shadow.download()
|
||||
|
||||
var offset = 0
|
||||
for (y in 0 until height) {
|
||||
for (x in 0 until width) {
|
||||
val c = shadow.read(x, y)
|
||||
p.data[offset] = (c.r * 255).toInt().coerceIn(0, 255).toByte()
|
||||
offset++
|
||||
}
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
|
||||
fun GrayU8.toColorBuffer() : ColorBuffer {
|
||||
val cb = colorBuffer(width, height, 1.0, ColorFormat.RGB, ColorType.UINT8)
|
||||
val shadow = cb.shadow
|
||||
shadow.buffer.rewind()
|
||||
var offset = 0
|
||||
for (y in 0 until height) {
|
||||
for (x in 0 until width) {
|
||||
val r = (data[offset].toInt() and 0xff).toDouble() / 255.0
|
||||
offset++
|
||||
shadow.write(x, y, ColorRGBa(r, r, r, 1.0))
|
||||
}
|
||||
}
|
||||
shadow.upload()
|
||||
return cb
|
||||
}
|
||||
|
||||
fun GrayF32.toColorBuffer() : ColorBuffer {
|
||||
val cb = colorBuffer(width, height, 1.0, ColorFormat.RGB, ColorType.FLOAT32)
|
||||
val shadow = cb.shadow
|
||||
shadow.buffer.rewind()
|
||||
var offset = 0
|
||||
for (y in 0 until height) {
|
||||
for (x in 0 until width) {
|
||||
val r = data[offset].toDouble() / 255.0
|
||||
offset++
|
||||
shadow.write(x, y, ColorRGBa(r, r, r))
|
||||
}
|
||||
}
|
||||
shadow.upload()
|
||||
return cb
|
||||
}
|
||||
|
||||
fun Planar<GrayU8>.toColorBuffer() : ColorBuffer {
|
||||
val bandCount = bands.size
|
||||
val format = when (bandCount) {
|
||||
1 -> ColorFormat.R
|
||||
2 -> ColorFormat.RG
|
||||
3 -> ColorFormat.RGB
|
||||
4 -> ColorFormat.RGBa
|
||||
else -> throw IllegalArgumentException("only 1 to 4 bands supported")
|
||||
}
|
||||
|
||||
val bands = bands
|
||||
val cb = colorBuffer(width, height, 1.0, format, ColorType.UINT8)
|
||||
val shadow = cb.shadow
|
||||
shadow.buffer.rewind()
|
||||
var offset = 0
|
||||
for (y in 0 until height) {
|
||||
for (x in 0 until width) {
|
||||
val r = (bands[0].data[offset].toInt() and 0xff).toDouble() / 255.0
|
||||
val g = if (bandCount >= 2) (bands[1].data[offset].toInt() and 0xff).toDouble() / 255.0 else 0.0
|
||||
val b = if (bandCount >= 3) (bands[2].data[offset].toInt() and 0xff).toDouble() / 255.0 else 0.0
|
||||
val a = if (bandCount >= 4) (bands[2].data[offset].toInt() and 0xff).toDouble() / 255.0 else 1.0
|
||||
offset++
|
||||
shadow.write(x, y, ColorRGBa(r, g, b, a))
|
||||
}
|
||||
}
|
||||
shadow.upload()
|
||||
return cb
|
||||
}
|
||||
|
||||
@JvmName("grayF32ToColorBuffer")
|
||||
fun Planar<GrayF32>.toColorBuffer() : ColorBuffer {
|
||||
val bandCount = bands.size
|
||||
val format = when (bandCount) {
|
||||
1 -> ColorFormat.R
|
||||
2 -> ColorFormat.RG
|
||||
3 -> ColorFormat.RGB
|
||||
4 -> ColorFormat.RGBa
|
||||
else -> throw IllegalArgumentException("only 1 to 4 bands supported")
|
||||
}
|
||||
|
||||
val bands = bands
|
||||
val cb = colorBuffer(width, height, 1.0, format, ColorType.UINT8)
|
||||
val shadow = cb.shadow
|
||||
shadow.buffer.rewind()
|
||||
var offset = 0
|
||||
for (y in 0 until height) {
|
||||
for (x in 0 until width) {
|
||||
val r = bands[0].data[offset] / 255.0
|
||||
val g = if (bandCount >= 2) bands[1].data[offset] / 255.0 else 0.0
|
||||
val b = if (bandCount >= 3) bands[2].data[offset] / 255.0 else 0.0
|
||||
val a = if (bandCount >= 4) bands[3].data[offset] / 255.0 else 1.0
|
||||
offset++
|
||||
shadow.write(x, y, ColorRGBa(r, g, b, a))
|
||||
}
|
||||
}
|
||||
shadow.upload()
|
||||
return cb
|
||||
}
|
||||
22
orx-boofcv/src/main/kotlin/ContourConversion.kt
Normal file
22
orx-boofcv/src/main/kotlin/ContourConversion.kt
Normal file
@@ -0,0 +1,22 @@
|
||||
package org.openrndr.boofcv.binding
|
||||
|
||||
import boofcv.alg.filter.binary.Contour
|
||||
import org.openrndr.shape.Shape
|
||||
import org.openrndr.shape.ShapeContour
|
||||
|
||||
fun Contour.toShape(): Shape {
|
||||
val external = external.toVector2s()
|
||||
val internal = internal.filter { it.size > 0 }. map { it.toVector2s() }
|
||||
val contours = listOf(ShapeContour.fromPoints(external, false)) +
|
||||
internal.map {
|
||||
ShapeContour.fromPoints(it, false)
|
||||
}
|
||||
|
||||
return Shape(contours)
|
||||
}
|
||||
|
||||
fun List<Contour>.toShapes(): List<Shape> {
|
||||
return this.filter { it.external.isNotEmpty() }.map {
|
||||
it.toShape()
|
||||
}
|
||||
}
|
||||
83
orx-boofcv/src/main/kotlin/Drawing.kt
Normal file
83
orx-boofcv/src/main/kotlin/Drawing.kt
Normal file
@@ -0,0 +1,83 @@
|
||||
package org.openrndr.boofcv.binding
|
||||
|
||||
import georegression.struct.line.LineSegment2D_F32
|
||||
import georegression.struct.line.LineSegment2D_F64
|
||||
import georegression.struct.trig.Circle2D_F32
|
||||
import georegression.struct.trig.Circle2D_F64
|
||||
import org.openrndr.draw.Drawer
|
||||
import org.openrndr.math.Vector2
|
||||
import org.openrndr.shape.Circle
|
||||
|
||||
fun Drawer.lineSegment(segment: LineSegment2D_F32) {
|
||||
lineSegment(
|
||||
segment.a.x.toDouble(),
|
||||
segment.a.y.toDouble(),
|
||||
segment.b.x.toDouble(),
|
||||
segment.b.y.toDouble()
|
||||
)
|
||||
}
|
||||
|
||||
@JvmName("lineSegments2D_F32")
|
||||
fun Drawer.lineSegments(segments: List<LineSegment2D_F32>) {
|
||||
lineSegments(
|
||||
segments.flatMap { segment ->
|
||||
listOf(
|
||||
Vector2(segment.a.x.toDouble(), segment.a.y.toDouble()),
|
||||
Vector2(segment.b.x.toDouble(), segment.b.y.toDouble())
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fun Drawer.lineSegment(segment: LineSegment2D_F64) {
|
||||
lineSegment(
|
||||
segment.a.x,
|
||||
segment.a.y,
|
||||
segment.b.x,
|
||||
segment.b.y
|
||||
)
|
||||
}
|
||||
|
||||
@JvmName("lineSegments2D_F64")
|
||||
fun Drawer.lineSegments(segments: List<LineSegment2D_F64>) {
|
||||
lineSegments(
|
||||
segments.flatMap { segment ->
|
||||
listOf(
|
||||
Vector2(segment.a.x, segment.a.y),
|
||||
Vector2(segment.b.x, segment.b.y)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fun Drawer.circle(circle: Circle2D_F32) {
|
||||
circle(
|
||||
circle.center.x.toDouble(), circle.center.y.toDouble(),
|
||||
circle.radius.toDouble()
|
||||
)
|
||||
}
|
||||
|
||||
fun Drawer.circle(circle: Circle2D_F64) {
|
||||
circle(
|
||||
circle.center.x, circle.center.y,
|
||||
circle.radius
|
||||
)
|
||||
}
|
||||
|
||||
@JvmName("circles2D_F32")
|
||||
fun Drawer.circles(circles: List<Circle2D_F32>) {
|
||||
circles(
|
||||
circles.map {
|
||||
Circle(it.center.x.toDouble(), it.center.y.toDouble(), it.radius.toDouble())
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@JvmName("circles2D_F64")
|
||||
fun Drawer.circles(circles: List<Circle2D_F64>) {
|
||||
circles(
|
||||
circles.map {
|
||||
Circle(it.center.x.toDouble(), it.center.y.toDouble(), it.radius.toDouble())
|
||||
}
|
||||
)
|
||||
}
|
||||
33
orx-boofcv/src/main/kotlin/ImageFlowConversion.kt
Normal file
33
orx-boofcv/src/main/kotlin/ImageFlowConversion.kt
Normal file
@@ -0,0 +1,33 @@
|
||||
package org.openrndr.boofcv.binding
|
||||
|
||||
import boofcv.struct.flow.ImageFlow
|
||||
import org.openrndr.draw.ColorBuffer
|
||||
import org.openrndr.draw.ColorFormat
|
||||
import org.openrndr.draw.ColorType
|
||||
import org.openrndr.draw.colorBuffer
|
||||
import java.nio.Buffer
|
||||
import java.nio.ByteBuffer
|
||||
import java.nio.ByteOrder
|
||||
|
||||
fun ImageFlow.toColorBuffer(): ColorBuffer {
|
||||
|
||||
val cb = colorBuffer(
|
||||
width, height, format = ColorFormat.RG,
|
||||
type = ColorType.FLOAT32
|
||||
)
|
||||
|
||||
val bb = ByteBuffer.allocateDirect(width * height * 8)
|
||||
bb.order(ByteOrder.nativeOrder())
|
||||
for (y in 0 until height) {
|
||||
for (x in 0 until width) {
|
||||
val f = get(x, y)
|
||||
bb.putFloat(f.x)
|
||||
bb.putFloat(f.y)
|
||||
}
|
||||
}
|
||||
|
||||
(bb as Buffer).rewind()
|
||||
cb.write(bb)
|
||||
cb.flipV = true
|
||||
return cb
|
||||
}
|
||||
11
orx-boofcv/src/main/kotlin/PointConversion.kt
Normal file
11
orx-boofcv/src/main/kotlin/PointConversion.kt
Normal file
@@ -0,0 +1,11 @@
|
||||
package org.openrndr.boofcv.binding
|
||||
|
||||
import georegression.struct.point.Point2D_F32
|
||||
import georegression.struct.point.Point2D_F64
|
||||
import georegression.struct.point.Point2D_I32
|
||||
import org.openrndr.math.Vector2
|
||||
|
||||
fun Point2D_I32.toVector2() = Vector2(x.toDouble(), y.toDouble())
|
||||
fun Point2D_F32.toVector2() = Vector2(x.toDouble(), y.toDouble())
|
||||
fun Point2D_F64.toVector2() = Vector2(x.toDouble(), y.toDouble())
|
||||
fun List<Point2D_I32>.toVector2s() = this.map { it.toVector2() }
|
||||
@@ -1,6 +1,7 @@
|
||||
rootProject.name = 'orx'
|
||||
|
||||
include 'orx-camera',
|
||||
include 'orx-boofcv',
|
||||
'orx-camera',
|
||||
'orx-compositor',
|
||||
'orx-easing',
|
||||
'orx-file-watcher',
|
||||
|
||||
Reference in New Issue
Block a user