Skip to content

Instantly share code, notes, and snippets.

@rladstaetter
Last active December 21, 2015 15:49
Show Gist options
  • Select an option

  • Save rladstaetter/6328844 to your computer and use it in GitHub Desktop.

Select an option

Save rladstaetter/6328844 to your computer and use it in GitHub Desktop.
A JavaFX application using openCV and Scala in order to explore HSV color space values of an image stream taken from your webcam
package net.ladstatt.apps
import javafx.scene._
import org.opencv.core._
import org.opencv.imgproc.Imgproc
import javafx.application.{Platform, Application}
import javafx.scene.control._
import javafx.scene.image.ImageView
import javafx.scene.layout.BorderPane
import javafx.stage.Stage
import scala.Some
import java.util.ResourceBundle
import javafx.fxml.{FXML, Initializable}
import java.net.URL
import javafx.beans.property.SimpleObjectProperty
import net.ladstatt.jfx._
import org.controlsfx.control.{HsvSlider, RangeSlider}
object HsvAdjuster {
def main(args: Array[String]): Unit = {
Application.launch(classOf[HsvAdjuster], args: _*)
}
}
class HsvAdjuster extends Application with JfxUtils with Initializable with OpenCVUtils {
// width and height of input image
val (webCamWidth, webCamHeight) = (1280, 720)
val lowerBoundProperty = new SimpleObjectProperty[Scalar](new Scalar(0, 0, 0))
def setLowerBound(lb: Scalar) = lowerBoundProperty.set(lb)
def getLowerBound() = lowerBoundProperty.get
val upperBoundProperty = new SimpleObjectProperty[Scalar](new Scalar(255, 255, 255))
def setUpperBound(lb: Scalar) = upperBoundProperty.set(lb)
def getUpperBound() = upperBoundProperty.get
override def init(): Unit = loadNativeLibs // important to have this statement on the "right" thread
def colorSpace(conversionMethod: Int = Imgproc.COLOR_BGR2GRAY)(input: Mat): Mat = {
val colorTransformed = new Mat
Imgproc.cvtColor(input, colorTransformed, conversionMethod)
colorTransformed
}
def restrain(input: Mat): Mat = {
val dest = new Mat
val lb = getLowerBound()
val ub = getUpperBound()
Core.inRange(input, lb, ub, dest)
dest
}
val colorRanges: Map[String, (Double, Double)] = Map("ALLHue" ->((0.0, 179.0)),
"ALLSaturation" ->((0.0, 255.0)),
"ALLValue" ->((0.0, 255.0)),
"orange" ->((165.0, 179.0)),
"yellow" ->((16.0, 28.0)),
"green" ->((92.0, 103.0)),
"blue" ->((103.0, 115.0)),
"white" ->((130.0, 160.0)),
"red" ->((160.0, 179.0)))
@FXML var labelLbHue: Label = _
@FXML var labelLbSaturation: Label = _
@FXML var labelLbValue: Label = _
@FXML var labelUbHue: Label = _
@FXML var labelUbSaturation: Label = _
@FXML var labelUbValue: Label = _
@FXML var hueSlider: HsvSlider = _
@FXML var saturationSlider: HsvSlider = _
@FXML var valueSlider: HsvSlider = _
@FXML var viewPort: ImageView = _
@FXML var orangePresetButton: Button = _
@FXML var yellowPresetButton: Button = _
@FXML var greenPresetButton: Button = _
@FXML var bluePresetButton: Button = _
@FXML var whitePresetButton: Button = _
@FXML var redPresetButton: Button = _
def initPresetButton(button: Button, range: (Double, Double)) {
button.setOnAction(mkEventHandler(e => {
hueSlider.setLowValue(range._1)
hueSlider.setHighValue(range._2)
}))
}
def toGray = colorSpace(Imgproc.COLOR_BGR2GRAY) _
def toHsv = colorSpace(Imgproc.COLOR_BGR2HSV) _
override def start(stage: Stage): Unit = {
stage.setTitle("HsvAdjuster")
val imageService = new WebcamService
imageService.setOnSucceeded(
mkEventHandler(
event => {
val grabbedMat = restrain(colorSpace(Imgproc.COLOR_BGR2HSV)(event.getSource.getValue.asInstanceOf[Mat]))
Platform.runLater(
new Runnable() {
def run = {
viewPort.imageProperty.set(toImage(grabbedMat))
imageService.restart
}
}
)
}
))
imageService.start
val scene = new Scene(mk[BorderPane](mkFxmlLoader("/hsvadjuster.fxml", this)))
stage.setScene(scene)
stage.show
}
def initialize(url: URL, resourceBundle: ResourceBundle): Unit = {
def initRangeSlider(pos: Int, slider: RangeSlider, lowerLabel: Label, upperLabel: Label): Unit = {
slider.lowValueProperty().addListener(mkChangeListener[Number](
(obVal, oldVal, newVal) => {
val mutableBounds = getLowerBound.`val`
mutableBounds(pos) = newVal.doubleValue()
setLowerBound(new Scalar(mutableBounds))
lowerLabel.setText("%.2f".format(newVal.doubleValue))
}
))
slider.highValueProperty().addListener(mkChangeListener[Number](
(obVal, oldVal, newVal) => {
val mutableBounds = getUpperBound.`val`
mutableBounds(pos) = newVal.doubleValue()
setUpperBound(new Scalar(mutableBounds))
upperLabel.setText("%.2f".format(newVal.doubleValue))
}
))
}
def setRangeSlider(slider: RangeSlider)(range: (Double, Double)) {
slider.setLowValue(range._1)
slider.setHighValue(range._2)
}
def setHueSlider = setRangeSlider(hueSlider) _
def setSaturationSlider = setRangeSlider(saturationSlider) _
def setValueSlider = setRangeSlider(valueSlider) _
initRangeSlider(0, hueSlider, labelLbHue, labelUbHue)
initRangeSlider(1, saturationSlider, labelLbSaturation, labelUbSaturation)
initRangeSlider(2, valueSlider, labelLbValue, labelUbValue)
setHueSlider(colorRanges("ALLHue"))
setSaturationSlider(colorRanges("ALLSaturation"))
setValueSlider(colorRanges("ALLValue"))
initPresetButton(orangePresetButton, colorRanges("orange"))
initPresetButton(yellowPresetButton, colorRanges("yellow"))
initPresetButton(greenPresetButton, colorRanges("green"))
initPresetButton(bluePresetButton, colorRanges("blue"))
initPresetButton(whitePresetButton, colorRanges("white"))
initPresetButton(redPresetButton, colorRanges("red"))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment