Skip to content

Commit

Permalink
Implement CrosshairNode CPython generator
Browse files Browse the repository at this point in the history
  • Loading branch information
serivesmejia committed Nov 15, 2024
1 parent 0314027 commit 5a5b13b
Show file tree
Hide file tree
Showing 12 changed files with 218 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,16 @@

package io.github.deltacv.papervision.plugin

import imgui.ImGui
import imgui.app.Application
import io.github.deltacv.papervision.engine.client.response.JsonElementResponse
import io.github.deltacv.papervision.engine.client.response.OkResponse
import io.github.deltacv.papervision.engine.message.OnResponseCallback
import io.github.deltacv.papervision.engine.message.PaperVisionEngineMessageResponse
import io.github.deltacv.papervision.gui.FontAwesomeIcons
import io.github.deltacv.papervision.gui.Option
import io.github.deltacv.papervision.gui.util.Popup
import io.github.deltacv.papervision.gui.util.TooltipPopup
import io.github.deltacv.papervision.platform.lwjgl.PaperVisionApp
import io.github.deltacv.papervision.plugin.gui.imgui.CloseConfirmWindow
import io.github.deltacv.papervision.plugin.gui.imgui.InputSourceWindow
Expand Down Expand Up @@ -93,8 +96,6 @@ class EOCVSimIpcPaperVisionMain : Callable<Int?> {
app.paperVision.engineClient
)

inputSourceWindow.enable()

app.paperVision.previzManager.onPrevizStart {
inputSourceWindow.enable()
}
Expand All @@ -103,14 +104,20 @@ class EOCVSimIpcPaperVisionMain : Callable<Int?> {
inputSourceWindow.delete()
}

app.paperVision.nodeEditor.options[FontAwesomeIcons.Save] = Option("Save project") {
SaveCurrentProjectMessage(
serializeToTree(
app.paperVision.nodes.inmutable, app.paperVision.links.inmutable
)
).onResponseWith<OkResponse> {
logger.info("Project saved")
}
app.paperVision.nodeEditor.options[FontAwesomeIcons.Save] = Option("mis_saveproject") {
app.paperVision.engineClient.sendMessage(
SaveCurrentProjectMessage(
serializeToTree(
app.paperVision.nodes.inmutable, app.paperVision.links.inmutable
)
).onResponseWith<OkResponse> {
app.paperVision.onUpdate.doOnce {
TooltipPopup("mis_projectsaved", ImGui.getMousePos(), 4.0).open()
}

logger.info("Project saved")
}
)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ class InputSourceWindow(
ImGuiWindowFlags.AlwaysAutoResize,
)

private var initialPosition: ImVec2? = null

init {
client.sendMessage(GetInputSourcesMessage().onResponseWith<InputSourcesListResponse> {
inputSources = it.sources
Expand All @@ -67,16 +69,18 @@ class InputSourceWindow(
})

onDraw.doOnce {
onDraw.doOnce {
position = ImVec2(
ImGui.getMainViewport().size.x - size.x - position.y, position.y
)
}
initialPosition = ImVec2(position.x, position.y)
}
}


override fun drawContents() {
if(initialPosition != null) {
position = ImVec2(
ImGui.getMainViewport().size.x - size.x - initialPosition!!.y, initialPosition!!.y
)
}

if(ImGui.beginListBox("###$id")) {
for (inputSource in inputSources) {
ImGui.pushFont(fontAwesome.imfont)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ sealed class GenValue {
data class Line(val color: Scalar, val thickness: Int) : LineParameters()
data class RuntimeLine(val colorScalarValue: Value, val thicknessValue: Value) : LineParameters()

fun ensureRuntimeLine(current: CodeGen.Current): RuntimeLine {
fun ensureRuntimeLineJava(current: CodeGen.Current): RuntimeLine {
return current {
val lineParams = this@LineParameters

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ open class LanguageContext(val language: Language) {

fun Type.newArray(size: Value) = language.newArrayOf(this, size)

fun Type.newArray() = language.newArrayOf(this)

fun value(type: Type, value: String) = language.value(type, value)

fun String.callValue(returnType: Type, vararg parameters: Value) =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,6 @@ object CPythonLanguage : LanguageBase(
mainScope.get()
}


class TupleVariable(value: Value, vararg names: String) : Variable(names.csv(), value) {
val names = names.toSet()

Expand All @@ -213,6 +212,18 @@ object CPythonLanguage : LanguageBase(
}
}

override fun int(value: Value) = callValue("int", language.IntType, value)
override fun int(value: Int) = int(value.toString().v)

override fun long(value: Value) = callValue("int", language.IntType, value)
override fun long(value: Long) = long(value.toString().v)

override fun float(value: Value) = callValue("float", language.IntType, value)
override fun float(value: Float) = float(value.toString().v)

override fun double(value: Value) = callValue("float", language.IntType, value)
override fun double(value: Double) = double(value.toString().v)

fun tupleVariables(value: Value, vararg names: String) = TupleVariable(value, *names)

fun tuple(vararg value: Value) = ConValue(NoType, "(${value.csv()})")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import imgui.flag.ImGuiCol
import imgui.flag.ImGuiMouseButton
import imgui.flag.ImGuiWindowFlags
import imgui.type.ImInt
import io.github.deltacv.mai18n.tr
import io.github.deltacv.papervision.PaperVision
import io.github.deltacv.papervision.action.editor.CreateLinkAction
import io.github.deltacv.papervision.action.editor.CreateNodeAction
Expand Down Expand Up @@ -181,7 +182,7 @@ class NodeEditor(val paperVision: PaperVision, private val keyManager: KeyManage

playButton.enable()

options[FontAwesomeIcons.EarthAmericas] = Option("Change Language") {
options[FontAwesomeIcons.EarthAmericas] = Option("mis_changelanguage") {
paperVision.showWelcome(askLanguage = true)
}

Expand Down Expand Up @@ -816,7 +817,7 @@ class NodeEditor(val paperVision: PaperVision, private val keyManager: KeyManage

if(ImGui.isItemHovered()) {
ImGui.pushFont(tooltipFont.imfont)
ImGui.setTooltip(option.description)
ImGui.setTooltip(tr(option.description))
ImGui.popFont()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class TooltipPopup(
val text: String,
override val position: ImVec2,
val timeoutSeconds: Double,
label: String
label: String = "mack"
) : Popup(label) {

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,17 @@ import io.github.deltacv.papervision.attribute.vision.structs.PointsAttribute
import io.github.deltacv.papervision.codegen.CodeGen
import io.github.deltacv.papervision.codegen.CodeGenSession
import io.github.deltacv.papervision.codegen.GenValue
import io.github.deltacv.papervision.codegen.build.type.CPythonOpenCvTypes
import io.github.deltacv.papervision.codegen.build.type.JavaTypes
import io.github.deltacv.papervision.codegen.build.type.JvmOpenCvTypes
import io.github.deltacv.papervision.codegen.build.type.JvmOpenCvTypes.Imgproc
import io.github.deltacv.papervision.codegen.dsl.generatorsBuilder
import io.github.deltacv.papervision.codegen.language.interpreted.CPythonLanguage
import io.github.deltacv.papervision.codegen.language.jvm.JavaLanguage
import io.github.deltacv.papervision.node.Category
import io.github.deltacv.papervision.node.DrawNode
import io.github.deltacv.papervision.node.PaperNode
import jdk.nashorn.internal.codegen.types.BooleanType

@PaperNode(
name = "nod_crosshair",
Expand All @@ -62,26 +65,30 @@ class CrosshairNode : DrawNode<CrosshairNode.Session>() {
val outputCrosshairImage = MatAttribute(OUTPUT, "$[att_crosshairimage]")

override fun onEnable() {
+ drawCrosshairOn.rebuildOnChange()
+ input.rebuildOnChange()
+ crosshairScale
+drawCrosshairOn.rebuildOnChange()
+input.rebuildOnChange()
+crosshairScale

+ crosshairPosition
+ crosshairLineParams
crosshairScale.value.set(5)

+crosshairPosition
+crosshairLineParams

crosshairPosition.onChange {
when(crosshairPosition.get()) {
when (crosshairPosition.get()) {
CrosshairPosition.Center -> {
}

CrosshairPosition.Offset -> {
}

CrosshairPosition.Custom -> {
}
}
}

+ outputCrosshairImage.enablePrevizButton().rebuildOnChange()
+ outputCrosshair.rebuildOnChange()
+outputCrosshairImage.enablePrevizButton().rebuildOnChange()
+outputCrosshair.rebuildOnChange()
}

override val generators = generatorsBuilder {
Expand All @@ -99,7 +106,8 @@ class CrosshairNode : DrawNode<CrosshairNode.Session>() {

val crosshairPosValue = crosshairPosition.value(current).value

val crosshairLineParams = (crosshairLineParams.value(current) as GenValue.LineParameters).ensureRuntimeLine(current)
val crosshairLineParams =
(crosshairLineParams.value(current) as GenValue.LineParameters).ensureRuntimeLineJava(current)

val crosshairSizeValue = crosshairScale.value(current).value

Expand Down Expand Up @@ -146,7 +154,8 @@ class CrosshairNode : DrawNode<CrosshairNode.Session>() {
separate()

// Adjust crosshairSize based on the scale factor
val adjustedCrosshairSize = uniqueVariable("adjustedCrosshairSize", crosshairSize * scaleFactor / 100.v)
val adjustedCrosshairSize =
uniqueVariable("adjustedCrosshairSize", crosshairSize * scaleFactor / 100.v)
local(adjustedCrosshairSize)

separate()
Expand Down Expand Up @@ -218,6 +227,149 @@ class CrosshairNode : DrawNode<CrosshairNode.Session>() {

session
}

generatorFor(CPythonLanguage) {
val session = Session()

val inputPoints = input.value(current)

if (inputPoints !is GenValue.GList.RuntimeListOf<*>) {
raise("") // TODO: Handle non-runtime lists
}

val lineParams = crosshairLineParams.value(current)
if (lineParams !is GenValue.LineParameters.Line) {
raise("Line parameters must not be runtime")
}

val drawOn = drawCrosshairOn.value(current)
val drawOnValue = drawOn.value

val crosshairPosValue = crosshairPosition.value(current).value
val crosshairLineParams = (crosshairLineParams.value(current) as GenValue.LineParameters.Line)
val crosshairSizeValue = crosshairScale.value(current).value

current {
val crosshair = uniqueVariable("crosshair", CPythonLanguage.NoType.newArray())
val crosshairImage = uniqueVariable("crosshair_image", drawOnValue.callValue("copy", CPythonLanguage.NoType))

current.scope {
local(crosshair)
local(crosshairImage)

separate()

val rowsCols = CPythonLanguage.tupleVariables(
crosshairImage.propertyValue("shape", CPythonLanguage.NoType),
"height", "width", "channels"
)

local(rowsCols)

val rows = rowsCols.get("height")
val cols = rowsCols.get("width")

separate()

val (crosshairPointX, crosshairPointY) = if (crosshairPosValue == CrosshairPosition.Center) {
// draw crosshair at center
Pair(cols / 2.v, rows / 2.v)
} else if (crosshairPosValue == CrosshairPosition.Offset) {
TODO()
} else {
TODO()
}

val pointX = uniqueVariable("crosshair_point_x", crosshairPointX)
val pointY = uniqueVariable("crosshair_point_y", crosshairPointY)

local(pointX)
local(pointY)

// Define a scale factor based on the image dimensions
val scaleFactor = uniqueVariable("scale_factor", (rows + cols) / 2.v)
local(scaleFactor)

separate()

// Adjust crosshairSize based on the scale factor
val adjustedCrosshairSize =
uniqueVariable("adjusted_crosshair_size", crosshairSizeValue.v * scaleFactor / 100.v)
local(adjustedCrosshairSize)

separate()

val crosshairCol = crosshairLineParams.color.elements.map { it.value.v }.toTypedArray()
val crosshairThickness = crosshairLineParams.thickness.value.v

CPythonOpenCvTypes.cv2(
"line",
crosshairImage,
CPythonLanguage.tuple(
int(pointX - adjustedCrosshairSize),
int(pointY)
),
CPythonLanguage.tuple(
int(pointX + adjustedCrosshairSize),
int(pointY)
),
CPythonLanguage.tuple(*crosshairCol),
crosshairThickness
)

CPythonOpenCvTypes.cv2(
"line",
crosshairImage,
CPythonLanguage.tuple(
int(pointX),
int(pointY - adjustedCrosshairSize)
),
CPythonLanguage.tuple(
int(pointX),
int(pointY + adjustedCrosshairSize)
),
CPythonLanguage.tuple(*crosshairCol),
crosshairThickness
)

separate()

foreach(variable(CPythonLanguage.NoType, "contour"), inputPoints.value) {
// Get the bounding rectangle of the current contour
val boundingRect = CPythonLanguage.tupleVariables(
CPythonOpenCvTypes.cv2.callValue("bounding_rect", CPythonLanguage.NoType, it),
"x", "y", "w", "h"
)
local(boundingRect)

separate()
// Extract x, y, w, h values
val x = boundingRect.get("x")
val y = boundingRect.get("y")
val w = boundingRect.get("w")
val h = boundingRect.get("h")

// Check if the crosshair rectangle is inside the bounding rectangle
// perform aabb check
ifCondition(
(pointX greaterOrEqualThan x)
and (pointX lessOrEqualThan (x + w))
and (pointY greaterOrEqualThan y)
and (pointY lessOrEqualThan (y + h))
) {
// Add the contour to the crosshair if the bounding rectangle contains the crosshair
crosshair("append", it)
}
}

session.outputCrosshair =
GenValue.GList.RuntimeListOf(crosshair, GenValue.GPoints.RuntimePoints::class)
session.outputCrosshairImage = GenValue.Mat(crosshairImage, drawOn.color, drawOn.isBinary)
}
}

session
}
}

override fun getOutputValueOf(current: CodeGen.Current, attrib: Attribute): GenValue {
Expand Down
Loading

0 comments on commit 5a5b13b

Please sign in to comment.