精华内容
下载资源
问答
  • opencv 数字识别详细教程

    万次阅读 多人点赞 2016-01-10 16:11:28
    最近要做数字识别这块,但是自己又完全不懂这个,网上搜资料搜了好多,但是都没找到完整代码。只有自己慢慢搞,下面写下自己的过程以及代码有不好的地方希望大神可以指出,大家相互交流下。有需要完整代码的可以留下...

     

    最近要做数字识别这块,但是自己又完全不懂这个,网上搜资料搜了好多,但是都没找到完整代码。只有自己慢慢搞,下面写下自己的过程以及代码有不好的地方希望大神可以指出,大家相互交流下。有需要完整代码的可以自行下载(源码里面 是需要自己做一个图片的,没有图片,不能直接运行)

     

    git 源码

     

    我是在VS2013 和opencv 2.4.9 环境下实现的。关于环境的搭建和配置以及软件的下载可以可以参考,http://blog.csdn.net/ltg01/article/details/50433386

    我要做的是把0123456789 印刷体数字识别出来。

    一、首先对图片进行预处理

    对图片进行灰度化二值化

     

            Mat src = imread("D:\\b.png", CV_LOAD_IMAGE_GRAYSCALE);//读取图片并进行灰度化处理
     	threshold(src, src, 100 , 255, CV_THRESH_BINARY);//二值化
    	imshow("origin", src);//显示图片
    

    原图经过灰度二值化的图

    Mat imread(const string& filename, int flags);

    filename:文件地址 flags:标志,读取什么样(灰度,彩色)图像hdrtype:传入的为载入什么类型(enum {LOAD_CVMAT=0,LOAD_IMAGE=1, LOAD_MAT=2 };这三个中的一个。) Mat :保存图像的Mat对象了。
    double threshold(InputArray src, OutputArray dst, double thresh, double maxval, int type) 
    参数信息:
    第一个参数,InputArray类型的src,输入数组,填单通道 , 8或32位浮点类型的Mat即可。
    第二个参数,OutputArray类型的dst,函数调用后的运算结果存在这里,即这个参数用于存放输出结果,且和第一个参数中的Mat变量有一样的尺寸和类型。
    第三个参数,double类型的thresh,阈值的具体值。
    第四个参数,double类型的maxval,当第五个参数阈值类型type取 THRESH_BINARY 或THRESH_BINARY_INV阈值类型时的最大值.
    第五个参数,int类型的type,阈值类型,。
    其它参数很好理解,我们来看看第五个参数,第五参数有以下几种类型
    0: THRESH_BINARY  当前点值大于阈值时,取Maxval,也就是第四个参数,下面再不说明,否则设置为0
    1: THRESH_BINARY_INV 当前点值大于阈值时,设置为0,否则设置为Maxval
    2: THRESH_TRUNC 当前点值大于阈值时,设置为阈值,否则不改变
    3: THRESH_TOZERO 当前点值大于阈值时,不改变,否则设置为0
    4: THRESH_TOZERO_INV  当前点值大于阈值时,设置为0,否则不改变

     

     

    二、对图片上的数字进行切割
     

       图片经过二值化后每个像素点的值只有1和0两种,在这里黑色部分的像素点的值为0白色字体部分的值为1.
    对图片

     

    先进行列扫描求每列的和。刚开始是都是黑色所以每列的和都是0,知道扫描到3的左边缘的那列的时候因为有白色所以这列的和大于0,这时候记下当前位置left,然后接着扫描,接下来每列的和都大于0,直到3的右边缘时候这列和右等于0,记下当前位置right,则right减去left则是3的宽度,高度仍为原图的高度,这样通过函数

     

            int width = right - left;
    	Rect rect(left, 0, width, src.rows);
    	leftImg = src(rect);
    

     

    就可以把3截取出来了,如图

    但是3的上下部分没有截取,同样对图片进行行扫描,截取上下部分,如下图

    就这样循环截取图片就可以吧其他数字截取下来了,但是每次截取的原图是不一样的,第二次截取的时候原图上就没有3 是从6开始的如图

     

    int cutLeft(Mat& src, Mat& leftImg, Mat& rightImg)//左右切割
    {
    	int left, right;
    	left = 0;
    	right = src.cols;
    
    	int i;
    	for (i = 0; i < src.cols; i++)
    	{
    		int colValue = getColSum(src, i);
    		//cout <<i<<" th "<< colValue << endl;
    		if (colValue>0)
    		{
    			left = i;
    			break;
    		}
    	}
    	if (left == 0)
    	{
    		return 1;
    	}
    
    
    	for (; i < src.cols; i++)
    	{
    		int colValue = getColSum(src, i);
    		//cout << i << " th " << colValue << endl;
    		if (colValue == 0)
    		{
    			right = i;
    			break;
    		}
    	}
    	int width = right - left;
    	Rect rect(left, 0, width, src.rows);
    	leftImg = src(rect).clone();
    	Rect rectRight(right, 0, src.cols - right, src.rows);
    	rightImg = src(rectRight).clone();
    	cutTop(leftImg, leftImg);
    	return 0;
    }
    
    void cutTop(Mat& src, Mat& dstImg)//上下切割
    {
    	int top, bottom;
    	top = 0;
    	bottom = src.rows;
    
    	int i;
    	for (i = 0; i < src.rows; i++)
    	{
    		int colValue = getRowSum(src, i);
    		//cout <<i<<" th "<< colValue << endl;
    		if (colValue>0)
    		{
    			top = i;
    			break;
    		}
    	}
    	for (; i < src.rows; i++)
    	{
    		int colValue = getRowSum(src, i);
    		//cout << i << " th " << colValue << endl;
    		if (colValue == 0)
    		{
    			bottom = i;
    			break;
    		}
    	}
    
    	int height = bottom - top;
    	Rect rect(0, top, src.cols, height);
    	dstImg = src(rect).clone();
    }
    int main()
    {
    	Mat src = imread("D:\\s.png", CV_LOAD_IMAGE_GRAYSCALE);
    	threshold(src, src, 100 , 255, CV_THRESH_BINARY_INV);
    	imshow("origin", src);
    
    	Mat leftImg,rightImg;
    	int res = cutLeft(src, leftImg, rightImg);	
    	int i = 0; 
    	while (res == 0)
    	{ 		
    		char nameLeft[10];
    		sprintf(nameLeft, "%dLeft", i);
    		char nameRight[10];
    		sprintf(nameRight, "%dRight", i);
    		i++;
            //stringstream ss;
           //ss << nameLeft;
            //imwrite("D:\\" + ss.str() + ".jpg", leftImg);
            //ss >> nameLeft;
            Mat srcTmp = rightImg;
            //getSubtract(leftImg, 10);
    		res = cutLeft(srcTmp, leftImg, rightImg);	
    	}
    	
    	waitKey(0);
    	return 0;
    }


    最后截取结果如下图

     

     

    (截取的很清楚只是拖动的时候留下的划痕)

     

    三、制作模板

     

     

    模板的制作和步骤二完全一样,首先你要切割的图片的字体样式和大小要和模板的样式和大小一样(比如都是宋体,10号)要不然匹配的结果就不准确,而且把0123456789最好按顺序这样匹配的时候可以知道是匹配到那个数字,比如你切割下的数字和模板匹配的时候,匹配到第三个模板则知道是匹配的数字3(模板从第0个开始)。只需要改主函数

     

     

     

    int main()
    {
    	Mat src = imread("D:\\s.png", CV_LOAD_IMAGE_GRAYSCALE);
    	threshold(src, src, 100 , 255, CV_THRESH_BINARY_INV);
    	imshow("origin", src);
    
    	Mat leftImg,rightImg;
    	int res = cutLeft(src, leftImg, rightImg);	
    	int i = 0; 
    	while (res == 0)
    	{ 		
    		char nameLeft[10];
    		sprintf(nameLeft, "%dLeft", i);
    		char nameRight[10];
    		sprintf(nameRight, "%dRight", i);
    		i++;
    		imshow(nameLeft, leftImg);
    		<strong>stringstream ss;
    		ss << nameLeft;
    		imwrite("D:\\" + ss.str() + ".jpg", leftImg);//保存截取图片做为模板
    		ss >> nameLeft;</strong>
    		Mat srcTmp = rightImg;
    		//getSubtract(leftImg, 10);
    		res = cutLeft(srcTmp, leftImg, rightImg);	
    	}
    	
    	waitKey(0);
    	return 0;
    }
    


    四、数字识别

     

     

     

     

     

     

     

    把你切割的数字图片大小调整到和模板一样的大小,然后让需要匹配的图和分别和10个模板相减,(让两个图片对应像素点值相减)然后求返回图片的整个图片的像素点值得平方和,和哪个模板匹配时候返回图片的平方和最小则就可以得到结果。只需要改主函数

     

     

    void getPXSum(Mat &src, int &a)//获取所有像素点和
    { 
    	threshold(src, src, 100, 255, CV_THRESH_BINARY);
    	  a = 0;
    	for (int i = 0; i < src.rows;i++)
    	{
    		for (int j = 0; j < src.cols; j++)
    		{
    			a += src.at <uchar>(i, j);
    		}
    	}
    }
    
    int  getSubtract(Mat &src, int TemplateNum) //两张图片相减
    {
    	Mat img_result;
    	int min = 1000000;
    	int serieNum = 0;
    	for (int i = 0; i < TemplateNum; i++){
    		char name[20];
    		sprintf_s(name, "D:\\%dLeft.jpg", i);
    		Mat Template = imread(name, CV_LOAD_IMAGE_GRAYSCALE);
    		threshold(Template, Template, 100, 255, CV_THRESH_BINARY);
    		threshold(src, src, 100, 255, CV_THRESH_BINARY);
    		resize(src, src, Size(32, 48), 0, 0, CV_INTER_LINEAR);
    	    resize(Template, Template, Size(32, 48), 0, 0, CV_INTER_LINEAR);//调整尺寸		
    		//imshow(name, Template);
    		absdiff(Template, src, img_result);//
    		getPXSum(img_result, diff);
    		if (diff < min)
    		{
    			min = diff;
    			serieNum = i;
    		}
    	}
    	printf("最小距离是%d ", min);
    	printf("匹配到第%d个模板匹配的数字是%d\n", serieNum,serieNum);
    	return serieNum;
    }
    
    int main()
    {
    	Mat src = imread("D:\\s.png", CV_LOAD_IMAGE_GRAYSCALE);
    	threshold(src, src, 100 , 255, CV_THRESH_BINARY_INV);
    	imshow("origin", src);
    
    	Mat leftImg,rightImg;
    	int res = cutLeft(src, leftImg, rightImg);	
    	int i = 0; 
    	while (res == 0)
    	{ 		
    	//	char nameLeft[10];
    	//	sprintf(nameLeft, "%dLeft", i);
    	//	char nameRight[10];
    	//	sprintf(nameRight, "%dRight", i);
    	//	i++;
    		imshow(nameLeft, leftImg);
    	//	stringstream ss;
    	//	ss << nameLeft;
    	//	imwrite("D:\\" + ss.str() + ".jpg", leftImg);
    	//	ss >> nameLeft;
    		Mat srcTmp = rightImg;
    		getSubtract(leftImg, 10);//数字识别
    		res = cutLeft(srcTmp, leftImg, rightImg);	
    	}
    	
    	waitKey(0);
    	return 0;
    }

     

     

     

     

     

    运行最终结果如下图

     

    
     

     

    
     
    
     
    
     
    
     
    
     
     
    
     
    
     
     
    
     
    
     
     
    
     
    
     
     
    
     
    
     
     
    
     
    
     
    展开全文
  • Python(TensorFlow框架)实现手写数字识别系统

    万次阅读 多人点赞 2019-07-31 11:27:55
    本文使用Tensorflow框架进行Python编程实现基于卷积神经网络的手写数字识别算法,并将其封装在一个GUI界面中,最终,设计并实现了一个手写数字识别系统。

    手写数字识别算法的设计与实现

    本文使用python基于TensorFlow设计手写数字识别算法,并编程实现GUI界面,构建手写数字识别系统。这是本人的本科毕业论文课题,当然,这个也是机器学习的基本问题。本博文不会以论文的形式展现,而是以编程实战完成机器学习项目的角度去描述。


    项目要求:本文主要解决的问题是手写数字识别,最终要完成一个识别系统。

    设计识别率高的算法,实现快速识别的系统。

    1 LeNet-5模型的介绍

    本文实现手写数字识别,使用的是卷积神经网络,建模思想来自LeNet-5,如下图所示:
    在这里插入图片描述
    这是原始的应用于手写数字识别的网络,我认为这也是最简单的深度网络。

    LeNet-5不包括输入,一共7层,较低层由卷积层和最大池化层交替构成,更高层则是全连接和高斯连接。

    LeNet-5的输入与BP神经网路的不一样。这里假设图像是黑白的,那么LeNet-5的输入是一个32*32的二维矩阵。同时,输入与下一层并不是全连接的,而是进行稀疏连接。本层每个神经元的输入来自于前一层神经元的局部区域(5×5),卷积核对原始图像卷积的结果加上相应的阈值,得出的结果再经过激活函数处理,输出即形成卷积层(C层)。卷积层中的每个特征映射都各自共享权重和阈值,这样能大大减少训练开销。降采样层(S层)为减少数据量同时保存有用信息,进行亚抽样。

    第一个卷积层(C1层)由6个特征映射构成,每个特征映射是一个28×28的神经元阵列,其中每个神经元负责从5×5的区域通过卷积滤波器提取局部特征。一般情况下,滤波器数量越多,就会得出越多的特征映射,反映越多的原始图像的特征。本层训练参数共6×(5×5+1)=156个,每个像素点都是由上层5×5=25个像素点和1个阈值连接计算所得,共28×28×156=122304个连接。

    S2层是对应上述6个特征映射的降采样层(pooling层)。pooling层的实现方法有两种,分别是max-pooling和mean-pooling,LeNet-5采用的是mean-pooling,即取n×n区域内像素的均值。C1通过2×2的窗口区域像素求均值再加上本层的阈值,然后经过激活函数的处理,得到S2层。pooling的实现,在保存图片信息的基础上,减少了权重参数,降低了计算成本,还能控制过拟合。本层学习参数共有1*6+6=12个,S2中的每个像素都与C1层中的2×2个像素和1个阈值相连,共6×(2×2+1)×14×14=5880个连接。

    S2层和C3层的连接比较复杂。C3卷积层是由16个大小为10×10的特征映射组成的,当中的每个特征映射与S2层的若干个特征映射的局部感受野(大小为5×5)相连。其中,前6个特征映射与S2层连续3个特征映射相连,后面接着的6个映射与S2层的连续的4个特征映射相连,然后的3个特征映射与S2层不连续的4个特征映射相连,最后一个映射与S2层的所有特征映射相连。此处卷积核大小为5×5,所以学习参数共有6×(3×5×5+1)+9×(4×5×5+1)+1×(6×5×5+1)=1516个参数。而图像大小为28×28,因此共有151600个连接。

    S4层是对C3层进行的降采样,与S2同理,学习参数有16×1+16=32个,同时共有16×(2×2+1)×5×5=2000个连接。

    C5层是由120个大小为1×1的特征映射组成的卷积层,而且S4层与C5层是全连接的,因此学习参数总个数为120×(16×25+1)=48120个。

    F6是与C5全连接的84个神经元,所以共有84×(120+1)=10164个学习参数。

    卷积神经网络通过通过稀疏连接和共享权重和阈值,大大减少了计算的开销,同时,pooling的实现,一定程度上减少了过拟合问题的出现,非常适合用于图像的处理和识别。

    2 手写数字识别算法模型的构建

    2.1 各层设计

    有了第一节的基础知识,在这基础上,进行完善和改进。

    输入层设计

    输入为28×28的矩阵,而不是向量。

    激活函数的选取

    Sigmoid函数具有光滑性、鲁棒性和其导数可用自身表示的优点,但其运算涉及指数运算,反向传播求误差梯度时,求导又涉及乘除运算,计算量相对较大。同时,针对本文构建的含有两层卷积层和降采样层,由于sgmoid函数自身的特性,在反向传播时,很容易出现梯度消失的情况,从而难以完成网络的训练。因此,本文设计的网络使用ReLU函数作为激活函数。

    ReLU的表达式:
    在这里插入图片描述

    卷积层设计

    本文设计卷积神经网络采取的是离散卷积,卷积步长为1,即水平和垂直方向每次运算完,移动一个像素。卷积核大小为5×5。

    降采样层

    本文降采样层的pooling方式是max-pooling,大小为2×2。

    输出层设计

    输出层设置为10个神经网络节点。数字0~9的目标向量如下表所示:
    在这里插入图片描述

    2.2 网络模型的总体结构

    在这里插入图片描述
    其实,本文网络的构建,参考自TensorFlow的手写数字识别的官方教程的,读者有兴趣也可以详细阅读。

    2.3 编程实现算法

    本文使用Python,调用TensorFlow的api完成手写数字识别的算法。
    注:本文程序运行环境是:Win10,python3.5.2。当然,也可以在Linux下运行,由于TensorFlow对py2和py3兼容得比较好,在Linux下可以在python2.7中运行。

    #!/usr/bin/env python2
    # -*- coding: utf-8 -*-
    """
    Created on Fri Feb 17 19:50:49 2017
    
    @author: Yonghao Huang
    """
    
    #import modules
    import numpy as np
    import matplotlib.pyplot as plt
    import tensorflow as tf
    import time
    from datetime import timedelta
    import math
    from tensorflow.examples.tutorials.mnist import input_data
    
    
    def new_weights(shape):
        return tf.Variable(tf.truncated_normal(shape,stddev=0.05))
    def new_biases(length):
        return tf.Variable(tf.constant(0.1,shape=length))
    def conv2d(x,W):
        return tf.nn.conv2d(x,W,strides=[1,1,1,1],padding='SAME')
    def max_pool_2x2(inputx):
        return tf.nn.max_pool(inputx,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
    
    #import data
    data = input_data.read_data_sets("./data", one_hot=True)  # one_hot means [0 0 1 0 0 0 0 0 0 0] stands for 2
    
    print("Size of:")
    print("--Training-set:\t\t{}".format(len(data.train.labels)))
    print("--Testing-set:\t\t{}".format(len(data.test.labels)))
    print("--Validation-set:\t\t{}".format(len(data.validation.labels)))
    data.test.cls = np.argmax(data.test.labels,axis=1)   # show the real test labels:  [7 2 1 ..., 4 5 6], 10000values
    
    x = tf.placeholder("float",shape=[None,784],name='x')
    x_image = tf.reshape(x,[-1,28,28,1])
    
    y_true = tf.placeholder("float",shape=[None,10],name='y_true')
    y_true_cls = tf.argmax(y_true,dimension=1)
    # Conv 1
    layer_conv1 = {"weights":new_weights([5,5,1,32]),
                   "biases":new_biases([32])}
    h_conv1 = tf.nn.relu(conv2d(x_image,layer_conv1["weights"])+layer_conv1["biases"])
    h_pool1 = max_pool_2x2(h_conv1)
    # Conv 2
    layer_conv2 = {"weights":new_weights([5,5,32,64]),
                   "biases":new_biases([64])}
    h_conv2 = tf.nn.relu(conv2d(h_pool1,layer_conv2["weights"])+layer_conv2["biases"])
    h_pool2 = max_pool_2x2(h_conv2)
    # Full-connected layer 1
    fc1_layer = {"weights":new_weights([7*7*64,1024]),
                "biases":new_biases([1024])}
    h_pool2_flat = tf.reshape(h_pool2,[-1,7*7*64])
    h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat,fc1_layer["weights"])+fc1_layer["biases"])
    # Droupout Layer
    keep_prob = tf.placeholder("float")
    h_fc1_drop = tf.nn.dropout(h_fc1,keep_prob)
    # Full-connected layer 2
    fc2_layer = {"weights":new_weights([1024,10]),
                 "biases":new_weights([10])}
    # Predicted class
    y_pred = tf.nn.softmax(tf.matmul(h_fc1_drop,fc2_layer["weights"])+fc2_layer["biases"])  # The output is like [0 0 1 0 0 0 0 0 0 0]
    y_pred_cls = tf.argmax(y_pred,dimension=1)  # Show the real predict number like '2'
    # cost function to be optimized
    cross_entropy = -tf.reduce_mean(y_true*tf.log(y_pred))
    optimizer = tf.train.AdamOptimizer(learning_rate=1e-4).minimize(cross_entropy)
    # Performance Measures
    correct_prediction = tf.equal(y_pred_cls,y_true_cls)
    accuracy = tf.reduce_mean(tf.cast(correct_prediction,"float"))
    with tf.Session() as sess:
        init = tf.global_variables_initializer()
        sess.run(init)
        train_batch_size = 50
        def optimize(num_iterations):
            total_iterations=0
            start_time = time.time()
            for i in range(total_iterations,total_iterations+num_iterations):
                x_batch,y_true_batch = data.train.next_batch(train_batch_size)
                feed_dict_train_op = {x:x_batch,y_true:y_true_batch,keep_prob:0.5}
                feed_dict_train = {x:x_batch,y_true:y_true_batch,keep_prob:1.0}
                sess.run(optimizer,feed_dict=feed_dict_train_op)
                # Print status every 100 iterations.
                if i%100==0:
                    # Calculate the accuracy on the training-set.
                    acc = sess.run(accuracy,feed_dict=feed_dict_train)
                    # Message for printing.
                    msg = "Optimization Iteration:{0:>6}, Training Accuracy: {1:>6.1%}"
                    # Print it.
                    print(msg.format(i+1,acc))
            # Update the total number of iterations performed
            total_iterations += num_iterations
            # Ending time
            end_time = time.time()
            # Difference between start and end_times.
            time_dif = end_time-start_time
            # Print the time-usage
            print("Time usage:"+str(timedelta(seconds=int(round(time_dif)))))
        test_batch_size = 256
        def print_test_accuracy():
            # Number of images in the test-set.
            num_test = len(data.test.images)
            cls_pred = np.zeros(shape=num_test,dtype=np.int)
            i = 0
            while i < num_test:
                # The ending index for the next batch is denoted j.
                j = min(i+test_batch_size,num_test)
                # Get the images from the test-set between index i and j
                images = data.test.images[i:j, :]
                # Get the associated labels
                labels = data.test.labels[i:j, :]
                # Create a feed-dict with these images and labels.
                feed_dict={x:images,y_true:labels,keep_prob:1.0}
                # Calculate the predicted class using Tensorflow.
                cls_pred[i:j] = sess.run(y_pred_cls,feed_dict=feed_dict)
                # Set the start-index for the next batch to the
                # end-index of the current batch
                i = j
            cls_true = data.test.cls
            correct = (cls_true==cls_pred)
            correct_sum = correct.sum()
            acc = float(correct_sum) / num_test
            # Print the accuracy
            msg = "Accuracy on Test-Set: {0:.1%} ({1}/{2})"
            print(msg.format(acc,correct_sum,num_test))
        # Performance after 10000 optimization iterations
        
        
        
    

    运行结果显示:测试集中准确率大概为99.2%。
    我还写了一些辅助函数,可以查看部分识别错误的图片,
    在这里插入图片描述
    还可以查看混淆矩阵,
    在这里插入图片描述

    2.3 实现手写识别系统

    最后,将训练好的参数保存,封装进一个GUI界面中,形成一个手写识别系统。
    在这里插入图片描述
    系统中还添加了一点图像预处理的操作,比如灰度化,图像信息的归一化等,更贴近实际应用。
    系统可进行快速识别,如下图:
    在这里插入图片描述

    3 总结

    本文实现的系统其实是基于卷积神经网络的手写数字识别系统。该系统能快速实现手写数字识别,成功识别率高。缺点:只能正确识别单个数字,图像预处理还不够,没有进行图像分割,读者也可以自行添加,进行完善。

    4 收获

    本人之前的本科期间,虽然努力学习高数、线性代数和概率论,但是没有认真学习过机器学习,本人是2017年才开始系统学习机器学习相关知识,而且本科毕业论文也选择了相关的课题,虽然比较基础,但是认真完成后,有一种学以致用的满足感,同时也激励着我进行更深入的理论学习和实践探讨,与所有读者共勉。

    ==================================

    2018年5月13日更新

    以上是基本网络的设计与基本的实现,可满足入门学习。

    相关链接:


    ========================================

    2018年6月6日更新更新!!

    python(TensorFlow)实现手写字符识别


    此处的“手写字符”,其实指的是notMNIST数据库中的手写字符,其实和MNIST数据库是一样的。这里实现手写字符识别,主要是展示TensorFlow框架的可拓展性很强,具体来说,就是可以通过改动少部分的代码,从而实现一个新的识别功能。

    NotMnist数据库

    这个数据库和MNIST数据库基本一样,只是把10个数字换成了10个字母,即:A,B,C,D,E,F,G,H,I,J,K
    当然,这个数据库的识别难度大一些,因为数据噪声更多一些,详情读者可以搜一搜了解一下。

    实战

    将NotMNIST数据库下载以后,放在本博文上述的网络中,基本不需要修改代码,直接训练,即可得到一个能识别字符的网络模型。

    最后在测试集中的准确率,比MNIST的会低一些,大概为96%左右。

    本文也将训练好的网络模型封装在和上述系统相似的GUI系统中,

    [外链图片转存失败(img-k7xPyAio-1564543116627)(https://i.imgur.com/59M3NlD.png)]

    识别效果还可以!

    同样,将卷积卷积层可视化。

    [外链图片转存失败(img-tIWWgZB9-1564543116629)(https://i.imgur.com/4awe7NY.png)]

    结语

    TensorFlow框架可拓展性很强,只要设计好了网络,就能很容易的实现出来;同时,使用基本的CNN识别整体架构也是大同小异的,很多识别任务是通用的。当然,在具体的实践中需要得到接近完美的效果,还是要下很大功夫的!努力学习吧,加油!
    (如果你/您有什么有趣的想法,可以在下面留言,如果我也感兴趣同时又有时间的话,我会尝试做一做,_

    展开全文
  • 手写数字识别

    千人学习 2017-06-28 20:34:23
    手写数字识别,使用简化后的近邻算法实现手写数字识别
  • matlab手写体数字识别

    千人学习 2019-10-09 09:35:59
    matlab手写体数字识别
  • 数字图像字符识别——数字识别

    万次阅读 多人点赞 2018-04-19 15:14:02
    本文简单介绍图片字符识别的原理,主要识别图片中的数字,其他字符识别原理类似。大家应该知道,对于人类来说,可以很容易理解一张图片所表达的信息,这是人类视觉系统数万年演变进化的结果。但对于计算机这个诞生...

    本文简单介绍图片字符识别的原理,主要识别图片中的数字,其他字符识别原理类似。

    大家应该知道,对于人类来说,可以很容易理解一张图片所表达的信息,这是人类视觉系统数万年演变进化的结果。但对于计算机这个诞生进化不到百年的 “新星”,要让它理解一张图像上的信息是一个复杂的过程。计算机理解图像是一个数字计算比较的过程。

    如图,我们一目了然的识别的图像中的数字,如何让计算机识别下图中的数字呢?

     

    环境:VS2015+openCV3.4.0

    要识别图像字符,首先需要模版库。对于识别简单字符,可自己训练,也可网上下载数据集。笔者这里就直接用提前做好的(用photoshop制作,字体和字大小尽量和待识别字符相近,不然影响识别率),为便于识别,模版名就以数字命名。

     

    1. 图片预处理。首先读取待识别图像,灰度化、二值化。

    Mat srcImg = imread("H:\\test.jpg",CV_LOAD_IMAGE_GRAYSCALE);//打开图片

    灰度后图像:

     

    threshold(srcImg, srcImg, threshVal, 255, CV_THRESH_BINARY);//二值化

    我们知道图像本身就以数字进行存储的,二值化后图像就只有两个值0和255.

    例数字0:

                    

    注意二值化的阈值根据图像实际情况进行调整。

    二值化图像后:

     

    2. 图像分割。我们需要将图像中的字符分割开。整个过程分两部,左右分割和上下分割。基本思想是,从图像的左上角第一列开始,从左往右逐列扫描扫描,当遇到像素值为0时,记录该列号sCol,继续扫描再遇到整列像素值为255时,记录列号eCol,sCol与eCol之间即为字符所在区间。复制二值图该区域,这样完成了左右分割;

     

    将左右分割后,在此基础上再对图像进行上下分割,同理,从图像左上角第一行,向下逐行扫描,当遇到像素值为255时,记录该列号sRow,继续扫描再遇到整列像素值为0时,记录列号eRow,sRow与eRow之间即为字符所在区间。复制该区域,这样完成了上下左右分割。

     

     

    3. 识别。把切割后的数字图片大小调整到和模板一样的大小(一般以模版中最大尺寸),然后让需要匹配的图和别和10个模板相减(让两个图片对应坐标像素点值相减),将所有差的绝对值求和 。

    最后与哪个模板匹配时绝对值和最小,则就可以得到图像与该模版最匹配,进而识别该字符。

    4. 结果。

     

    展开全文
  • TensorFlow实战教程,该课程主要分享两个TensorFlow卷积神经网络实战的案例,第一个是手写数字识别案例,第二个是人脸识别案例。
  • Tensorflow 实现 MNIST 手写数字识别

    万次阅读 热门讨论 2017-04-09 16:05:52
    本节笔记作为 Tensorflow 的 Hello World,用 MNIST 手写数字识别来探索 Tensorflow。笔记的内容来自 Tensorflow 中文社区和黄文坚的《Tensorflow 实战》,只作为自己复习总结。

    本节笔记作为 Tensorflow 的 Hello World,用 MNIST 手写数字识别来探索 Tensorflow。笔记的内容来自 Tensorflow 中文社区和黄文坚的《Tensorflow 实战》,只作为自己复习总结。

    环境:

    • Windows 10
    • Anaconda 4.3.0
    • Spyder

    本节笔记主要采用 Softmax Regression 算法,构建一个没有隐层的神经网络来实现 MNIST 手写数字识别。

    1. MNIST 数据集加载

    MNIST 数据集可以从MNIST官网下载。也可以通过 Tensorflow 提供的 input_data.py进行载入。

    由于上述方法下载数据集比较慢,我已经把下载好的数据集上传到CSDN资源中,可以直接下载。

    将下载好的数据集放到目录C:/Users/Administrator/.spyder-py3/MNIST_data/下。目录可以根据自己的喜好变换,只是代码中随之改变即可。

    通过运行Tensorflow 提供的代码加载数据集:

    from tensorflow.examples.tutorials.mnist import input_data
    
    # 获取数据
    mnist = input_data.read_data_sets("C:/Users/Administrator/.spyder-py3/MNIST_data/", one_hot=True)
    

    MNIST数据集包含55000样本的训练集,5000样本的验证集,10000样本的测试集。 input_data.py 已经将下载好的数据集解压、重构图片和标签数据来组成新的数据集对象。

    图像是28像素x28像素大小的灰度图片。空白部分全部为0,有笔迹的地方根据颜色深浅有0~1的取值,因此,每个样本有28x28=784维的特征,相当于展开为1维。

    这里写图片描述

    所以,训练集的特征是一个 55000x784 的 Tensor,第一纬度是图片编号,第二维度是图像像素点编号。而训练集的 Label(图片代表的是0~9中哪个数)是一个 55000x10 的 Tensor,10是10个种类的意思,进行 one-hot 编码 即只有一个值为1,其余为0,如数字0,对于 label 为[1,0,0,0,0,0,0,0,0,0]。

    这里写图片描述

    这里写图片描述

    2. Softmax Regression 算法

    数字都是0~9之间的,一共有10个类别,当对图片进行预测时,Softmax Regression 会对每一种类别估算一个概率,并将概率最大的那个数字作为结果输出。

    Softmax Regression 将可以判定为某类的特征相加,然后将这些特征转化为判定是这一个类的概率。我们对图片的所以像素求一个加权和。如某个像素的灰度值大代表很有可能是数字n,这个像素权重就很大,反之,这个权重很有可能为负值。

    特征公式:

    这里写图片描述

    bib_ibi 为偏置值,就是这个数据本身的一些倾向。

    然后用 softmax 函数把这些特征转换成概率 yyy :

    这里写图片描述

    对所有特征计算 softmax,并进行标准化(所有类别输出的概率值和为1):

    这里写图片描述

    判定为第 i 类的概率为:

    这里写图片描述

    Softmax Regression 流程如下:

    这里写图片描述

    转换为矩阵乘法:

    这里写图片描述

    这里写图片描述

    写成公式如下:

    这里写图片描述

    3.实现模型

    import tensorflow as tf
    sess = tf.InteractiveSession()
    x = tf.placeholder(tf.float32, [None, 784])
    W = tf.Variable(tf.zeros([784,10]))
    b = tf.Variable(tf.zeros([10]))
    y = tf.nn.softmax(tf.matmul(x,W) + b)
    

    首先载入 Tensorflow 库,并创建一个新的 InteractiveSession ,之后的运算默认在这个 session 中。

    • placeholder:输入数据的地方,None 代表不限条数的输入,每条是784维的向量
    • Variable:存储模型参数,持久化的

    4.训练模型

    我们定义一个 loss 函数来描述模型对问题的分类精度。 Loss 越小,模型越精确。这里采用交叉熵:

    这里写图片描述
    其中,y 是我们预测的概率分布, y’ 是实际的分布。

    y_ = tf.placeholder(tf.float32, [None,10])
    cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y),reduction_indices=[1]))
    

    定义一个 placeholder 用于输入正确值,并计算交叉熵。

    接着采用随机梯度下降法,步长为0.5进行训练。

    train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)
    

    训练模型,让模型循环训练1000次,每次随机从训练集去100条样本,以提高收敛速度。

    for i in range(1000):
      batch_xs, batch_ys = mnist.train.next_batch(100)
      train_step.run({x: batch_xs, y_: batch_ys})
    

    5.评估模型

    我们通过判断实际值和预测值是否相同来评估模型,并计算准确率,准确率越高,分类越精确。

    这里写图片描述

    6.总结

    实现的整个流程:

    1. 定义算法公式,也就是神经网络前向传播时的计算。
    2. 定义 loss ,选定优化器,并指定优化器优化 loss。
    3. 迭代地对数据进行训练。
    4. 在测试集或验证集上对准确率进行评测。

    7.全部代码

    import tensorflow as tf
    
    from tensorflow.examples.tutorials.mnist import input_data
    
    # 获取数据
    mnist = input_data.read_data_sets("C:/Users/Administrator/.spyder-py3/MNIST_data/", one_hot=True)
    
    print('训练集信息:')
    print(mnist.train.images.shape,mnist.train.labels.shape)
    print('测试集信息:')
    print(mnist.test.images.shape,mnist.test.labels.shape)
    print('验证集信息:')
    print(mnist.validation.images.shape,mnist.validation.labels.shape)
    
    # 构建图
    sess = tf.InteractiveSession()
    x = tf.placeholder(tf.float32, [None, 784])
    W = tf.Variable(tf.zeros([784,10]))
    b = tf.Variable(tf.zeros([10]))
    
    y = tf.nn.softmax(tf.matmul(x,W) + b)
    
    y_ = tf.placeholder(tf.float32, [None,10])
    cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y),reduction_indices=[1]))
    train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)
    
    # 进行训练
    tf.global_variables_initializer().run()
    
    for i in range(1000):
      batch_xs, batch_ys = mnist.train.next_batch(100)
      train_step.run({x: batch_xs, y_: batch_ys})
    
    # 模型评估
    correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
    
    print('MNIST手写图片准确率:')
    print(accuracy.eval({x: mnist.test.images, y_: mnist.test.labels}))
    
    展开全文
  • 特征匹配实现印刷体数字识别,卷积神经网络实现印刷体数字识别(很可靠) 1.印刷体数字识别(特征匹配) 1.首先需要了解为什么印刷体数字识别我使用的是特征匹配的方法,我起初也走了很多的坑,当初固执的识别印刷体...
  • Python+Opencv实现数字识别

    万次阅读 多人点赞 2019-06-04 11:10:23
    目录一、什么是数字识别?二、如何实现数字识别?三、识别LCD屏幕上面的数字的原理详解四、算法实现步骤五、算法代码实现六、效果展示和分析七、问题扩展与延伸参考资料注意事项 一、什么是数字识别?   所谓的...
  • opencv数字识别

    千次阅读 2017-10-24 21:18:26
    这是基于opencv写的数字识别程序 对于记事本里的宋体常规数字能够完美的识别 思路: 放大图片→灰度化→二值化→开运算→寻找外轮廓→轮廓排序→遍历像素与模板匹配→得到数字 最后为了验证识别率,读入txt文件与...
  • MNIST 手写数字识别(一)

    万次阅读 多人点赞 2018-11-07 21:43:33
    MNIST 手写数字识别模型建立与优化 本篇的主要内容有: TensorFlow 处理MNIST数据集的基本操作 建立一个基础的识别模型 介绍 SoftmaxSoftmaxSoftmax回归以及交叉熵等 MNIST是一个很有名的手写数字识别数据集(基本...
  • 1联机手写数字识别设计一、设计论述模式识别是六十年代初迅速发展起来的一门学科。由于它研究的是如何用机器来实现人(及某些动物)对事物的学习、识别和判断能力,因而受到了很多科技领域研究人员的注意,成为人工...
  • 手写数字识别问题实战

    千次阅读 2020-04-02 11:04:46
    1、何为手写数字识别问题? 手写数字识别即将如下图所示的各种各样的手写体阿拉伯数字识别出来的一个过程,这个问题已经被研究的很成熟了,也有人搜集和整理了手写数字的数据集-mnist。 2、如何解决手写数字...
  • 实时手写数字识别

    千次阅读 热门讨论 2018-05-10 14:49:38
    手写数字识别作为模式识别领域的一个重要问题,也有着重要的理论价值,在大数据时代的背景下,其应用领域非常之广。很多学者对手写数字识别提出了不同的算法,取得了不错的测试效果,但如今OCR领域大部分还在算法...
  • 手写数字识别是一个经典的机器学习问题,通过识别手写体图片来判断数字 因为数字类别是0——9,所以是十分类问题 本文以KNN算法为例,来实现手写数字的识别 文章目录实现简单的手写数字识别关于load_digits简介调用...
  • 基于opencv的数字识别

    万次阅读 多人点赞 2018-09-12 15:44:29
    最近学习了opencv,然后想通过其对图片上的数字进行识别,参考了网上几篇关于opencv数字识别的博客,我自己也写了一个程序玩玩。我是在vs2017和opencv3.4.1环境下实现的。  这里先说一下我的思路和步骤: 加载...
  • 手写数字识别mnist测试集上正确率很高,自己用画图软件写的数字为什么识别很差
  • 基于SVM技术的手写数字识别

    千次阅读 多人点赞 2019-07-29 22:51:39
    你没有看错,又是手写数字识别,就是喜欢这个手写数字识别,没办法(¬∀¬)σ 一、背景 1.手写数字识别技术的含义 2.手写数字识别技术的理论价值 3.数字识别技术的难点 二、SVM技术 1.SVM方法简介 2.线性可...
  • 源代码下载: 图片识别 Gui界面 画板数字识别
  • 基于FPGA的数字识别

    千次阅读 2018-07-31 09:46:52
    基于FPGA的数字识别三 作者:OpenS_Lee 1 背景知识 在《基于FPGA数字识别一》我们在三种数字识别方法中选择了数字特征识别算法,完成了屏幕固定位置的数字识别。例如图1所示,数字只有在标线的固定位置才能被识别...
  • 基于FPGA的数字识别的实现

    千次阅读 2018-04-24 13:35:17
    基于FPGA的数字识别的实现 1 背景知识 1.1基于FPGA的数字识别的方法 通常,针对印刷体数字识别使用的算法有:基于模版匹配的识别方法、基于BP 神经网络的识别方法、基于数字特征的识别方法等。下文将对这几种算法...
  • PyTorch手写数字识别(MNIST数据集)

    万次阅读 多人点赞 2019-06-05 08:27:40
    MNIST 手写数字识别是一个比较简单的入门项目,相当于深度学习中的 Hello World,可以让我们快速了解构建神经网络的大致过程。虽然网上的案例比较多,但还是要自己实现一遍。代码采用 PyTorch 1.0 编写并运行...
  • PyTorch手写数字识别

    千次阅读 2019-04-18 22:09:54
    手写数字识别是经典数据集 最后一次任务我们来搞一下 import torch import torch.nn as nn import torch.nn.functional as F import torch.optim as optim import matplotlib.pyplot as plt from torchvision...
  • OpenCV车牌/数字识别

    2019-09-16 22:58:23
    opencv 数字识别 附完整代码 Opencv的应用之车牌识别 用的支持向量机 使用opencv进行数字识别 对学习还是有点帮助的 Tensorflow 实现 MNIST 手写数字识别 这个网络不复杂 -----------------------------------...
  • matlab手写数字识别

    热门讨论 2016-07-17 21:56:51
    毕业设计,matlab神经网络实现手写数字识别
  • 手写数字识别 简单手写数字识别系统 :我们对VC比较熟悉,采用VC开发. 数字的类别只有十种,笔划又简单,其识别问题似乎不是很困难。但事实上,一些测试结果表明,数字的正确识别率并不如印刷体汉字识别正确率...
  • 基于FPGA的数字识别实现

    千次阅读 2019-07-21 17:30:34
    本篇博客就将介绍数字识别的方法,由于只是研究数字识别的方法,我们就不用硬件平台,而是用Modelsim和Matlab来仿真验证。 具体方法如下: 我们用画图软件将带有数字的图片截取为640x480像素,为了和我们将来要使用...
  • 手写数字识别Mnist的Pytorch实现

    千次阅读 2020-07-02 23:20:09
    手写数字识别Mnist的Pytorch实现 注:该内容为校内课程实验,仅供参考,请勿抄袭! 源码地址: 一、引言(Introduction)   手写数字识别时经典的图像分类任务,也是经典的有监督学习任务,经常被用于测试图像的...
  • 手写数字识别系统之数字提取

    千次阅读 2016-11-17 16:05:50
    数字分割在数字识别中是一个必不可少的关键步骤,只有能够将数字进行准确的提取,才能将其一一识别。数字分割的方法数字分割的方法相当多,主要有以下几种:基于直方图的分割此类方法就是对每行和每列黑色像素数进行...
  • OpenCV简单标准数字识别

    万次阅读 多人点赞 2018-10-21 15:32:22
    在学习openCV时,看到一个问答做数字识别,里面配有代码,应用到了openCV里面的ml包,很有学习价值。 https://stackoverflow.com/questions/9413216/simple-digit-recognition-ocr-in-opencv-python# import sys ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 37,529
精华内容 15,011
关键字:

数字识别