TensorFlow在MNIST中的应用 识别手写数字(OpenCV+TensorFlow+CNN)

2023-11-17

参考:

1.《TensorFlow技术解析与实战》

2. http://blog.csdn.net/sparta_117/article/details/66965760

3. http://blog.csdn.net/HelloZEX/article/details/78537213

4. http://blog.csdn.net/gaohuazhao/article/details/72886450

5.http://blog.csdn.net/skeeee/article/details/16844937

###################################################

学习TF已经有一段时间了 ,《TensorFlow技术解析与实战》介绍的TF也还算详尽,参考众多大牛博客后,就跟着实现一遍识别自己手写数字的识别程序好了。学习过程就是在模仿中提高的嘛。手写原图:


内容如下: 
Tensorflow和MNIST简介 
CNN算法 
训练程序 
写数字,并用Opencv进行预处理 
将图片输入网络进行识别

################################################

Tensorflow和MNIST简介:
TensorFlow™ 是一个采用数据流图,用于数值计算的开源软件库。它是一个不严格的“神经网络”库,可以利用它提供的模块搭建大多数类型的神经网络。它可以基于CPU或GPU运行,可以自动使用GPU,无需编写分配程序。主要支持Python编写,但是官方说也有C++使用界面。MNIST是一个巨大的手写数字数据集,被广泛应用于机器学习识别领域。MNIST有60000张训练集数据和10000张测试集数据,每一个训练元素都是28*28像素的手写数字图片。作为一个常见的数据集,MNIST经常被用来测试神经网络,也是比较基本的应用。

CNN卷积神经网络:
识别算法主要使用的是卷积神经网络算法(CNN)。 


主要结构为:输入-卷积层-池化层-卷积层-池化层-全连接层-输出。


卷积 
卷积其实可以看做是提取特征的过程。如果不使用卷积的话,整个网络的输入量就是整张图片,处理就很困难。


假设图中绿色5*5矩阵为原图片,黄色的3*3矩阵就是我们的过滤器,即卷积核。将黄色矩阵和绿色矩阵被覆盖的部分进行卷积计算,即每个元素相乘求和,便可得到这一部分的特征值,即图中的卷积特征。 
然后,向右滑动黄色的矩阵,便可继续求下一部分的卷积特征值。而滑动的距离就是步长。


池化 
池化是用来把卷积结果进行压缩,进一步减少全连接时的连接数。 


池化有两种: 
一种是最大池化,在选中区域中找最大的值作为抽样后的值; 
一种是平均值池化,把选中的区域中的平均值作为抽样后的值。

#############################################################

一、训练程序:

这里我就先把程序贴出来,主体和tensorflow教程上大致相同。值得注意的是其中的saver部分,将训练的权重和偏置保存下来,在评价程序中可以再次使用。


# -*- coding:utf-8 -*-
# ==============================================================================
# 20171115
# HelloZEX
# 卷积神经网络 实现手写数字识别
# 生成并保存模型
# ==============================================================================

from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_Labels_Images", one_hot=True)


import tensorflow as tf

sess = tf.InteractiveSession()


x = tf.placeholder(tf.float32, shape=[None, 784])
y_ = tf.placeholder(tf.float32, shape=[None, 10])
W = tf.Variable(tf.zeros([784,10]))
b = tf.Variable(tf.zeros([10]))


sess.run(tf.global_variables_initializer())

y = tf.matmul(x,W) + b

cross_entropy = tf.reduce_mean(
    tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y))

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

for _ in range(1000):
  batch = mnist.train.next_batch(100)
  train_step.run(feed_dict={x: batch[0], y_: batch[1]})
correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))

accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

print(accuracy.eval(feed_dict={x: mnist.test.images, y_: mnist.test.labels}))

def weight_variable(shape):
  initial = tf.truncated_normal(shape, stddev=0.1)
  return tf.Variable(initial)

def bias_variable(shape):
  initial = tf.constant(0.1, shape=shape)
  return tf.Variable(initial)

def conv2d(x, W):
  return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')

def max_pool_2x2(x):
  return tf.nn.max_pool(x, ksize=[1, 2, 2, 1],
                        strides=[1, 2, 2, 1], padding='SAME')

W_conv1 = weight_variable([5, 5, 1, 32])
b_conv1 = bias_variable([32])
x_image = tf.reshape(x, [-1,28,28,1])
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
h_pool1 = max_pool_2x2(h_conv1)

W_conv2 = weight_variable([5, 5, 32, 64])
b_conv2 = bias_variable([64])
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
h_pool2 = max_pool_2x2(h_conv2)

W_fc1 = weight_variable([7 * 7 * 64, 1024])
b_fc1 = bias_variable([1024])

h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64])
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)
keep_prob = tf.placeholder(tf.float32)
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)
W_fc2 = weight_variable([1024, 10])
b_fc2 = bias_variable([10])

y_conv = tf.matmul(h_fc1_drop, W_fc2) + b_fc2
cross_entropy = tf.reduce_mean(
    tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y_conv))
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
correct_prediction = tf.equal(tf.argmax(y_conv,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

saver = tf.train.Saver()  # defaults to saving all variables

sess.run(tf.global_variables_initializer())
for i in range(20000):
  batch = mnist.train.next_batch(50)
  if i%100 == 0:
    train_accuracy = accuracy.eval(feed_dict={
        x:batch[0], y_: batch[1], keep_prob: 1.0})
    print("step %d, training accuracy %g"%(i, train_accuracy))

  train_step.run(feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5})
# 保存模型参数,注意把这里改为自己的路径
saver.save(sess, 'CKPT/model.ckpt')

print("test accuracy %g"%accuracy.eval(feed_dict={
    x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0}))

print("Finish!")

注意模型存储位置!

##############################################

输出结果:

/usr/bin/python2.7 /home/zhengxinxin/Desktop/PyCharm/Spark/SparkMNIST/SparkMNIST_TF1.py
Extracting MNIST_Labels_Images/train-images-idx3-ubyte.gz
Extracting MNIST_Labels_Images/train-labels-idx1-ubyte.gz
Extracting MNIST_Labels_Images/t10k-images-idx3-ubyte.gz
Extracting MNIST_Labels_Images/t10k-labels-idx1-ubyte.gz
2017-11-15 16:28:43.205071: W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use SSE4.1 instructions, but these are available on your machine and could speed up CPU computations.
2017-11-15 16:28:43.205098: W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use SSE4.2 instructions, but these are available on your machine and could speed up CPU computations.
2017-11-15 16:28:43.205103: W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use AVX instructions, but these are available on your machine and could speed up CPU computations.
2017-11-15 16:28:43.205106: W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use AVX2 instructions, but these are available on your machine and could speed up CPU computations.
2017-11-15 16:28:43.205109: W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use FMA instructions, but these are available on your machine and could speed up CPU computations.
0.9182
step 0, training accuracy 0.14
step 100, training accuracy 0.82
step 200, training accuracy 0.94
step 300, training accuracy 0.92
step 400, training accuracy 0.94
step 500, training accuracy 0.92
step 600, training accuracy 0.96
step 19600, training accuracy 1
step 19700, training accuracy 1
step 19800, training accuracy 1
step 19900, training accuracy 1
terminate called after throwing an instance of 'std::bad_alloc'
  what():  std::bad_alloc

Process finished with exit code 134 (interrupted by signal 6: SIGABRT)
########################################################
最后在CKPT文件夹中生成以下几个文件:



#########################################################

二、OpenCV处理手写原图:
下面我们就要对它进行预处理,缩小它的大小为28*28像素,并转变为灰度图,进行二值化处理。我使用的是Opencv对图像进行处理,也可以使用MATLAB等进行预处理。 
图片预处理程序如下:(程序改编自 参考5,可以使用鼠标拖动选取框,对选取框中的图像进行处理)


#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <stdio.h>

using namespace cv;
using namespace std;

cv::Mat org, dst, img, tmp;
void on_mouse(int event, int x, int y, int flags, void *ustc)//event鼠标事件代号,x,y鼠标坐标,flags拖拽和键盘操作的代号
{
	static Point pre_pt = cv::Point(-1, -1);//初始坐标
	static Point cur_pt = cv::Point(-1, -1);//实时坐标
	char temp[16];
	if (event == CV_EVENT_LBUTTONDOWN)//左键按下,读取初始坐标,并在图像上该点处划圆
	{
		org.copyTo(img);//将原始图片复制到img中
		sprintf(temp, "(%d,%d)", x, y);
		pre_pt = Point(x, y);
		putText(img, temp, pre_pt, FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 0, 0, 255), 1, 8);//在窗口上显示坐标
		circle(img, pre_pt, 2, Scalar(255, 0, 0, 0), CV_FILLED, CV_AA, 0);//划圆
		imshow("img", img);
	}
	else if (event == CV_EVENT_MOUSEMOVE && !(flags & CV_EVENT_FLAG_LBUTTON))//左键没有按下的情况下鼠标移动的处理函数
	{
		img.copyTo(tmp);//将img复制到临时图像tmp上,用于显示实时坐标
		sprintf(temp, "(%d,%d)", x, y);
		cur_pt = Point(x, y);
		putText(tmp, temp, cur_pt, FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 0, 0, 255));//只是实时显示鼠标移动的坐标
		imshow("img", tmp);
	}
	else if (event == CV_EVENT_MOUSEMOVE && (flags & CV_EVENT_FLAG_LBUTTON))//左键按下时,鼠标移动,则在图像上划矩形
	{
		img.copyTo(tmp);
		sprintf(temp, "(%d,%d)", x, y);
		cur_pt = Point(x, y);
		putText(tmp, temp, cur_pt, FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 0, 0, 255));
		rectangle(tmp, pre_pt, cur_pt, Scalar(0, 255, 0, 0), 1, 8, 0);//在临时图像上实时显示鼠标拖动时形成的矩形
		imshow("img", tmp);
	}
	else if (event == CV_EVENT_LBUTTONUP)//左键松开,将在图像上划矩形
	{
		org.copyTo(img);
		sprintf(temp, "(%d,%d)", x, y);
		cur_pt = Point(x, y);
		putText(img, temp, cur_pt, FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 0, 0, 255));
		circle(img, pre_pt, 2, Scalar(255, 0, 0, 0), CV_FILLED, CV_AA, 0);
		rectangle(img, pre_pt, cur_pt, Scalar(0, 255, 0, 0), 1, 8, 0);//根据初始点和结束点,将矩形画到img上
		imshow("img", img);
		img.copyTo(tmp);
		//截取矩形包围的图像,并保存到dst中
		int width = abs(pre_pt.x - cur_pt.x);
		int height = abs(pre_pt.y - cur_pt.y);
		if (width == 0 || height == 0)
		{
			printf("width == 0 || height == 0");
			return;
		}
		dst = org(Rect(min(cur_pt.x, pre_pt.x), min(cur_pt.y, pre_pt.y), width, height));
		cv::resize(dst, dst, Size(28, 28));
		cvtColor(dst, dst, CV_BGR2GRAY);
		threshold(dst, dst, 110, 255, CV_THRESH_BINARY);
		imwrite("T.png", dst);//注意将这里改为自己的处理结果存储地址
		namedWindow("dst");
		imshow("dst", dst);
		waitKey(0);
	}
}
int main()
{
	org = imread("7.jpg");//读取图片地址
	org.copyTo(img);
	org.copyTo(tmp);
	namedWindow("img");//定义一个img窗口
	setMouseCallback("img", on_mouse, 0);//调用回调函数
	imshow("img", img);
	cv::waitKey(0);
}


需要注意根据你手写图片的条件修改二值化阈值。

threshold(dst, dst, 110, 255, CV_THRESH_BINARY);


处理后的结果:

这就是28*28的二值化后的图片,这样的格式和我们MNIST数据集中的图片格式相同。只有这样,我们才能将图片输入到网络中进行识别。
##########################################################
三、将图片输入到网络进行识别:
前向传播的程序,最后softmax层分类的结果就是最后的识别结果啦。 


# -*- coding:utf-8 -*-
# ==============================================================================
# 20171115
# HelloZEX
# 卷积神经网络 实现手写数字识别
# 读取模型并运用识别手写数字
# 如没有cv2,可以尝试 sudo pip install opencv-python
# ==============================================================================

from PIL import Image, ImageFilter
import tensorflow as tf
import matplotlib.pyplot as plt
#import cv2

def imageprepare():
    """
    This function returns the pixel values.
    The imput is a png file location.
    """
    file_name='Pictures/7.png'#导入自己的图片地址
    #in terminal 'mogrify -format png *.jpg' convert jpg to png
    im = Image.open(file_name).convert('L')

    im.save("Pictures/sample.png")
    plt.imshow(im)
    plt.show()
    tv = list(im.getdata()) #get pixel values

    #normalize pixels to 0 and 1. 0 is pure white, 1 is pure black.
    tva = [ (255-x)*1.0/255.0 for x in tv]
    #print(tva)
    return tva

    """
    This function returns the predicted integer.
    The imput is the pixel values from the imageprepare() function.
    """

    # Define the model (same as when creating the model file)
result=imageprepare()
x = tf.placeholder(tf.float32, [None, 784])
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))

def weight_variable(shape):
  initial = tf.truncated_normal(shape, stddev=0.1)
  return tf.Variable(initial)

def bias_variable(shape):
  initial = tf.constant(0.1, shape=shape)
  return tf.Variable(initial)

def conv2d(x, W):
  return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')

def max_pool_2x2(x):
  return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')

W_conv1 = weight_variable([5, 5, 1, 32])
b_conv1 = bias_variable([32])

x_image = tf.reshape(x, [-1,28,28,1])
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
h_pool1 = max_pool_2x2(h_conv1)

W_conv2 = weight_variable([5, 5, 32, 64])
b_conv2 = bias_variable([64])

h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
h_pool2 = max_pool_2x2(h_conv2)

W_fc1 = weight_variable([7 * 7 * 64, 1024])
b_fc1 = bias_variable([1024])

h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64])
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)

keep_prob = tf.placeholder(tf.float32)
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

W_fc2 = weight_variable([1024, 10])
b_fc2 = bias_variable([10])

y_conv=tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)

init_op = tf.initialize_all_variables()


"""
Load the model2.ckpt file
file is stored in the same directory as this python script is started
Use the model to predict the integer. Integer is returend as list.

Based on the documentatoin at
https://www.tensorflow.org/versions/master/how_tos/variables/index.html
"""
saver = tf.train.Saver()
with tf.Session() as sess:
    sess.run(init_op)
    saver.restore(sess, "CKPT/model.ckpt")#这里使用了之前保存的模型参数
    #print ("Model restored.")

    prediction=tf.argmax(y_conv,1)
    predint=prediction.eval(feed_dict={x: [result],keep_prob: 1.0}, session=sess)
    print(h_conv2)

    print('recognize result:')
    print(predint[0])

运行中产生一个Figure1,叉掉他就继续运行。



输出结果:

/usr/bin/python2.7 /home/zhengxinxin/Desktop/PyCharm/Spark/SparkMNIST/SparkMNIST_TF2.py
WARNING:tensorflow:From /home/zhengxinxin/Desktop/PyCharm/Spark/SparkMNIST/SparkMNIST_TF2.py:85: initialize_all_variables (from tensorflow.python.ops.variables) is deprecated and will be removed after 2017-03-02.
Instructions for updating:
Use `tf.global_variables_initializer` instead.
2017-11-15 19:09:12.008792: W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use SSE4.1 instructions, but these are available on your machine and could speed up CPU computations.
2017-11-15 19:09:12.008817: W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use SSE4.2 instructions, but these are available on your machine and could speed up CPU computations.
2017-11-15 19:09:12.008822: W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use AVX instructions, but these are available on your machine and could speed up CPU computations.
2017-11-15 19:09:12.008825: W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use AVX2 instructions, but these are available on your machine and could speed up CPU computations.
2017-11-15 19:09:12.008829: W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use FMA instructions, but these are available on your machine and could speed up CPU computations.
Tensor("Relu_1:0", shape=(?, 14, 14, 64), dtype=float32)
recognize result:
7

Process finished with exit code 0

可以看到正确识别了手写数字。可喜可乐可喜可乐!!!!



























本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

TensorFlow在MNIST中的应用 识别手写数字(OpenCV+TensorFlow+CNN) 的相关文章

随机推荐

  • docker构建部署node后端项目

    文章目录 简介 详细过程 1 将node项目打包成 tar 2 将node项目 tar打包成 tar gz 3 构建Dockerfile文件 4 执行命令打包镜像 简介 本次主要想记录一下docker部署node后端项目的过程 方便后面如果
  • CMU15-213 课程笔记 01-课程概览

    知识点 这门课的目的 深入理解当你执行代码时 计算机在做什么 LLDB 基于 LLVM 的命令行调试器 类似 GBD 内存引用 Bug typedef struct int a 2 double d struct t double fun
  • 如何确定一次完整的请求过程——服务链路跟踪

    微服务体系下 一个请求会调用多个服务 整个请求就会形成一个调用链 普通的日志输出是无法将整个体系串联起来 调用过程中某一个节点出现异常 定位排查难度系数增高 这种情况下就需要一个组件 来分析系统性能 展现调用链路 以便出现故障时快速定位并解
  • 【笔记整理】通信原理第四章复习——数字基带传输

    4 1 引言 数字基带信号 数字信号 补充 基带信号 指未经调制的信号 特征是其频谱从零频率或很低频率开始 占据较宽的频带 基带在传输前 必须经过一些处理或某些变换 比如码型变换 波形变换和频谱变换 才能送入信道中传输 处理或变换是为了使信
  • Django-rest-framework框架

    目录 一 Web应用模式 1 1 前后端不分离 二 API接口 三 接口测试工具 Postman 四 RESTful API规范 4 1 数据的安全保障 4 2 接口特征表现 4 3 多数据版本共存 4 4 数据即是资源 均使用名词 可复数
  • VHDL语言实现8位LED流水灯

    VHDL语言实现8位LED流水灯 包含对50MHz时钟信号分频产生1Hz信号 library ieee use ieee std logic 1164 all use ieee std logic unsigned all entity l
  • 1、mos管的工作原理

    文章目录 一 导体 绝缘体 半导体 二 半导体的制作 掺杂 pn结 半导体的单向导电性 三 mos管的工作原理 源极 栅极和漏极 nmos和pmos 电路符号 四 总结 一 导体 绝缘体 半导体 导体 能够导电的介质 绝缘体 不能导电的介质
  • 程序猿眼中的协议:TCP / IP 五层网络模型

    哈喽 大家好 我是你们的老朋友 保护小周 本期为大家带来的是 网络基础原理中的 TCP IP 五层网络模型 主要从协议的概念 网络模型 数据分层传输的流程 几个方面讲解 看完之后可以轻松的理解数据是如何在网络中传输的 确定不来看看嘛 更多精
  • List循环删除集合

    目录 For循环遍历List 增强For循环遍历List 迭代器iterator的remove方法 创建新的对象添加值 For循环遍历List 删除后list大小发生变化 因此索引发生变化 所以删除的元素不是你想要的 解决办法 倒着遍历li
  • qt学习笔记(五) QGraphicsPixmapItem与QGraphicsScene的编程实例 图标拖动渐变效果

    应大家的要求 还是把完整的工程文件贴出来 大家省点事 http www kuaipan cn file id 48923272389086450 htm 先看看运行效果 我用的群创7寸屏 主机是mini2440 分辨率是800 480 程序
  • 转】M1卡密钥破解,收藏

    M1卡说明及使用proxmark3破解方法 看了网上写的一些关于M1卡的文章 多数有些误导之嫌 首先谈谈M1卡的规格 M1卡的容量为1KB 好多网上写8KB 这里其实是有个误区 应该是8K位 1Byte 1B 8位 其实也就是说8k位想到于
  • Oracle数据库启动过程

    一 Oracle数据库的四种状态 Oracle数据库有四种状态 SHUTDOWN NOMOUNT MOUNT OPEN 二 Oracle数据库的启动过程详解 Oracle数据库启动主要包括三个过程 1 shutdown状态 数据库没有启动
  • Linux·设备文件devfs

    目录 设备文件系统 devfs udev mdev 关于file和inode数据结构在内核中的探究 设备文件系统 Linux引入了虚拟文件系统 从而使设备的访问可以像访问普通文件系统一样 因此在内核中描述打开文件的数据inode中的rdev
  • Python实现自动化办公

    人工智能 AI 是当今世界最为热门的话题之一 而Python是从事AI领域最为流行的编程语言 在本文中 我将介绍如何使用Python实现自动化办公和处理工资表等知识教程 帮助您从零入门人工智能Python 一 制作Excel可视化报表 在传
  • Qt槽和信号参数

    Qt的信号只需要申明 不需要定义 signals void signalA int a Qt的槽和普通的成员函数是一样的 可以加上public potected 以及virtual等标记 public void slotA int a 把这
  • JAVA远程调试功能

    JAVA 支持调试功能 本身提供了一个简单的调试工具JDB 支持设置断点及线程级的调试同时 不同的JVM通过接口的协议联系 本地的Java文件在远程JVM建立联系和通信 一 基本使用 服务端配置 1 服务器端开启调试模式 启动时增加JVM启
  • unity利用Image画直线,以及折线图

    using System Collections using System Collections Generic using UnityEngine using UnityEngine UI
  • QT qrand()随机函数

    在Qt中 生成随机数的函数为 qrand 该函数是标准C 函数 rand 的线程安全版本 如果我们仅仅只是调用该函数来生成随机数 那么每次得到的随机数都将是相同的 这是因为Qt生成的随机数严格来说是一个 伪随机 它的产生是根据随机数种子计算
  • 山东大学 研一 高级算法设计与分析期末考试回忆版

    新鲜出炉 1 给了一个无序的数组 要求给定时间复杂度为n的平方和nlogn的2中排序算法进行排序 并证明其时间复杂度 2 证明WPAR问题是npc问题 即给定一个集合 我们能够找到它的一个子集 剩余部分是这个子集的C倍 C是整数 1 利用划
  • TensorFlow在MNIST中的应用 识别手写数字(OpenCV+TensorFlow+CNN)

    参考 1 TensorFlow技术解析与实战 2 http blog csdn net sparta 117 article details 66965760 3 http blog csdn net HelloZEX article de