Skip to content

Instantly share code, notes, and snippets.

@rladstaetter
Last active December 23, 2015 15:59
Show Gist options
  • Save rladstaetter/6659193 to your computer and use it in GitHub Desktop.
Save rladstaetter/6659193 to your computer and use it in GitHub Desktop.
An application to extract certain regions of an image stream which share the same color.
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 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 ColorExtractor {
def main(args: Array[String]): Unit = {
Application.launch(classOf[ColorExtractor], args: _*)
}
}
class ColorExtractor extends Application with JfxUtils with Initializable with OpenCVUtils {
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
}
def alphaBlend(src: Mat, alpha: Mat): Mat = {
val channels = new java.util.ArrayList[Mat]()
Core.split(src, channels)
channels.add(alpha)
val merged = new Mat
Core.merge(channels, merged)
merged
}
@FXML var textFieldLbHue: TextField = _
@FXML var textFieldLbSaturation: TextField = _
@FXML var textFieldLbValue: TextField = _
@FXML var textFieldUbHue: TextField = _
@FXML var textFieldUbSaturation: TextField = _
@FXML var textFieldUbValue: TextField = _
@FXML var hueSlider: HsvSlider = _
@FXML var saturationSlider: HsvSlider = _
@FXML var valueSlider: HsvSlider = _
@FXML var viewPort: ImageView = _
override def start(stage: Stage): Unit = {
stage.setTitle("Color Extractor")
val imageService = new WebcamService
imageService.setOnSucceeded(
mkEventHandler(
event => {
val imageAsMat = event.getSource.getValue.asInstanceOf[Mat]
val alphaChannel = restrain(colorSpace(Imgproc.COLOR_BGR2HSV)(imageAsMat))
viewPort.imageProperty.set(toImage(alphaBlend(imageAsMat, alphaChannel)))
imageService.restart
}
))
imageService.start
val scene = new Scene(mk[BorderPane](mkFxmlLoader("/colorextractor.fxml", this)))
stage.setScene(scene)
stage.show
}
def initialize(url: URL, resourceBundle: ResourceBundle): Unit = {
def initRangeSlider(pos: Int, slider: RangeSlider, lowerTextField: TextField, upperTextField: TextField): Unit = {
slider.lowValueProperty().addListener(mkChangeListener[Number](
(obVal, oldVal, newVal) => {
val mutableBounds = getLowerBound.`val`
mutableBounds(pos) = newVal.doubleValue()
setLowerBound(new Scalar(mutableBounds))
lowerTextField.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))
upperTextField.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, textFieldLbHue, textFieldUbHue)
initRangeSlider(1, saturationSlider, textFieldLbSaturation, textFieldUbSaturation)
initRangeSlider(2, valueSlider, textFieldLbValue, textFieldUbValue)
setHueSlider((0.0, 179.0))
setSaturationSlider((0.0, 255.0))
setValueSlider((0.0, 255.0))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment