【为生活开发系列之四】图片文字识别与标准文档对比工具

前言

我:测试?测试?测试? 5s后 测试:刚刚在对比网页上图片上的文字和标准文档里面的文字是否是同样的,看的老娘眼都废了,没空理你。 我:。。。。。。这么low的吗? 测试:莫非这位兄台有高见? 我:稍等。。。好了,能够了,来试试? 。。。 测试:666html

效果预览

效果预览

目标需求与实现需求的思路

因为每次上线活动或者运营报告的时候,网页上的不少内容直接就是UI弄好的图片,UI将图片给前端,前端直接显示这些图片,可是UI在制做这些图片的时候可能复制错内容,因此测试须要在每次上下前检查这些内容是否正确,原始的作法是电脑左边显示网页,右边显示标准文档,一个字一个字的检查,这种方式不只慢,效率低并且容易出错,因此须要咱们的时候到了。前端

需求:

给定须要检查的图片,识别图片上的内容,而后与标准文档里面的内容进行比较,找出错别字,提交给前端和UI设计师修改。为了交互友好,咱们须要作一个可视化界面进行操做。因为图片的识别可能会出错,因此咱们须要在界面上实时的显示出被检测的图片,而后在对比出错的时候检查图片识别是否出问题了。java

就拿上面的例子来讲明,咱们识别的标准文档在最上面,目标标准内容是上面输入内容去掉全部的标点符号和空格后的内容,识别图片内容是识别的图片上的内容,在咱们第一次点击开始比较的时候,显示的是匹配不成功,咱们拖动进度条以后发现,标准内容比咱们识别出来的内容多一个“平”字,咱们检查下面的图片后发现,这个“平”字是存在的,只是识别的时候出现了问题,那么咱们就认为这个不算错误,咱们删掉目标内容中的“平”字,而后再一次进行比较,此时显示对比成功,那么咱们认为这个图片中的内容与标准文档中的内容是一致的。虽然也仍是存在一些偏差,可是这中方式的效率的正确率已是以前那种方式的好几倍了。^_^git

实现需求的思路

核心功能是图片的识别,以前了解到百度云下有一个技术是图片文字识别的技术,正好能够派上用场了。 百度云文字识别快速入门,连接是 https://cloud.baidu.com/doc/OCR/OCR-Java-SDK.html#.E5.BF.AB.E9.80.9F.E5.85.A5.E9.97.A8,用法很简单,首先注册帐号,获取对应的key,secret和id啥的,而后免费版的一天能够最多识别图片500次,对于咱们测试来讲,足矣。github

其次,识别出图片上的文字以后,咱们须要将识别出的文字去掉全部空格和标点符号备用A1,获取标准内容后去掉全部空格和标点符号备用A2,而后比较A1和A2,若是是同样的就表示匹配成功,若是不同,咱们监听识别图片内容的文本框的滑动条B2,在咱们滑动这个滑动条的时候,动态的去滑动目标标准内容的滑动条B1,这样的目的是为了方便的找出不一致的文字所在的地方,找到地方以后,判断是识别问题仍是真的有问题,再作相应的处理便可。json

代码实现

因为时间比较紧,因此有些处理不是很好,之后有时间了再优化,好比去除空格和标符号的处理,就至关low逼,你们忍忍吧。安全

package com.cretin;

import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.io.File;
import java.util.HashMap;
import java.util.Iterator;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import org.json.JSONArray;
import org.json.JSONObject;

import com.baidu.aip.ocr.AipOcr;

/** * <p> * Title: TupianShibie * </p> * <p> * Description: * </p> * <p> * Company: www.cretin.com * </p> * * @author cretin * @date 2018年2月2日 */
public class TupianShibie extends JFrame {
	private static final long serialVersionUID = 1L;
	// 设置APPID/AK/SK
	public static final String APP_ID = "YOUR APP_ID";
	public static final String API_KEY = "YOUR API_KEY";
	public static final String SECRET_KEY = "YOUR SECRET_KEY";

	// 设置宽高
	private static int mWidth = 1000;
	private static int mHeight = 800;

	// 当前选择的文件
	private String currFilePath = "";

	// 控件
	private JPanel mainPanel;

	public TupianShibie() {
		setTitle("图片识别与文字对比助手");

		// 获取屏幕宽度
		Dimension screensize = Toolkit.getDefaultToolkit().getScreenSize();
		mWidth = (int) ((int) screensize.getWidth() * 0.9);
		mHeight = (int) ((int) screensize.getHeight() * 0.9);
		setSize(mWidth, mHeight);
		setResizable(false);
		setLocationRelativeTo(null);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		mainPanel = new JPanel();
		mainPanel.setLayout(null);

		// 标准内容区域
		JLabel label1 = new JLabel("请输入标准内容");
		label1.setBounds(10, 20, 100, 20);
		mainPanel.add(label1);
		JTextArea textArea = new JTextArea();
		textArea.setLineWrap(true);// 设置文本区的换行策略
// 测试时使用 省得每次都输入内容
// textArea.setText(
// "新春佳节事后,万象更新,人们饱含着新的但愿朝着新的目标,整装待发、再启征程。狗年伊始,网贷行业的发展示状是怎么样的?房融界又有哪些规划呢?2018网贷备案年正式开启,随着监管政策一步一步的落实,各网贷平台加速合规,全力迎接4月份的终极“大考”。同时,在备案关键期,平台对资产资质审核也将愈来愈严格,投资人将面临继年关事后的又一段“投标荒”时期。\n"
// + " 顺利完成备案登记将是房融界接下来工做的重中之重。2018年1月份,房融界已经向前海管理局提交了所有自查资料,并遵循政策的指引,根据律所和会计所出具的建议书加速合规整改,力争今年备案成功。同时,为解决当前投资人抢标困难的状况,房融界已经对接了车贷、消费分期等符合监管规定的优质的资产,并计划于近期上线。进行合规建设的同时,房融界也一直不敢放松对风控体系和用户体验的打造,今年房融界会继续借助科技的力量完善风控、打磨产品,提高平台服务品质。厚积“搏8”,“犬力”以赴。2018,房融界将在合规的路上继续砥砺前行,努力为投资人构建更安全、更可靠的投资环境。");
		JScrollPane jsp0 = new JScrollPane(textArea);
		jsp0.setBounds(116, 10, mWidth - 10 - 120 - 100, 100);
		jsp0.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
		mainPanel.add(jsp0);

		// 两个按钮
		JButton jButton1 = new JButton("打开图片");
		JButton jButton2 = new JButton("开始比较");
		JButton jButton3 = new JButton("清空数据");
		jButton1.setBounds(mWidth - 100, 15, 90, 30);
		jButton2.setBounds(mWidth - 100, 45, 90, 30);
		jButton3.setBounds(mWidth - 100, 75, 90, 30);
		mainPanel.add(jButton1);
		mainPanel.add(jButton2);
		mainPanel.add(jButton3);
		add(mainPanel);

		// 目标标准内容
		JLabel label2 = new JLabel("目标标准内容");
		label2.setBounds(10, 130, 100, 20);
		JTextField jTextField = new JTextField();
		JScrollPane jsp = new JScrollPane(jTextField);
		jsp.setBounds(116, 120, mWidth - 10 - 120, 60);
		jsp.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
		jsp.getHorizontalScrollBar().setEnabled(false);
		mainPanel.add(label2);
		mainPanel.add(jsp);

		// 识别图片内容
		JLabel label3 = new JLabel("识别图片内容");
		label3.setBounds(10, 200, 100, 20);
		JTextField jTextField1 = new JTextField();
		jTextField1.setEditable(false);
		JScrollPane jsp1 = new JScrollPane(jTextField1);
		jsp1.setBounds(116, 190, mWidth - 10 - 120, 60);
		jsp1.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
		mainPanel.add(label3);
		mainPanel.add(jsp1);

		// 所选图片预览
		JLabel label4 = new JLabel("所选图片预览");
		label4.setBounds(10, 270, 100, 20);
		mainPanel.add(label4);
		JLabel label = new JLabel();
		JScrollPane jsp2 = new JScrollPane(label);
		int picHeight = mHeight - 260;
		jsp2.setBounds(116, 260, mWidth - 20 - 110, picHeight - 130);
		mainPanel.add(jsp2);

		// 对比结果预览
		JLabel label5 = new JLabel("操做控制台");
		label5.setBounds(10, 270 + picHeight - 130 + 10, 100, 20);
		mainPanel.add(label5);
		JTextArea textArea1 = new JTextArea();
		JScrollPane jsp3 = new JScrollPane(textArea1);
		jsp3.setBounds(116, 260 + picHeight - 130 + 10, mWidth - 20 - 110, mHeight - (260 + picHeight - 130 + 10 + 30));
		jsp3.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
		mainPanel.add(jsp3);

		add(mainPanel);

		// 添加事件
		// 选择文件夹
		jButton1.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				// 检查内容
				String tag = textArea.getText();
				if (tag == null || tag.equals("")) {
					JOptionPane.showMessageDialog(getContentPane(), "请先输入标准内容再操做", "系统信息", JOptionPane.WARNING_MESSAGE);
					return;
				}
				JFileChooser jfc = new JFileChooser();
				jfc.setFileSelectionMode(JFileChooser.FILES_ONLY);
				jfc.showDialog(new JLabel(), "选择文件夹");
				File file = jfc.getSelectedFile();
				if (file != null) {
					textArea1.append("已选择文件:" + file.getAbsolutePath() + "\n");
					ImageIcon img = new ImageIcon(file.getAbsolutePath());// 建立图片对象
					label.setIcon(img);
					currFilePath = file.getAbsolutePath();
				} else {
					textArea1.append("取消选择文件......\n");
				}
			}
		});

		// 开始对比
		jButton2.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if (currFilePath != "" && !currFilePath.equals("")) {
					String tag = textArea.getText();
					doInt(tag, currFilePath, textArea1, jTextField, jTextField1,jButton2);
				} else {
					JOptionPane.showMessageDialog(getContentPane(), "请先选择图片再操做", "系统信息", JOptionPane.WARNING_MESSAGE);
				}
			}
		});
        //清空数据
		jButton3.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				// 清空全部数据
				textArea1.append("清空全部数据,准备进行下一次操做!!!\n");
				jTextField.setText("");
				jTextField1.setText("");
				textArea.setText("");
				//清空图片
				label.setIcon(null);
				currFilePath = "";
				jButton2.setEnabled(true);
			}
		});
		// 对滑动条进行监听
		JScrollBar bar = jsp1.getHorizontalScrollBar();
		bar.addAdjustmentListener(new AdjustmentListener() {

			@Override
			public void adjustmentValueChanged(AdjustmentEvent e) {
                //获取到标准内容的滑动条 并将目前滑动的进度传给他
				jsp.getHorizontalScrollBar().setValue(e.getValue());
			}
		});
		// 显示窗体
		setVisible(true);
	}

	public static void main(String[] args) {
		new TupianShibie();
	}

	private void doInt(String aimStr, String path, JTextArea textArea1, JTextField jTextField, JTextField jTextField1, JButton jButton2) {
		String aimStr1 = "";
		String content = jTextField.getText();
		if (content == "" || content.equals("")) {
			aimStr1 = formatStr(aimStr);
			jTextField.setText(aimStr1);
		}else {
			aimStr1 = content;
		}
		final String aimStr2 = aimStr1;
		jButton2.setEnabled(false);
		textArea1.append("正在对比,请等待...\n");
		// 初始化一个AipOcr
		AipOcr client = new AipOcr(APP_ID, API_KEY, SECRET_KEY);
		// 可选:设置网络链接参数
		client.setConnectionTimeoutInMillis(2000);
		client.setSocketTimeoutInMillis(60000);
		new Thread() {
			public void run() {
				// 调用接口
				JSONObject res = client.basicGeneral(path, new HashMap<String, String>());
				JSONArray array = res.getJSONArray("words_result");
				Iterator<Object> it = array.iterator();
				StringBuffer stringBuffer = new StringBuffer();
				while (it.hasNext()) {
					JSONObject ob = (JSONObject) it.next();
					String ss = ob.getString("words");
					stringBuffer.append(ss);
				}
				String endStr = formatStr(stringBuffer.toString());
				jTextField1.setText(endStr);
				textArea1.append("对比完成!!!\n");
				if (endStr.equals(aimStr2)) {
					textArea1.append("对比结果:匹配成功\n");
					JOptionPane.showMessageDialog(getContentPane(), "恭喜,匹配成功", "系统信息", JOptionPane.INFORMATION_MESSAGE);
				} else {
					textArea1.append("对比结果:匹配不成功,请检查\n");
					JOptionPane.showMessageDialog(getContentPane(), "匹配不成功,请注意", "系统信息", JOptionPane.WARNING_MESSAGE);
				}
				jButton2.setEnabled(true);
			};
		}.start();

	}

	// 去除标点符号 去除换行和空格
	private static String formatStr(String aimStr) {
		aimStr = aimStr.trim();
		// 对aimStr 去除标点符号 去除换行和空格
		aimStr = aimStr.replaceAll("\\n", "");
		aimStr = aimStr.replaceAll("\\r", "");
		aimStr = aimStr.replaceAll("\\t", "");
		aimStr = aimStr.replaceAll(",", "");
		aimStr = aimStr.replaceAll("。", "");
		aimStr = aimStr.replaceAll(",", "");
		aimStr = aimStr.replaceAll("、", "");
		aimStr = aimStr.replaceAll("\\.", "");
		aimStr = aimStr.replaceAll("(", "");
		aimStr = aimStr.replaceAll(")", "");
		aimStr = aimStr.replaceAll("\\)", "");
		aimStr = aimStr.replaceAll("\\(", "");
		aimStr = aimStr.replaceAll("!", "");
		aimStr = aimStr.replaceAll("!", "");
		aimStr = aimStr.replaceAll("\\?", "");
		aimStr = aimStr.replaceAll("?", "");
		aimStr = aimStr.replaceAll("“", "");
		aimStr = aimStr.replaceAll("\\:", "");
		aimStr = aimStr.replaceAll(":", "");
		aimStr = aimStr.replaceAll(";", "");
		aimStr = aimStr.replaceAll("\\;", "");
		aimStr = aimStr.replaceAll("”", "");
		aimStr = aimStr.replaceAll("\"", "");
		aimStr = aimStr.replaceAll(" ", "");
		return aimStr;
	}
}
复制代码

相关链接

百度云文字识别快速入门,连接是 https://cloud.baidu.com/doc/OCR/OCR-Java-SDK.html#.E5.BF.AB.E9.80.9F.E5.85.A5.E9.97.A8网络

百度云文字识别sdk下载,连接是 http://ai.baidu.com/sdkapp

GIthub项目QuickMapping,连接是 https://github.com/MZCretin/QuickMappingjsp

本项目代码也已经上传github了,能够直接使用项目中的jar文件,另外你们须要本身去申请帐号哦,为了测试能正常使用,个人帐号就不暴露了,谢谢理解。

我就是比较喜欢用代码解决生活中的问题,感受很开心,哈哈哈。也喜欢你们关注个人简书,掘金,Github和CSDN。

简书首页,连接是 https://www.jianshu.com/u/123f97613b86

掘金首页,连接是 https://juejin.im/user/5838d57fac502e006c1708bc

Github首页,连接是 https://github.com/MZCretin

CSDN首页,连接是 http://blog.csdn.net/u010998327

我是Cretin,一个可爱的小男孩。