implement basic UI
This commit is contained in:
parent
f66413710b
commit
e221b6d06c
10 changed files with 185 additions and 34 deletions
6
.idea/google-java-format.xml
Normal file
6
.idea/google-java-format.xml
Normal file
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GoogleJavaFormatSettings">
|
||||
<option name="enabled" value="false" />
|
||||
</component>
|
||||
</project>
|
|
@ -5,6 +5,7 @@
|
|||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="gradleJvm" value="corretto-21" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<component name="FrameworkDetectionExcludesConfiguration">
|
||||
<file type="web" url="file://$PROJECT_DIR$" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="21" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="corretto-21" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
|
@ -25,7 +25,7 @@ tasks.withType(JavaCompile) {
|
|||
|
||||
application {
|
||||
mainModule = 'com.nuculabs.dev.imagetagger.ui'
|
||||
mainClass = 'com.nuculabs.dev.imagetagger.ui.MainApplication'
|
||||
mainClass = 'com.nuculabs.dev.imagetagger.ui.MainPage'
|
||||
}
|
||||
kotlin {
|
||||
jvmToolchain( 17 )
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
package com.nuculabs.dev.imagetagger.ui
|
||||
|
||||
import com.nuculabs.dev.imagetagger.tag_prediction.ImageTagsPrediction
|
||||
import javafx.fxml.FXML
|
||||
import javafx.scene.control.Label
|
||||
import java.io.File
|
||||
|
||||
class HelloController {
|
||||
@FXML
|
||||
private lateinit var welcomeText: Label
|
||||
|
||||
@FXML
|
||||
private fun onHelloButtonClick() {
|
||||
val imageTagsPrediction = ImageTagsPrediction.getInstance()
|
||||
val testTags = imageTagsPrediction.predictTags(File("/home/denis/Pictures/not_in_train/0a1a1e8bafbcdb00d34d87f35f0f4b9f.jpg").inputStream())
|
||||
|
||||
welcomeText.text = testTags.joinToString { it }
|
||||
}
|
||||
}
|
|
@ -6,11 +6,11 @@ import javafx.fxml.FXMLLoader
|
|||
import javafx.scene.Scene
|
||||
import javafx.stage.Stage
|
||||
|
||||
class MainApplication : Application() {
|
||||
class MainPage : Application() {
|
||||
override fun start(stage: Stage) {
|
||||
ImageTagsPrediction.getInstance()
|
||||
|
||||
val fxmlLoader = FXMLLoader(MainApplication::class.java.getResource("main-window-view.fxml"))
|
||||
val fxmlLoader = FXMLLoader(MainPage::class.java.getResource("main-window-view.fxml"))
|
||||
val scene = Scene(fxmlLoader.load(), 640.0, 760.0)
|
||||
stage.title = "Image Tagger"
|
||||
stage.scene = scene
|
||||
|
@ -21,5 +21,5 @@ class MainApplication : Application() {
|
|||
}
|
||||
|
||||
fun main() {
|
||||
Application.launch(MainApplication::class.java)
|
||||
Application.launch(MainPage::class.java)
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
package com.nuculabs.dev.imagetagger.ui
|
||||
|
||||
import com.nuculabs.dev.imagetagger.tag_prediction.ImageTagsPrediction
|
||||
import com.nuculabs.dev.imagetagger.ui.controls.ImageTagsEntry
|
||||
import javafx.application.Platform
|
||||
import javafx.fxml.FXML
|
||||
import javafx.scene.control.Label
|
||||
import javafx.scene.control.Separator
|
||||
import javafx.scene.layout.VBox
|
||||
import javafx.stage.FileChooser
|
||||
import java.io.File
|
||||
import java.util.logging.Logger
|
||||
import javax.imageio.ImageIO
|
||||
|
||||
|
||||
class MainPageController {
|
||||
private val logger: Logger = Logger.getLogger("InfoLogging")
|
||||
|
||||
@FXML
|
||||
private lateinit var verticalBox: VBox
|
||||
|
||||
@FXML
|
||||
private lateinit var statusLabel: Label
|
||||
|
||||
/**
|
||||
* Prompts the user to select files then predicts tags for the selected image files.
|
||||
*/
|
||||
@FXML
|
||||
private fun onTagImagesButtonClick() {
|
||||
val imageTagsPrediction = ImageTagsPrediction.getInstance()
|
||||
|
||||
val fileChooser = FileChooser()
|
||||
fileChooser.title = "Choose images"
|
||||
val filePaths = fileChooser.showOpenMultipleDialog(null) ?: return
|
||||
|
||||
statusLabel.isVisible = true
|
||||
|
||||
// Create a new thread to predict the images.
|
||||
val thread = Thread {
|
||||
try {
|
||||
for (filePath in filePaths) {
|
||||
// Get predictions for the image.
|
||||
val imageFile = ImageIO.read(File(filePath.absolutePath))
|
||||
val tags: List<String> = imageTagsPrediction.predictTags(imageFile)
|
||||
Platform.runLater {
|
||||
// Add image and prediction to the view.
|
||||
verticalBox.children.add(
|
||||
Label("${filePath.name} - $tags")
|
||||
)
|
||||
verticalBox.children.add(Separator())
|
||||
}
|
||||
}
|
||||
Platform.runLater {
|
||||
statusLabel.setVisible(false)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
logger.warning("Error while predicting images $e")
|
||||
}
|
||||
}
|
||||
thread.start()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package com.nuculabs.dev.imagetagger.ui.controls
|
||||
import javafx.fxml.FXML
|
||||
import javafx.fxml.FXMLLoader
|
||||
import javafx.scene.control.TextArea
|
||||
import javafx.scene.image.Image
|
||||
import javafx.scene.image.ImageView
|
||||
import javafx.scene.layout.HBox
|
||||
import java.io.IOException
|
||||
|
||||
/**
|
||||
* This class is used to create a custom control for the image prediction entry.
|
||||
*/
|
||||
class ImageTagsEntry(imagePath: String, predictions: List<String>) : HBox() {
|
||||
/**
|
||||
* The image view for the image prediction entry.
|
||||
*/
|
||||
@FXML
|
||||
private lateinit var imageView: ImageView
|
||||
|
||||
/**
|
||||
* The text area for the image prediction entry.
|
||||
*/
|
||||
@FXML
|
||||
private lateinit var predictedImageTags: TextArea
|
||||
|
||||
/**
|
||||
* Constructor for the image prediction entry.
|
||||
*
|
||||
* @param imagePath The image path.
|
||||
* @param predictions The prediction list.
|
||||
*/
|
||||
init {
|
||||
val fxmlLoader = FXMLLoader(ImageTagsEntry::class.java.getResource("/controls/image-tags-entry.fxml"))
|
||||
fxmlLoader.setRoot(this)
|
||||
fxmlLoader.setController(this)
|
||||
|
||||
try {
|
||||
fxmlLoader.load<Any>()
|
||||
} catch (exception: IOException) {
|
||||
throw RuntimeException(exception)
|
||||
}
|
||||
|
||||
setImage(imagePath)
|
||||
setText(predictions)
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the image view.
|
||||
*
|
||||
* @param predictions The prediction list.
|
||||
*/
|
||||
fun setText(predictions: List<String>) {
|
||||
predictedImageTags.text = predictions.joinToString { it }
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for setting the image.
|
||||
*/
|
||||
fun setImage(imagePath: String?) {
|
||||
imageView.image = Image(imagePath)
|
||||
imageView.resize(244.0, 244.0)
|
||||
imageView.fitHeight = 244.0
|
||||
imageView.fitWidth = 244.0
|
||||
imageView.isSmooth = true
|
||||
imageView.isCache = true
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.scene.control.*?>
|
||||
<?import javafx.scene.layout.*?>
|
||||
<?import javafx.geometry.Insets?>
|
||||
|
||||
<?import javafx.scene.image.ImageView?>
|
||||
<fx:root type="javafx.scene.layout.HBox" xmlns:fx="http://javafx.com/fxml">
|
||||
<padding>
|
||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0"/>
|
||||
</padding>
|
||||
<HBox>
|
||||
<ImageView fx:id="imageView" />
|
||||
<VBox>
|
||||
<padding>
|
||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0"/>
|
||||
</padding>
|
||||
<Label text="Predicted tags:"/>
|
||||
<TextArea fx:id="predictedImageTags" editable="false" wrapText="true" prefColumnCount="23"/>
|
||||
</VBox>
|
||||
</HBox>
|
||||
</fx:root>
|
|
@ -1,16 +1,28 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<?import javafx.geometry.*?>
|
||||
<?import javafx.scene.control.*?>
|
||||
<?import javafx.scene.layout.*?>
|
||||
|
||||
<?import javafx.scene.control.Button?>
|
||||
<VBox alignment="CENTER" spacing="20.0" xmlns:fx="http://javafx.com/fxml"
|
||||
fx:controller="com.nuculabs.dev.imagetagger.ui.HelloController">
|
||||
<BorderPane prefHeight="537.0" prefWidth="725.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/17.0.2-ea" fx:controller="com.nuculabs.dev.imagetagger.ui.MainPageController">
|
||||
<padding>
|
||||
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0"/>
|
||||
<Insets bottom="20.0" left="30.0" right="30.0" top="30.0" />
|
||||
</padding>
|
||||
<center>
|
||||
<ScrollPane>
|
||||
<VBox fx:id="verticalBox">
|
||||
</VBox>
|
||||
</ScrollPane>
|
||||
</center>
|
||||
|
||||
<Label fx:id="welcomeText"/>
|
||||
<Button text="Hello!" onAction="#onHelloButtonClick"/>
|
||||
</VBox>
|
||||
<bottom>
|
||||
<HBox alignment="CENTER_LEFT">
|
||||
<padding>
|
||||
<Insets bottom="5" left="5" right="5" top="10" />
|
||||
</padding>
|
||||
<Button onAction="#onTagImagesButtonClick" text="Tag Images" />
|
||||
<Separator orientation="VERTICAL" style="-fx-padding: 10px" />
|
||||
<Label fx:id="statusLabel" visible="false" text="Predicting... please wait" />
|
||||
</HBox>
|
||||
</bottom>
|
||||
</BorderPane>
|
Loading…
Reference in a new issue