JavaFXを使用してOpenCVで行なった処理を表示する仕組み(アプリ)を作成します。
前回、SceneBuilderを使用して作成した画面の土台になる部分に、コントローラーを追加しました。
これにより「ボタンを押下した時にXXXの処理をする〜」というような処理を実装することができます。
画像を描画する
そして、やっとOpenCVの処理にたどり着きました。
イメージファイルを読み込み表示する。。。ハローワールド的な処理ですが、まずはハローワールドです。
出力した結果はい下のような感じで出力することができました。
実装(成果物)
「FXMLファイル」
<?xml version="1.0" encoding="UTF-8"?> <?import javafx.scene.canvas.*?> <?import javafx.scene.control.*?> <?import java.lang.*?> <?import javafx.scene.layout.*?> <BorderPane fx:controller="zenryokuservice.opencv.fx.controller.TestingCvController" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"> <top> <HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0" BorderPane.alignment="CENTER"> <children> <Label text="Input app no" /> <TextField promptText="App No" /> <Button mnemonicParsing="false" text="Execute" onAction="#clickExecute"/> </children> </HBox> </top> <center> <Canvas fx:id="testCanvas" height="200.0" width="200.0" BorderPane.alignment="CENTER" /> </center> <bottom> <HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0" BorderPane.alignment="CENTER"> <children> <Button mnemonicParsing="false" text="Clear" onAction="#clear"/> </children> </HBox> </bottom> </BorderPane>
コントローラー
public class TestingCvController { @FXML private Canvas testCanvas; /** コンストラクタ */ public TestingCvController() { this.testCanvas = new Canvas(); } @FXML protected void clickExecute() { System.out.println("Helllo"); URL url = getClass().getResource("/pipo-charachip007.png"); Mat charactor = Imgcodecs.imread(url.getPath(), CvType.CV_8UC4); MatOfByte charaByte = new MatOfByte(); Imgcodecs.imencode(".png", charactor, charaByte); try { // Image img = new Image(url.getPath().toString()); BufferedImage buf = ImageIO.read(new ByteArrayInputStream(charaByte.toArray())); GraphicsContext g = testCanvas.getGraphicsContext2D(); g.drawImage(SwingFXUtils.toFXImage(buf, null), buf.getWidth(), buf.getHeight()); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @FXML public void setClosed() { // 現状は空実装 } @FXML public void clear() { System.out.println("Clear"); this.testCanvas.getGraphicsContext2D().clearRect(0, 0, this.testCanvas.getWidth(), this.testCanvas.getHeight()); } }
処理内容
FXMLで、アクションを指定しています。
<Button mnemonicParsing="false" text="Execute" onAction="#clickExecute"/>
この行で指定している#clickExevute
の部分でコントローラークラスの「TestingCvController#clickExevute()
を呼び出す」という意味になります。
同様に、<Button mnemonicParsing="false" text="Clear" onAction="#clear"/>
の部分は「TestingCvController#clear()
」を呼び出す。という命令を指定しています。
画像を表示する
下の処理が起動するメソッドになります。
@FXML protected void clickExecute() { System.out.println("Helllo"); URL url = getClass().getResource("/pipo-charachip007.png"); Mat charactor = Imgcodecs.imread(url.getPath(), CvType.CV_8UC4); MatOfByte charaByte = new MatOfByte(); Imgcodecs.imencode(".png", charactor, charaByte); try { BufferedImage buf = ImageIO.read(new ByteArrayInputStream(charaByte.toArray())); GraphicsContext g = testCanvas.getGraphicsContext2D(); g.drawImage(SwingFXUtils.toFXImage(buf, null), buf.getWidth(), buf.getHeight()); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
ビルドパス上にあるフォルダより「pipo-charachip007.png"」を読み込み、SceneBuilderで作成したCanvasに書き込み処理を行っています。
上に表示した画像は指定のpngファイルを表示したものです。
ここまで来たので
現状としては、固定のイメージファイルを表示しているだけですが、ここからアプリっぽくしていきます。
変更点としては下の部分です。
- テキストボックスに入力したファイル名を表示する
- Clearボタンを押下したら、現在表示している画像を消す
とりあえずはここまで実装します。
LearnOpenCvクラスを作る
設計としては以下のような実装にしようと考えております。
- テキストフィールドに処理の名前(コマンド)を入力
- コマンドに対応したクラスの
execute()
を起動する→なのでコマンドはいくらでも増やすことができる
具体的にどのように実現するか?
すでに実装してあるclickExcecute()
の処理を修正して下のように変更する
- 入力値を受け取り、プロパティファイルのキーの有無をチェック
- プロパティファイルにキーがあれば、キーに紐付くクラスを取得、
execte()
を起動する - 実行結果をCanvasに描画する
なので、execute()
には引数としてGraphicsContextを渡してあげる必要があります。(描画するためです)
実装は次回にいたします。
でわでわ。。。