效果演示

先看一下界面,界面做的有点简陋

大致记录一下操作的过程
1.点击训练
2.选择一个需要训练的数字
3.在白色面板上写下该训练的数字
4.写完后点击确定
5.双击白色面板,清除画的数字痕迹,重复②和3的步骤,直到训练完所有的数字6.在白色面板上写下需要识别的数字
7.点击识别,则会有一个小框弹出,显示识别出的数字,点击小框的确定按钮,双击白色面板,清除画过的痕迹
8.再一次在白色面板上写下需要识别的数字,再次点击识别,可以重复7和8步骤
注意:一次仅能识别一位数字,每画完一次数字需要再次点击识别
识别过程演示如下:
写下数字0

再点击识别按钮

写下数字4

再点击识别按钮

实现过程

一. 画出界面,加监听器
注意:

  • 在这里添加的JRadioButton单选按钮组件训练和识别,两个按钮不可以同时选择,所以将这两个组件加入了ButtonGroup中去,这样同一时刻仅仅可以选择其中一个;
  • 这里其实可以不用单独为每个组件添加监听器,但是为了更方便区分各自的功能,我给每个组件单独添加了监听器;
this.setTitle("数字手写识别");this.setSize(400, 400);this.setDefaultCloseOperation(3);this.setResizable(false);this.setLocationRelativeTo(null);//设置为流式布局this.setLayout(new FlowLayout());//添加单选按钮组件JRadioButton button_recognition = new JRadioButton("识别");JRadioButton button_exercise = new JRadioButton("训练");button_recognition.setActionCommand("识别");button_exercise.setActionCommand("训练");//加入到ButtonGroup中的JRadioButton只有一个可以被选中,每个JRadioButton独享一个监听器,//当其被选中时执行监听器中的处理方法ButtonGroup group = new ButtonGroup();group.add(button_recognition);group.add(button_exercise);//在这里JRadioButton被添加了两次,一次加到了ButtonGroup中,另一次是加到了JPanel中,//但是ButtonGroup不需要被添加this.add(button_recognition);this.add(button_exercise);String[] label = {"0","1","2","3","4","5","6","7","8","9"};jcb = new JComboBox(label);this.add(jcb);//添加写数字的面板JPanel jp = new JPanel();//jp.setLayout(new FlowLayout(FlowLayout.CENTER,0,0));//设置添加的写数字的面板的位置和大小//JPanel需要使用的方法为setPreferredSize()jp.setPreferredSize(new Dimension(300,300));jp.setBackground(Color.white);this.add(jp);//BorderLayout.CENTERJButton button_sure = new JButton("确定");button_sure.setActionCommand("确定");this.add(button_sure);this.setVisible(true);g = jp.getGraphics();gD = (Graphics2D)g;//添加监听器Listener l = new Listener(g,jcb);//给面板添加鼠标监听器,用于画数字的记录JpanelListener jpListener = new JpanelListener();jp.addMouseListener(jpListener);jp.addMouseMotionListener(jpListener);//识别按钮加上监听器JButton_recognitionListener JButton_recognition = new JButton_recognitionListener();button_recognition.addActionListener(JButton_recognition);//训练按钮加上监听器JButton_exerciseListener JButton_exercise = new JButton_exerciseListener();button_exercise.addActionListener(JButton_exercise);//给确定按钮加上监听器JButton_sureListener JButton_sure = new JButton_sureListener();button_sure.addActionListener(JButton_sure);//给数字滑条加上监听器JComboBoxListener Jcombobox = new JComboBoxListener();jcb.addActionListener(Jcombobox);}

二,生成数字数组number_list

 //面板将写的数字生成二维数组   并且  从中判断数字private class JpanelListener extends MouseAdapter {public void mouseClicked(MouseEvent e) {//双击画布,则清除画布为白色,且将数字数组清为全0if(e.getClickCount()==2) {gD.setColor(Color.white);gD.fillRect(0, 0,299, 299);for(int i = 0;i<30;i++) {for(int j = 0;j<30;j++) {number_list[i][j] = 0;}}}}public void mousePressed(MouseEvent e) {x1 = e.getX();y1 = e.getY();}public void mouseDragged(MouseEvent e) {x2 = e.getX();y2 = e.getY();gD.setStroke(new BasicStroke(12));gD.setColor(Color.black);gD.drawLine(x1, y1, x2, y2);//1.将写入的数字转化为二维数组for(int i = 0;i<number_list.length;i++) {for(int j = 0;j<number_list.length;j++) {if(x2<i*size && x2>(i-1)*size) {if(y2<j*size && y2>(j-1)*size) {//记录鼠标走过的区域number_list[i][j] =1;}}}}x1 = x2;y1 = y2;}}

三,将生成的数字数组写入对应的txt文件中去
注意:

  • 这里文件名必须保证不重复,故文件命名时加入了时间System.currentTimeMillis()
//确定按钮,之后将数字生成的二维数组写入文件中去private class JButton_sureListener implements ActionListener{@Overridepublic void actionPerformed(ActionEvent e) {if(e.getActionCommand().equals("确定")) {//如果用户写好数字之后,点击确定,打印出数组并写入文件
//              for(int i = 0;i<number_list.length;i++) {
//                  for(int j = 0;j<number_list.length;j++) {
//                      System.out.print(number_list[j][i]+" ");
//                  }
//                  System.out.println("");
//              }//给文件起名,为了不重复,在其中添加时间进行命名File file = new File("D:\\Java需要\\handing\\"+num+"--"+System.currentTimeMillis()+".txt");try {FileWriter out = new FileWriter(file);System.out.println("----------------点击训练按钮了");for(int i = 0;i<30;i++) {for(int j = 0;j<30;j++) {//public void write(int c:,写入单个字符,参数:c - 指定要写入字符的 int。out.write(number_list[i][j]);}}out.flush();out.close();} catch (IOException e1) {e1.printStackTrace();}}}}

四,识别过程第一步,将上一步txt文件中的内容取出存入数组number_list_read中去
程序片段:

//识别下,应该先读取训练完成后数字文件中的内容File file = new File("D:\\Java需要\\handing\\");//得到目录下所有文件名//list():返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录。String[] filelist = file.list();for(int i=0;i<filelist.length;i++) {try {FileReader in = new FileReader("D:\\Java需要\\handing\\"+filelist[i]);try {//选用了public int read():读取单个字符,返回:读取的字符,如果已到达流的末尾,则返回 -1 int b = in.read();int m = 0;int n = 0;while(b!=-1) {//如果读取的文件还没有到达文件尾//取出来的数字存入number_list_read数组中去number_list_read[m][n] = b;n++;//按行读if(n == 30) {n = 0;m++;//按列读}//读取下一个字符b = in.read();}//读取文件结束//关闭文件in.close();

五,将读取的每个数组txt文件中的内容,与当前识别状态下面板上画出的数字数组对比,算出欧氏距离存入数组distance中,并记录下对应文件代表的数字
注意

  • 在第五步之前,已经通过训练写下了0~9十个数字并且生成了对应的若干个txt文件,当前在面板上写下了需要识别的数字并且已经生成了对应的数字数组number_list
  • 点击识别按钮,就会进行第五步需要的操作,也就是将目录中的若干个txt文件中的内容和当前的number_list进行比较,算出相应的若干个欧式距离,存入数组distance中去,并且记录下目录中的若干个txt文件所代表的数字0~9,存入数组number_recognize中去
//获得数字文件名字的首字符,Integer.parseInt方法用于将String类型转换为int类型int number = Integer.parseInt(filelist[i].substring(0, 1));//计算距离int d = 0;//遍历所有点,算出所有欧式距离之和for(int p = 0;p<30;p++) {for(int q = 0;q<30;q++) {d += Math.abs(number_list_read[p][q] - number_list[p][q]);}}//将训练后的每个数字文件中的内容与识别写入的数字数组计算欧式距离distance.add(d);//存入数字文件中代表的数字number_recognize.add(number);

六,将算出的欧式距离从小到大排序,选取最短的距离和作为识别的结果

//接着将所有求出的欧式距离进行从小到大的排序for(int i = 0;i<distance.size()-1;i++) {for(int j = 0;j<distance.size()-1-i;j++) {if(distance.get(j)>distance.get(j+1)) {//交换j和j+1两个位置的值int temp = distance.get(j);distance.set(j, distance.get(j+1));distance.set(j+1,temp);//还有代表的数字number_recognize也需要发生变化int tempnum = number_recognize.get(j);number_recognize.set(j, number_recognize.get(j+1));number_recognize.set(j+1,tempnum);}}}//排好序之后,选取欧式距离最短的int result = number_recognize.get(0);JOptionPane.showMessageDialog(null, "识别出的数字是:"+result);

源代码

package Handing;import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;public class MainFrame extends JFrame{public static void main(String[] args) {MainFrame mf = new MainFrame();mf.initUI();}Graphics g;Graphics2D gD;private static volatile int num;private int x1;private int y1;private int x2;private int y2;private static int size = 10;private static volatile int number_list[][] = new int[30][30];private static volatile int number_list_read[][] = new int[30][30];//存放计算的欧式距离private ArrayList<Integer> distance = new ArrayList<Integer>();private ArrayList<Integer> number_recognize = new ArrayList<Integer>();JComboBox jcb;private void initUI() {this.setTitle("数字手写识别");this.setSize(400, 400);this.setDefaultCloseOperation(3);this.setResizable(false);this.setLocationRelativeTo(null);//设置为流式布局this.setLayout(new FlowLayout());//添加单选按钮组件JRadioButton button_recognition = new JRadioButton("识别");JRadioButton button_exercise = new JRadioButton("训练");button_recognition.setActionCommand("识别");button_exercise.setActionCommand("训练");//加入到ButtonGroup中的JRadioButton只有一个可以被选中,每个JRadioButton独享一个监听器,//当其被选中时执行监听器中的处理方法ButtonGroup group = new ButtonGroup();group.add(button_recognition);group.add(button_exercise);//在这里JRadioButton被添加了两次,一次加到了ButtonGroup中,另一次是加到了JPanel中,//但是ButtonGroup不需要被添加this.add(button_recognition);this.add(button_exercise);String[] label = {"0","1","2","3","4","5","6","7","8","9"};jcb = new JComboBox(label);this.add(jcb);//添加写数字的面板JPanel jp = new JPanel();//设置添加的写数字的面板的位置和大小//JPanel需要使用的方法为setPreferredSize()jp.setPreferredSize(new Dimension(300,300));jp.setBackground(Color.white);this.add(jp);//BorderLayout.CENTERJButton button_sure = new JButton("确定");button_sure.setActionCommand("确定");this.add(button_sure);this.setVisible(true);g = jp.getGraphics();gD = (Graphics2D)g;//添加监听器Listener l = new Listener(g,jcb);//给面板添加鼠标监听器,用于画数字的记录JpanelListener jpListener = new JpanelListener();jp.addMouseListener(jpListener);jp.addMouseMotionListener(jpListener);//识别按钮加上监听器JButton_recognitionListener JButton_recognition = new JButton_recognitionListener();button_recognition.addActionListener(JButton_recognition);//训练按钮加上监听器JButton_exerciseListener JButton_exercise = new JButton_exerciseListener();button_exercise.addActionListener(JButton_exercise);//给确定按钮加上监听器JButton_sureListener JButton_sure = new JButton_sureListener();button_sure.addActionListener(JButton_sure);//给数字滑条加上监听器JComboBoxListener Jcombobox = new JComboBoxListener();jcb.addActionListener(Jcombobox);}//--------------------------------------------------------------------//给数字滑条加上监听器,便于监听用户点击训练的的是哪个数字private class JComboBoxListener implements ActionListener{@Overridepublic void actionPerformed(ActionEvent e) {num = jcb.getSelectedIndex();}}//--------------------------------------------------------------//确定按钮监听,点击后将用户所画的数字生成的二维数组写入文件中private class JButton_sureListener implements ActionListener{@Overridepublic void actionPerformed(ActionEvent e) {if(e.getActionCommand().equals("确定")) {//如果用户写好数字之后,点击确定,可以打印出数组查看后写入文件
//              for(int i = 0;i<number_list.length;i++) {
//                  for(int j = 0;j<number_list.length;j++) {
//                      System.out.print(number_list[j][i]+" ");
//                  }
//                  System.out.println("");
//              }//给文件起名,为了不重复,在其中添加时间进行命名File file = new File("D:\\Java需要\\handing\\"+num+"--"+System.currentTimeMillis()+".txt");try {FileWriter out = new FileWriter(file);for(int i = 0;i<30;i++) {for(int j = 0;j<30;j++) {//public void write(int c:,写入单个字符,参数:c - 指定要写入字符的 intout.write(number_list[i][j]);}}out.flush();out.close();} catch (IOException e1) {e1.printStackTrace();}}}}//---------------------------------------------------------------//训练下应该进行的操作,实际上没有写具体用处,可去掉该监听private class JButton_exerciseListener implements ActionListener{@Overridepublic void actionPerformed(ActionEvent e) {//训练下应该监听训练的数字}}//------------------------------------------------------------------//识别按钮下应该进行的操作,操作是先在面板上写下数字,生成了一个数组文件,然后将该数组文件与训练中的数字文件求欧式距离,选取最小者private class JButton_recognitionListener implements ActionListener{@Overridepublic void actionPerformed(ActionEvent e) {distance.clear();number_recognize.clear();//识别下,应该先读取训练完成后数字文件中的内容File file = new File("D:\\Java需要\\handing\\");//得到目录下所有文件名//list():返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录。String[] filelist = file.list();for(int i=0;i<filelist.length;i++) {try {FileReader in = new FileReader("D:\\Java需要\\handing\\"+filelist[i]);try {//选用了public int read():读取单个字符,返回:读取的字符,如果已到达流的末尾,则返回 -1 int b = in.read();int m = 0;int n = 0;while(b!=-1) {//如果读取的文件还没有到达文件尾//取出来的数字存入number_list_read数组中去number_list_read[m][n] = b;n++;//按行读if(n == 30) {n = 0;m++;//按列读}//读取下一个字符b = in.read();}//读取文件结束//关闭文件in.close();//获得数字文件名字的首字符,Integer.parseInt方法用于将String类型转换为int类型int number = Integer.parseInt(filelist[i].substring(0, 1));//计算距离int d = 0;//遍历所有点,算出所有欧式距离之和for(int p = 0;p<30;p++) {for(int q = 0;q<30;q++) {d += Math.abs(number_list_read[p][q] - number_list[p][q]);}}//将训练后的每个数字文件中的内容与识别写入的数字数组计算欧式距离distance.add(d);//存入数字文件中代表的数字number_recognize.add(number);} catch (IOException e1) {e1.printStackTrace();}} catch (FileNotFoundException e1) {e1.printStackTrace();}}//接着将所有求出的欧式距离进行从小到大排序for(int i = 0;i<distance.size()-1;i++) {for(int j = 0;j<distance.size()-1-i;j++) {if(distance.get(j)>distance.get(j+1)) {//交换j和j+1两个位置的值int temp = distance.get(j);distance.set(j, distance.get(j+1));distance.set(j+1,temp);//还有代表的数字number_recognize也需要发生变化int tempnum = number_recognize.get(j);number_recognize.set(j, number_recognize.get(j+1));number_recognize.set(j+1,tempnum);}}}//排好序之后,选取欧式距离最短的作为识别结果int result = number_recognize.get(0);JOptionPane.showMessageDialog(null, "识别出的数字是:"+result);}}//-----------------------------------------------------------------//面板将写的数字生成二维数组   并且  从中判断数字private class JpanelListener extends MouseAdapter {public void mouseClicked(MouseEvent e) {//双击画布,则清除画布为白色,且将数组清为全0if(e.getClickCount()==2) {gD.setColor(Color.white);gD.fillRect(0, 0,299, 299);for(int i = 0;i<30;i++) {for(int j = 0;j<30;j++) {number_list[i][j] = 0;}}}}public void mousePressed(MouseEvent e) {x1 = e.getX();y1 = e.getY();}public void mouseDragged(MouseEvent e) {x2 = e.getX();y2 = e.getY();gD.setStroke(new BasicStroke(12));gD.setColor(Color.black);gD.drawLine(x1, y1, x2, y2);//将写入的数字转化为二维数组for(int i = 0;i<number_list.length;i++) {for(int j = 0;j<number_list.length;j++) {if(x2<i*size && x2>(i-1)*size) {if(y2<j*size && y2>(j-1)*size) {//记录鼠标走过的区域number_list[i][j] =1;}}}}x1 = x2;y1 = y2;}public void mouseReleased(MouseEvent e) {}}
}

数字0~9的手写识别相关推荐

  1. 手写体数字图像识别图像_手写识别调整笔画大小而不是图像

    手写体数字图像识别图像 A straightforward algorithm to dealing with handwritten symbol recognition problems in M ...

  2. 逻辑回归实现数字手写识别

    逻辑回归实现数字手写识别 我是用自己写的算法实现数字手写识别,采用的是Mnist的数据集,因为数据过多,所以我训练集取了600张,测试集取了100张 提取图片 因为mnist的数据集下载的是ubyte ...

  3. 数字手写识别——Java实现KNN算法

    引言 手写识别也是当前机器学习的一大热点,数字手写识别是手写识别中的基础,我们用到的是knn算法,今天给大家讲一下我的实现方法: 环境 IDE:Eclipse 语言:Java 项目:数字手写识别 思路 ...

  4. python简单代码演示效果-10分钟教你用python 30行代码搞定简单手写识别!

    欲直接下载代码文件,关注我们的公众号哦!查看历史消息即可! 手写笔记还是电子笔记好呢? 毕业季刚结束,眼瞅着2018级小萌新马上就要来了,老腊肉小编为了咱学弟学妹们的学习,绞尽脑汁准备编一套大学秘籍, ...

  5. AI应用开发实战 - 手写识别应用入门

    AI应用开发实战 - 手写识别应用入门 手写体识别的应用已经非常流行了,如输入法,图片中的文字识别等.但对于大多数开发人员来说,如何实现这样的一个应用,还是会感觉无从下手.本文从简单的MNIST训练出 ...

  6. AI应用开发实战系列之三:手写识别应用入门

    AI应用开发实战 - 手写识别应用入门 手写体识别的应用已经非常流行了,如输入法,图片中的文字识别等.但对于大多数开发人员来说,如何实现这样的一个应用,还是会感觉无从下手.本文从简单的MNIST训练出 ...

  7. 最终章 | TensorFlow战Kaggle“手写识别达成99%准确率

    刘颖,某互联网创业公司COO,技术出身,做产品里最懂运营的. 这是一个TensorFlow的系列文章,本文是第三篇,在这个系列中,你讲了解到机器学习的一些基本概念.TensorFlow的使用,并能实际 ...

  8. 用TensorFlow做Kaggle“手写识别”达到98%准确率-详解

    (点击"阅读原文"即可进入查看课程表) 刘颖,某互联网创业公司COO,技术出身,做产品里最懂运营的. 这是一个TensorFlow的系列文章,本文是第三篇,在这个系列中,你讲了解到 ...

  9. cnn神经网络可以用于数据拟合吗_使用Keras搭建卷积神经网络进行手写识别的入门(包含代码解读)...

    本文是发在Medium上的一篇博客:<Handwritten Equation Solver using Convolutional Neural Network>.本文是原文的翻译.这篇 ...

最新文章

  1. SQL Server 行列转换(2)
  2. socket PF_INET AF_INET 区别
  3. SharePoint 状态机工作流解决方案(一):为什么要用状态机
  4. 【ArcGIS风暴】ArcGIS10.6创建LAS数据集的两种方法并加载点云数据
  5. linux添加三权,基于SELinux的三权分离技术的研究
  6. QQ春节福袋正式上线 解锁春节红包新姿势
  7. 树莓派c语言实现modbus主机_特斯拉+树莓派实现车牌识别检测系统
  8. PartyUs 待添加内容(不定期更新)
  9. Messari前主管:一旦L2证明其实力,BSC上的团队将会迁移回以太坊
  10. 2013年国家计算机等级考试c语言考试真题,2013年3月计算机等级考试二级C语言真题及答案.doc...
  11. SharePoint开发中上传Excel问题 无法更新Microsoft Office文档
  12. c语言文件io的fork,15. C语言的fork
  13. 基于RV1126平台imx291分析 --- open及media graph分析
  14. 西门子plc语句表是c语言吗,三菱、西门子PLC常用语句表,速来收!
  15. 宝塔linux怎么运行war,宝塔Linux面板在线解压WAR压缩文件
  16. Python后端实现苹果ID登陆
  17. c语言输出10000以内的回文数,输出10000以内的素数、回文数、回文素数
  18. —— GPS测量原理及应用复习-7 ——
  19. Doom3 CVarSystem分析
  20. 《东周列国志》第二十一回 管夷吾智辨俞儿 齐桓公兵定孤竹

热门文章

  1. 《SQL Server 2008从入门到精通》--20180724
  2. 【雷达与对抗】【2017.06】空中目标的无源雷达探测
  3. Salesforce触发器面试题
  4. VMM验证方法学学习随笔
  5. win7如何设置通电自动开机_dell主板win10如何设置通电自动启动_dell主板win10怎么设置通电自动启动...
  6. 电商营销策略介绍,电商营销手段有哪些
  7. 电力系统非线性控制_第二届电气,控制,自动化和机器人国际学术会议 (ECAR2020)...
  8. 计算机老是跳出usb设备无法识别,电脑一直弹出无法识别的USB设备的解决办法
  9. 【源码】核磁共振成像的脑部肿瘤检测与分类
  10. 计算机网络相关知识总结