手写识别

作者:倪屁屁
链接:https://zhuanlan.zhihu.com/p/40431290
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

(1)KNN分类算法

KNN是通过测量不同特征值之间的距离进行分类。如果取样本的特征空间里K个相似对象向里占最多的类别,并把样本归入此类。

理解:通过计算样本与待计算对象之间的差距 dn(距离) 让样本以对象为中心开始排队,取以个最大半径K,在这个范围里,那一类的类占的比重大,就把待测对象标记为该类。

*有一点像soul交友软件,通过你的信息,在数据库里计算和你相似距离最小的用户,并且还会给你表明你们的相似度,然后把你也归入这一类星球里*

(2)KNN使用

将数据转化为可计算数据,并且储存到相应文件里。

(0)录入样本

(1) 录入带识别对象

(2) 计算样本数据和识别对象的距离;

(3)按照距离大小把对象存储到队列里

(4)取得K值计算K值内类别所占的最多类为最相似类别;

(5)将待识别样本标记为最相似类别

二--思路二

1.首先录取样本的数据,得到0-9这10个数字对应的数据类,着10个数字对应着你输入的数据,输入的数据越多越好

*1这里我用一个数组存“0-9”着是10个数字,想让数组对应的值为样本的个数,最开始都初始化为0,当你准备录入“0”的时候,就在文件夹里建立0的第1个样本,并且a[0]++;这样号访问到底有多少个“0”数据,也好到后期算距离;

2.读取样本数据----a[10]++;"待测量数据增多"

3. 用样本数据分别和 "0-9”着10个类里面存的样本算距离,取得平均距,并且当作样本与“0”到“9”着9个数字之间的差距,取最小距离mind ,以及对应最相似数字

4.将待测对象的类别修改为最相似类

我会调用一个方法,直接把待测对像的数据放到,相似数字的会便利的下一个数据,并且a[相似数字]++

public class MyUI extends JFrame {
	public Hashtable<Integer,String> ht=new Hashtable<Integer,String>();
	private int width = 400;
	private int height = 550;
	 MyCanvas canvas = null;
	private Graphics g;
	public JTextField number=null;
	public static void main(String[] args) throws AWTException {
		MyUI myui=new MyUI();
		
		}
	
	public MyUI()
	{
		super();
		this.setTitle("handwirting");
		this.setSize(width, height);
		this.setResizable(false);
		this.setLocation(400, 180);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setLayout(null);
		this.canvas = new MyCanvas(this);
		this.add(canvas);
		
		JPanel jp=new JPanel();
		jp.setBackground(Color.BLACK);
		jp.setSize(new Dimension(400,40 ));
		this.add(BorderLayout.EAST,jp);
		jp.setLayout(new FlowLayout());
		JButton b1=new JButton("练习");
		b1.addActionListener(canvas);
		JButton b2=new JButton("识别");
		b2.addActionListener(canvas);
		
		jp.add(b1);
		jp.add(b2);
		number=new JTextField(1);
		
		jp.add(number);
		this.setVisible(true);
		
		canvas.setG();
	
	}

}

首先会有这么一个界面,在输入框里写入要学习的数字(存储相应对象的数据1),这时候我会将这个黑色区域存下来,并且获取它的每一个点rgb因为是黑白的,所以就将白色设为1,黑色设为0,这几样就可以得到一串子,把他存到名字为“0-1”文件里代表“0”数字的第一组数据。

我会配合着输出存储情况

第一行代表计算机要学习“存储”的类别

第二行是当前对10个数组存储数据的情况,目前只学习了1所以[1]的长度就是1啦;

这里[10]用来代表待识别的对象。

这时候点击识别按钮,进行识别

这里就是输出

我这个版本就是有bug的

进行改进

(1)需要如果计算出来的差距特别大的时候,就直接选择废除这个数据,并且输出不能识别

(2)每一次启动程序都需要重新输入学习样本的数据,应该调用一个方法来实践设置数组的长度,在计算knn时候直接读取以前存取的数据。。。。。

//图片存储

public void wirte2jpg(int key) throws IOException {

		// TODO Auto-generated method stub
		Dimension imagesize = this.getSize();
		// 创建一个图形
		BufferedImage image = new BufferedImage(imagesize.width, imagesize.height, BufferedImage.TYPE_INT_RGB);
		Graphics graphics = image.createGraphics();
		this.paint(graphics);
		// 创建图片
		File f = new File("D:手写图片\" + key + "-" + (keylength[key]) + ".jpg");
		try {
			if (!f.exists()) {
				f.createNewFile();
				System.out.println(123);
			}
			// 存储一张手写图片
			ImageIO.write(image, "jpg", f);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		savepage(image, key);
		this.setBackground(Color.BLACK);
		
	}

//存储数据

	public void savepage(BufferedImage image, int key) throws IOException {
		int k = 0;
		// 存起来图像
		for (int i = image.getMinY(); i < image.getMinY() + height; i++) {
			for (int j = image.getMinX(); j < image.getMinX() + width; j++) {
				// 数组颜色
				int mycolor = image.getRGB(j, i);
				if (mycolor == -1) {
					Mydata[k] = 1;
					k++;
				} else {
					Mydata[k] = 0;
					k++;
				}
			}
		}

		// 创建文本本舰存数组
		File f = new File("D:数字\" + key + "-" + (keylength[key]) + ".txt");
		FileOutputStream out = null;
		try {
			out = new FileOutputStream(f);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		// 存入数据
		for (int q = 0; q < SIZE; q++) {
			try {
				out.write((byte) Mydata[q]);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

总结一下-这个项目我耗费最久的在IO流,以及数据存储上面,以及方法之间的调用布局,

方法与方法之间的调用关系,存储数据的读取上面。下一篇总结IO流以及异常。

原文地址:https://www.cnblogs.com/ttnrt/p/11086572.html