Last active
December 21, 2015 15:49
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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