龙空技术网

OCR识别护照(一):JavaFX搭建可视化界面

小新coding 789

前言:

当前姐妹们对“javafx显示图片”大致比较珍视,我们都需要分析一些“javafx显示图片”的相关知识。那么小编在网摘上搜集了一些对于“javafx显示图片””的相关内容,希望兄弟们能喜欢,大家一起来学习一下吧!

本系列文章将介绍一个使用OCR技术批量识别护照的桌面小工具的编写过程。使用到的主要技术为java、javafx、pdfbox等。最终代码将上传Github和Gitee。

OCR识别护照(二):护照识别及数据导出

需求描述

一个在国际学校做HR的朋友跟我说总是需要在OA系统或excel中录入外籍人员的护照信息,每次都需要打开pdf文件或图片对照填写,一旦遇到大批外籍员工入职或更换护照、签证信息时,工作量较大且容易出错。于是我利用业余时间给她写了一个小工具,可以批量识别护照。

新建javafx项目

在idea中新建JavaFxApplication,取名passportScanner。

界面布局

使用Idea自带的javafx编辑工具,简单地实现程序的界面布局。

<?xml version="1.0" encoding="UTF-8"?><?import javafx.geometry.*?><?import javafx.scene.control.*?><?import javafx.scene.layout.*?><?import javafx.scene.text.*?><AnchorPane prefHeight="500.0" prefWidth="1024.0" xmlns="; xmlns:fx="; fx:controller="org.xy.passportScanner.MainController">   <children>      <VBox layoutX="14.0" layoutY="6.0" prefHeight="500.0" prefWidth="1024.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">         <children>            <GridPane hgap="8.0" prefHeight="80.0" prefWidth="1024.0" vgap="12.0">              <columnConstraints>                <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="300.0" />                <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="160.0" />              </columnConstraints>              <rowConstraints>                <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />                <RowConstraints minHeight="10.0" prefHeight="40.0" vgrow="SOMETIMES" />              </rowConstraints>               <children>                  <Button fx:id="fileButton" mnemonicParsing="false" text="选择文件" GridPane.columnIndex="1">                     <font>                        <Font size="14.0" />                     </font></Button>                  <Label text="(png,jpg,bmp,pdf)" GridPane.columnIndex="1">                     <GridPane.margin>                        <Insets left="90.0" />                     </GridPane.margin>                     <font>                        <Font size="14.0" />                     </font>                  </Label>                  <TextArea fx:id="filePath" editable="false" prefHeight="200.0" prefWidth="200.0" />                  <HBox prefHeight="100.0" prefWidth="200.0" spacing="20.0" GridPane.columnSpan="2" GridPane.rowIndex="1">                     <children>                        <Button fx:id="scanButton" graphicTextGap="8.0" layoutX="10.0" layoutY="10.0" minWidth="108.0" mnemonicParsing="false" text="开始识别">                           <font>                              <Font size="20.0" />                           </font>                           <opaqueInsets>                              <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />                           </opaqueInsets>                        </Button>                        <Label fx:id="tipLabel" prefHeight="40.0" wrapText="true">                           <font>                              <Font size="18.0" />                           </font>                        </Label>                     </children>                  </HBox>               </children>               <VBox.margin>                  <Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />               </VBox.margin>            </GridPane>            <AnchorPane prefHeight="200.0" prefWidth="200.0" VBox.vgrow="ALWAYS">               <children>                  <TableView fx:id="resultTable" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="420.0" prefWidth="1024.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />               </children>            </AnchorPane>         </children>      </VBox>   </children></AnchorPane>
设置界面大小、图标、标题

在resources/images文件夹中添加passport.png。

在Main.java的start方法中添加以下代码。

package org.xy.passportScanner;import javafx.scene.image.Image;import org.xy.passportScanner.config.GlobalData;import org.xy.passportScanner.config.Settings;import javafx.application.Application;import javafx.event.EventHandler;import javafx.fxml.FXMLLoader;import javafx.scene.Parent;import javafx.scene.Scene;import javafx.stage.Stage;import javafx.stage.WindowEvent;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.yaml.snakeyaml.Yaml;import org.yaml.snakeyaml.constructor.Constructor;import java.io.InputStream;public class Main extends Application {    private static final Logger logger = LoggerFactory.getLogger(Main.class);    @Override    public void start(Stage primaryStage) throws Exception {        //加载界面文件        Parent load = FXMLLoader.load(getClass().getClassLoader().getResource("main.fxml"));        //设置窗口大小        Scene scene = new Scene(load, 1024, 500);        primaryStage.setScene(scene);        //设置标题和logo        primaryStage.setTitle("PassportScanner");        primaryStage.getIcons().add(new Image("images/passport.png"));        //显示页面        primaryStage.show();        //关闭事件处理        primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() {            @Override            public void handle(WindowEvent event) {                System.exit(0);            }        });    }    public static void main(String[] args) {        launch(args);    }}
tableview绑定数据

新建PassportBean.java类,与不同javabean不同,所有属性均使用StringProperty,以便与javafx组件绑定数据。

package org.xy.passportScanner.data;import javafx.beans.property.SimpleStringProperty;import javafx.beans.property.StringProperty;public class PassportBean {    //文件序号    private StringProperty id = new SimpleStringProperty();    //文件名    private StringProperty file = new SimpleStringProperty();    //护照号    private StringProperty number = new SimpleStringProperty();    //姓名    private StringProperty name = new SimpleStringProperty();    //性别    private StringProperty gender = new SimpleStringProperty();    //出生日期    private StringProperty birthday = new SimpleStringProperty();    //有效期    private StringProperty expireDate = new SimpleStringProperty();    //签发国    private StringProperty issuingCountry = new SimpleStringProperty();    //国籍    private StringProperty nationality = new SimpleStringProperty();    //备注    private StringProperty comments = new SimpleStringProperty();    public PassportBean(String id, String file, String number, String name, String gender, String birthday, String expireDate, String issuingCountry, String nationality, String comments){        this.id.set(id);        this.file.set(file);        this.number.set(number);        this.name.set(name);        this.gender.set(gender);        this.birthday.set(birthday);        this.expireDate.set(expireDate);        this.issuingCountry.set(issuingCountry);        this.nationality.set(nationality);        this.comments.set(comments);    }    public PassportBean(){}    public String getId() {        return id.get();    }    public StringProperty idProperty() {        return id;    }    public void setId(String id) {        this.id.set(id);    }    public String getFile() {        return file.get();    }    public StringProperty fileProperty() {        return file;    }    public void setFile(String file) {        this.file.set(file);    }    public String getNumber() {        return number.get();    }    public StringProperty numberProperty() {        return number;    }    public void setNumber(String number) {        this.number.set(number);    }    public String getName() {        return name.get();    }    public StringProperty nameProperty() {        return name;    }    public void setName(String name) {        this.name.set(name);    }    public String getGender() {        return gender.get();    }    public StringProperty genderProperty() {        return gender;    }    public void setGender(String gender) {        this.gender.set(gender);    }    public String getBirthday() {        return birthday.get();    }    public StringProperty birthdayProperty() {        return birthday;    }    public void setBirthday(String birthday) {        this.birthday.set(birthday);    }    public String getExpireDate() {        return expireDate.get();    }    public StringProperty expireDateProperty() {        return expireDate;    }    public void setExpireDate(String expireDate) {        this.expireDate.set(expireDate);    }    public String getIssuingCountry() {        return issuingCountry.get();    }    public StringProperty issuingCountryProperty() {        return issuingCountry;    }    public void setIssuingCountry(String issuingCountry) {        this.issuingCountry.set(issuingCountry);    }    public String getNationality() {        return nationality.get();    }    public StringProperty nationalityProperty() {        return nationality;    }    public void setNationality(String nationality) {        this.nationality.set(nationality);    }    public String getComments() {        return comments.get();    }    public StringProperty commentsProperty() {        return comments;    }    public void setComments(String comments) {        this.comments.set(comments);    }}

在MainController的initialize方法中为tableview绑定数据

//初始化结果表resultTable.setItems(data);TableColumn<PassportBean,String> id = new TableColumn<PassportBean,String>("序号");id.prefWidthProperty().bind(resultTable.widthProperty().multiply(0.05));id.setCellFactory(TextFieldTableCell.forTableColumn());id.setCellValueFactory(new PropertyValueFactory<PassportBean, String>("id"));id.getStyleClass().add("alarm-table");resultTable.getColumns().add(id);TableColumn<PassportBean,String> file = new TableColumn<PassportBean,String>("文件");file.prefWidthProperty().bind(resultTable.widthProperty().multiply(0.15));file.setCellValueFactory(new PropertyValueFactory<PassportBean,String>("file"));file.getStyleClass().add("alarm-table");resultTable.getColumns().add(file);TableColumn<PassportBean,String> number = new TableColumn<PassportBean,String>("护照号");number.prefWidthProperty().bind(resultTable.widthProperty().multiply(0.1));number.setCellValueFactory(new PropertyValueFactory<PassportBean,String>("number"));number.getStyleClass().add("alarm-table");resultTable.getColumns().add(number);TableColumn<PassportBean,String> name = new TableColumn<PassportBean,String>("姓名");name.prefWidthProperty().bind(resultTable.widthProperty().multiply(0.25));name.setCellValueFactory(new PropertyValueFactory<PassportBean,String>("name"));name.getStyleClass().add("alarm-table");resultTable.getColumns().add(name);TableColumn<PassportBean,String> gender = new TableColumn<PassportBean,String>("性别");gender.prefWidthProperty().bind(resultTable.widthProperty().multiply(0.05));gender.setCellValueFactory(new PropertyValueFactory<PassportBean,String>("gender"));gender.getStyleClass().add("alarm-table");resultTable.getColumns().add(gender);TableColumn<PassportBean,String> birthday = new TableColumn<PassportBean,String>("出生日期");birthday.prefWidthProperty().bind(resultTable.widthProperty().multiply(0.1));birthday.setCellValueFactory(new PropertyValueFactory<PassportBean,String>("birthday"));birthday.getStyleClass().add("alarm-table");resultTable.getColumns().add(birthday);TableColumn<PassportBean,String> expireDate = new TableColumn<PassportBean,String>("有效期");expireDate.prefWidthProperty().bind(resultTable.widthProperty().multiply(0.1));expireDate.setCellValueFactory(new PropertyValueFactory<PassportBean,String>("expireDate"));expireDate.getStyleClass().add("alarm-table");resultTable.getColumns().add(expireDate);TableColumn<PassportBean,String> issuingCountry = new TableColumn<PassportBean,String>("签发国");issuingCountry.prefWidthProperty().bind(resultTable.widthProperty().multiply(0.05));issuingCountry.setCellValueFactory(new PropertyValueFactory<PassportBean,String>("issuingCountry"));issuingCountry.getStyleClass().add("alarm-table");resultTable.getColumns().add(issuingCountry);TableColumn<PassportBean,String> nationality = new TableColumn<PassportBean,String>("国籍");nationality.prefWidthProperty().bind(resultTable.widthProperty().multiply(0.05));nationality.setCellValueFactory(new PropertyValueFactory<PassportBean,String>("nationality"));nationality.getStyleClass().add("alarm-table");resultTable.getColumns().add(nationality);TableColumn<PassportBean,String> comments = new TableColumn<PassportBean,String>("备注");comments.prefWidthProperty().bind(resultTable.widthProperty().multiply(0.1));comments.setCellValueFactory(new PropertyValueFactory<PassportBean,String>("comments"));comments.getStyleClass().add("alarm-table");resultTable.getColumns().add(comments);//模拟数据data.add(new PassportBean("1", "c:/123", "12345", "LI SI", "M", "20010302", "20250909", "CHN", "CHN", ""));data.add(new PassportBean("2", "c:/123", "12345", "LI SI", "M", "20010302", "20250909", "CHN", "CHN", ""));
运行Main看看效果

至此,界面已经可以运行了。运行Main.main后,界面如下图。

javafx打包为exe程序

javafx打包使用的plugin为com.zenjava,详细配置如下:

如果需要修改默认的exe图标,则需要制作相应的ico图片,并放到指定目录下,如resources/images/passport.ico。

<plugin>    <groupId>com.zenjava</groupId>    <artifactId>javafx-maven-plugin</artifactId>    <version>8.8.3</version>    <configuration>        <!--运行类-->        <mainClass>org.xy.passportScanner.Main</mainClass>        <vendor>pegasus</vendor>        <bundleArguments>            <!-- 指示用户是否可以选择应用程序安装目录 -->            <installdirChooser>true</installdirChooser>            <!--exe图标-->            <icon>${project.basedir}/src/main/resources/images/passport.ico</icon>        </bundleArguments>        <allPermissions>true</allPermissions>        <!--添加到程序列表-->        <needMenu>true</needMenu>        <!--桌面快捷方式-->        <needShortcut>true</needShortcut>    </configuration></plugin>

配置好以后,执行maven clean package和jfx:build-native即可将javafx程序打包生成exe文件,同时将java运行环境一起打包。

标签: #javafx显示图片