Lenet5实现及代码详解——以MINST数据集为例

2023-11-05

看了卷积神经网络(CNN)的原理及介绍,想着自己动手解决一个案例,在网上也看了很多博客,这里整理一下,顺便记录一下自己解决一个完成的CNN实例的过程,以便以后方便看。
如果有不足之处,欢迎大家指正。

数据获取与可视化操作

1、下载minst数据集

在网上可以很容易找到minst数据集,这里为了方便大家,直接给出链接,大家直接点击下载即可.。注意下载后不要解压缩

2、数据的读取

利用python的pickle模块以及gzip库直接读取文件

import pickle
import gzip
# 数据的读取
f = gzip.open("D:\\wangyang\\图像识别\\程序\\CNN\\minst.gz", "rb")
train_set, valid_set, test_set = pickle.load(f, encoding="bytes")
#注意后面的编码参数encoding不能省略,否则会报错
f.close()
#记得及时关闭文件

到这里数据的读取工作就已经完成了,值得注意的是训练集train_set是一个元组(tuple,一共有两个元素),第一个元素是一个多维数组(np.ndarray),存储了50000个28*28的二维数组(可以看成是一个矩阵),也就是说mnist.pkl.gz库中图像的大小是28 * 28的。

3.数据的可视化(tile)

为了更清楚看到数据究竟是什么样子的,我们需要对数据进行可视化操作(当然这不是必须的)对训练集数据进行可视化操作,结果如下图所示
在这里插入图片描述
具体程序如下所示

class DataofVisualization(object):
    """对数据的可视化操作,将数据tile出来"""

    def normalize(self, data):
        """
        对数据进行归一化操作,这里采用线性归一化方法——Min-Max归一化
        X_norm=(X-min)/(X_max-X_min)
        """
        from sklearn import preprocessing
        X = preprocessing.MinMaxScaler()
        return X.fit_transform(data)

    def tile_raster_images(self, X, image_shape, tile_shape, tile_spacing=(0, 0), normalize_rows=True, output_pixel_vals=True):
        """
        把图片按贴砖的形式打印出来
        image_shape:每一块砖的高和宽;
        tile_shape:在横纵方向上分别有多少砖;
        tile_spacing:砖与砖之间的距离
        normalize_rows:是否对砖进行归一化;
        output_pixel_vals:是否对砖以图像的形式进行显示
        """
        # 对参数进行断言(asser),确保它们都是二维数组,否则报错
        assert len(image_shape) == 2
        assert len(tile_shape) == 2
        assert len(tile_spacing) == 2

        output_shape = [(ishp + tsp) * tshp - tsp for ishp, tshp, tsp in zip(image_shape,
                                                                             tile_shape, tile_spacing)]
        # 计算最后的"大砖"高和宽

        im_H, im_w = image_shape
        Hs, Ws = tile_spacing
        dt = "uint8" if output_pixel_vals else X.dtype  # 确定数据的编码格式
        output_array = np.zeros(output_shape, dtype=dt)

        # 开始贴砖
        for i in range(tile_shape[0]):
            for j in range(tile_shape[1]):
                if i * tile_shape[1] + j < X.shape[0]:
                    this_x = X[i * tile_shape[1] + j]
                    this_image = self.normalize(this_x.reshape(
                        image_shape)) if normalize_rows else this_x.reshape(image_shape)

                    c = 255 if output_pixel_vals else 1
                    output_array[i * (im_H + Hs):i * (im_H + Hs) + im_H, j * (im_w + Ws):
                                 j * (im_w + Ws) + im_w] = this_image * c
        return output_array
mydata = DataofVisualization()
X = train_set[0]
arr = mydata.tile_raster_images(X, image_shape=(28, 28),
                                tile_shape=(12, 12), tile_spacing=(5, 5))
img = Image.fromarray(arr)
img.show()

归一化方法有两种形式,一种是把数变为(0,1)之间的小数,一种是把有量纲表达式变为无量纲表达式。主要是为了数据处理方便提出来的,把数据映射到0~1范围之内处理,更加便捷快速,应该归到数字信号处理范畴之内

注意上面的利用到了归一化处理,为了简单起见只用了线性归一化方法,对其他归一化方法感兴趣的同学可以看这篇博客

卷积神经网络

关于卷积神经网络网上已经有很多优秀的博客了,这里就不再多说什么了,感兴趣的可以看看下面这篇博客
卷积神经网络详解 - 卷积层逻辑篇
接下来我想复现经典的卷积神经网络——Lenet-5模型
前期准备工作,请确保以下模块以及安装成功

基于theano实现Lenet 5

import os
import sys
import timeit
import theano
# theano与tensorfloe类似,都是基于建立神经网络的组件
import theano.tensor as T
from theano.tensor.signal import pool
from theano.tensor.nnet import conv
from logistic_sgd import LogisticRegression, load_data
from mlp import HidderLayer

期间会出现如下问题
Q:No module named ‘logistic_sgd’
A:对照着博客一步一步解决就好了(注意最好把文件放在你当前工程的目录下)
Q:出现下列问题在这里插入图片描述
将keras版本退化到1.2.2版本,win+r调出命令窗口,输入如下命令

pip install keras == 1.2.2

Q:缺少模块
A:根据错误信息,利用pip install下载缺少的模块即可

Q:出现下列问题
在这里插入图片描述
A:后来发现这个目前mlp类中已经不支持HidderLayer了,在网上找了很久都没有找到对应的解决办法,希望以后有大佬能够解决吧
到这里我实在是不知道怎么看下去了,本来就是初学者,哈哈哈哈,所以改用基于Tensorflow来实现

基于Tensorflow实现Lenet 5

简单回顾一下Lenet 5的基本结构
在这里插入图片描述
在此之前导入相关模块,以下的代码均基于此来运行

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data

运行编译一下,观察是否出现错误,如果报错根据错误信息对应解决
(一般多是没有对应的模块,win+r调出命令窗口利用pip命令下载对应的模块即可)
因为笔者本身就是一个新手,所有下面的东西难免会出错,同时也会有些啰嗦,还请大家多多担待。

数据的读取

同样的,要实现一个卷积神经网络最开始的就是数据的读取工作,所以接下来实现数据的读取操作

mnist = input_data.read_data_sets(
    'D:\\wangyang\\图像识别\\程序\\CNN\\mnist.gz', one_hot=True)

sess = tf.InteractiveSession() #创建一个对话

运行上述代码之后会发现之前的文件夹中多了一个文件夹,里面是这样的
在这里插入图片描述
是不是很神奇?其实不是,秘密就在那一行命令中。
首先来说明一下input_data是手写数字识别的一个模块,其中read_data_sets方法的具体含义不再多说,相关参数如下

def read_data_sets(train_dir,
                   fake_data=False,
                   one_hot=False,
                   dtype=dtypes.float32,
                   reshape=True,
                   validation_size=5000,
                   seed=None,
                   source_url=DEFAULT_SOURCE_URL)

我们一般常用第一个参数(数据集的绝对路径,即在电脑中的位置)和第三个参数,直白点说就是用0或1去描述图片上的数字,只能有一个1,它在哪一位就代表数字几,其他位均为0。最后关于InteractiveSession就不再多说了,感兴趣的自己点击看看。(TensorFlow中的变量是惰性加载的,如果你想看到变量的值,必须建立一个对话(Session))

训练数据

# 训练数据
x = tf.placeholder("float", shape=[None, 784])  
# 训练标签数据
y_ = tf.placeholder("float", shape=[None, 10])  
# 把x更改为4维张量,第1维代表样本数量,第2维和第3维代表图像长宽, 第4维代表图像通道数, 1表示黑白
x_image = tf.reshape(x, [-1, 28, 28, 1])
#因为minst数据集中图像的大小都是28*28的,所以第二个参数和第三个参数均为28,第一个参数为-1表示大小不确定

其中tf.placeholder的用法如下,只有dtype参数是必选参数,其余均是可选参数。
在这里插入图片描述

卷积层C1


# 第一层:卷积层
# 过滤器大小为5*5, 当前层深度为1, 所以过滤器的深度为1,一共6个过滤器,即6个卷积核
conv1_weights = tf.get_variable("conv1_weights", [5, 5, 1, 6], initializer=tf.truncated_normal_initializer(stddev=0.1))#过滤器,即卷积核
#偏置项,因为有6个卷积核,所以需要6个偏置项
conv1_biases = tf.get_variable("conv1_biases", [6], initializer=tf.constant_initializer(0.0))
# 移动步长为1, 不使用全0填充
conv1 = tf.nn.conv2d(x_image, conv1_weights, strides=[1, 1, 1, 1], padding='VALID')
# 激活函数Relu去线性化
relu1 = tf.nn.relu(tf.nn.bias_add(conv1, conv1_biases))
#relu1即为本层的输出,亦为下一层的输入

代码解释

注意:get_variable是创建一个变量并初始化,第一个参数的变量名,第二个参数是大小,第三个参数用于初始化,详细说明点击此处并且两个初始化方法
在这里插入图片描述
在这里插入图片描述

conv1 = tf.nn.conv2d(x_image, conv1_weights, strides=[1, 1, 1, 1], padding='VALID')

strides参数,第一个和第四个是1,不能改变,第二个和第三个分别指水平滑动和垂直滑动的步长值(一般来说是一样的,这里就是说步长为1),参数padding通俗的说就是决定是否补0,后面是padding='VALID'就是不进行补0操作的,详细解析点击此处
这句话的命令实际就是在进行卷积运算,tf.nn.conv2d的具体用法点击此处,这里就不再多说了,只要明白这一步是在进行卷积运算就好了。

relu1 = tf.nn.relu(tf.nn.bias_add(conv1, conv1_biases))

函数tf.nn.relu就是我们通常立即的Relu激活函数(相关用法),即
在这里插入图片描述
函数tf.nn.bias_add表示加上偏置项,用一维向量加到矩阵的每一行上去。
到这里就已经结束了第一层卷积。

逻辑分析

输入:28 * 28大小的矩阵,深度为1,数目未知
卷积核:5 * 5,深度为1,一共6个
偏置项:constant,一维,一共6个
步长S:S=1
padding(P):P=0,不填充0
输出:6个特征图,每一个大小24*24,深度为1(与输入矩阵的大小保持一致)

因为计算公式如下
在这里插入图片描述

池化层S2

# 第二层:最大池化层
# 池化层过滤器的大小为2*2, 移动步长为2,不使用全0填充
pool1 = tf.nn.max_pool(relu1, ksize=[1, 2, 2, 1], strides=[
                       1, 2, 2, 1], padding='VALID')

代码解释

这里采用的最大池化,在池化层中一般使用非重叠池化,所以这里步长设置为了2,池化大小为(2,2),这里通过tf.nn.max_pool函数来实现了池化层的功能,相关用法请点击此处

逻辑分析

输入:24 * 24大小的矩阵,一个有6个(也就是特征图)
池化大小:2 * 2
padding:不补0,P=0
步长(S):S=2
输出:12 * 12大小的特征图,一共有6个(池化不会改变特征图的个数,只会改变每个特征图的大小)

卷积层C3

# 第三层:卷积层
conv2_weights = tf.get_variable("conv2_weights", [5, 5, 6, 16], initializer=tf.truncated_normal_initializer(
    stddev=0.1))  # 过滤器大小为5*5, 当前层有6个输入, 过滤器的个数为16
conv2_biases = tf.get_variable(
    "conv2_biases", [16], initializer=tf.constant_initializer(0.0))
conv2 = tf.nn.conv2d(pool1, conv2_weights, strides=[
                     1, 1, 1, 1], padding='VALID')  # 移动步长为1, 使用全0填充
relu2 = tf.nn.relu(tf.nn.bias_add(conv2, conv2_biases))

代码解释

相关命令与C1层类似(只是相关的参数不一样),这里就不再重复了。这里仅说明

conv2_weights = tf.get_variable("conv2_weights", [5, 5, 6, 16], initializer=tf.truncated_normal_initializer(
    stddev=0.1)) 

中的第二个参数中的第三个为什么是6,因为该层的输入就是池化层S2的输出,而S2的输出一共有6个特征图,所以这里为6

逻辑分析

输入:12 * 12的特征图,一共6个,每个深度为1
卷积核:5 * 5的矩阵,一共16个,每个深度也为1
步长(S):S=1
padding:P=0,不填充0
输出:8 * 8的特征图,得到16个特征图(一般是几个卷积核就会得到几个特征图)
值得注意的是:
卷积层S3与S1是有不同的,最主要的区别就是连接方式
在这里插入图片描述
输入的6个特征图与卷积层中16个卷积核的连接方式如下图所示
在这里插入图片描述
简单的就是
C2得到了6个特征图,S3中有16个卷积核,最后经过卷积层S3,得到了16个特征图

1、前6个特征图是以C2中的三个特征图作为输入,作用到6个卷积核中,得到了6个
eg:用特征图0,1,2作为输入,作用到卷积核0中,得到了一个特征图;用特征图1,2,3作用到卷积核1中又得到一个特征图(也就是第一个红色的方框里的形式),以此类推可以得到6个特征图

2、接下来的6个特征图是用连续4个特征图作为输入,作用到另外6个卷积核,又可以得到6个特征图
eg:用特征图0,1,2,3作为输入,作用到卷积核6中,得到一个特征图;用特征图1,2,3,4作为输入,作用到卷积核7中又可以得到一个特征图(即第二个蓝色方框中的形式),以此类推可以得到6个特征图

3、接下来的3个特征图是用间隔的4个特征图作用到3个卷积核中得到的
eg:用特征图0,1,3,4作为输入,作用到卷积核12中,得到一个特征图;用特征图1,2,4,5作为输入,又可以得到一个特征图(即第三个红色方框中的形式),以此类推得到3个特征图

4、最后一个特征图是用6个特征图作为输入,作用到最后一个卷积核得到的
eg:用特征图0,1,2,3,4,5作为输入,作用到卷积核15中得到第16个特征图

池化层C4

# 第四层:最大池化层
# 池化层过滤器的大小为2*2, 移动步长为2,使用全0填充
pool2 = tf.nn.max_pool(relu2, ksize=[1, 2, 2, 1], strides=[
                       1, 2, 2, 1], padding='VALID')

代码解释

这一层代码池化层C2类似,这里就不在重复了

逻辑分析

输入:8*8的特征图,一共有16个

池化器:2 * 2

步长:S=2

padding:P=0,不填充

输出:4 * 4的特征图,一共16个

全连接层C5

# 第五层:全连接层
fc1_weights = tf.get_variable("fc1_weights", [
                              4 * 4 * 16, 120], initializer=tf.truncated_normal_initializer(stddev=0.1))  # 7*7*64=3136把前一层的输出变成特征向量
fc1_baises = tf.get_variable(
    "fc1_baises", [120], initializer=tf.constant_initializer(0.1))
pool2_vector = tf.reshape(pool2, [-1, 4 *4* 16])
fc1 = tf.nn.relu(tf.matmul(pool2_vector, fc1_weights) + fc1_baises)

# 为了减少过拟合,加入Dropout层
keep_prob = tf.placeholder(tf.float32)
fc1_dropout = tf.nn.dropout(fc1, keep_prob)

代码解释

这一层在Lenet论文中也是卷积层,只不过在经过卷积核作用以后它变成了一个1*1的,起到了一个类似全连接的作用

fc1_weights = tf.get_variable("fc1_weights", [
                              4 * 4 * 16, 120], initializer=tf.truncated_normal_initializer(stddev=0.1)) 

创建一个张量,因为池化层的输入是4 * 4的,一共有16个,经过这一层后要得到120个1 * 1的特征图,所以要创建一个[4*4*16,120]的张量

fc1 = tf.nn.relu(tf.matmul(pool2_vector, fc1_weights) + fc1_baises)

函数tf.matmul表示两个矩阵相乘,具体用法点击此处

fc1_dropout = tf.nn.dropout(fc1, keep_prob)

函数tf.nn.dropout()是tensorflow里面为了防止或减轻过拟合而使用的函数,它一般用在全连接层,具体用法点击此处

逻辑分析

输入:4 * 4的特征图,一共16个
输出:1 * 1的特征图,一个120个

全连接层F6

# 第六层:全连接层
fc2_weights = tf.get_variable("fc2_weights", [
                              120, 10], initializer=tf.truncated_normal_initializer(stddev=0.1))  # 神经元节点数120, 分类节点10,也就是输入为120,输出为10
fc2_biases = tf.get_variable(
    "fc2_biases", [10], initializer=tf.constant_initializer(0.1))
fc2 = tf.matmul(fc1_dropout, fc2_weights) + fc2_biases

代码解释

与上一层大致一样,最大的区别是上一层虽然叫做全连接层,但是本质还是一个卷积层,所以需要通过激活函数,这一层就是完完全全的全连接层,所以不需要激活函数

逻辑分析

输入:神经节点120个

输出:分类节点10个

输出层Output

# 第七层:输出层
# softmax
y_conv = tf.nn.softmax(fc2)
# 定义交叉熵损失函数
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ *
                                              tf.log(y_conv), reduction_indices=[1]))

# 选择优化器,并让优化器最小化损失函数/收敛, 反向传播
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)

# tf.argmax()返回的是某一维度上其数据最大所在的索引值,在这里即代表预测值和真实值
# 判断预测值y和真实值y_中最大数的索引是否一致,y_conv的值为1-10概率
correct_prediction = tf.equal(tf.argmax(y_conv, 1), tf.argmax(y_, 1))

# 用平均值来统计测试准确率
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

代码解释

函数tf.nn.softmax主要是将N * 1的向量转成N * 1的向量(每个元素的大小在0-1之间,也就是属于某一类的概率),具体用法点击此处

cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ *
                                              tf.log(y_conv), reduction_indices=[1]))

函数tf.log用来求自然对数(底数为e),具体用法点击此处
函数tf.reduce_sum是求和,该命令的意思是对矩阵y*tf.log(y_cov)横向求和,具体用法点击此处
函数tf.reduce_mean是用来求平均值,具体用法点击此处
另外交叉熵损失函数如下
在这里插入图片描述

train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)

选择Adam优化器学习率设置为1e-4),优化最小化损失函数,找到最优的矩阵W,其实反向传播的目的就是不断更新矩阵W,找到最优的W,是的W*x后的概率矩阵的损失函数最小。

correct_prediction = tf.equal(tf.argmax(y_conv, 1), tf.argmax(y_, 1))

函数tf.argmax表示返回某一维度上最大值所在的索引值(该命令是返回某一行最大值所在的位置,因为y_conv和y_是一个行向量),详细用法点击此处
函数tf.equal用来判断两个张量是否相等(逐个元素进行比较),具体用法点击此处

# 用平均值来统计测试准确率
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

函数tf.cast进行张量的数据类型转换,将布尔值转成浮点数(ture变成1,false变成0),具体用法点击此处

逻辑分析

输入:1*10的向量

输出:1*10的向量,但是向量中的值均在0-1之间

训练数据

# 开始训练
sess.run(tf.global_variables_initializer())
for i in range(5000):#这里仅训练五千次
    batch = mnist.train.next_batch(100)#批量读取数据
    if i % 100 == 0:
        train_accuracy = accuracy.eval(
            feed_dict={x: batch[0], y_: batch[1], keep_prob: 1.0})  # 评估阶段不使用Dropout
        print("step %d, training accuracy %g" % (i, train_accuracy))
    # 训练阶段使用50%的Dropout
    train_step.run(feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5})
# 在测试数据上测试准确率
print("test accuracy %g" % accuracy.eval(
    feed_dict={x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0}))

代码解释

函数feed_dict是用来给之前占位符赋值,即把batch[0]给x等。

运行结果

在这里插入图片描述

完整代码

完整的代码请点击此处下载

参考博客

数据集可视化——tile(“贴砖”)
深度学习 CNN卷积神经网络 LeNet-5详解

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

Lenet5实现及代码详解——以MINST数据集为例 的相关文章

  • Vision Transformer

    A N I MAGE IS W ORTH 16 X 16 W ORDS TRANSFORMERS FOR I MAGE R ECOGNITION AT S CALE 原文链接地址 https arxiv org abs 2010 11929
  • Open mv识别三角形的办法

    文章目录 前言 带着问题来看 一 函数 二 使用方法 1 find line segments 2 img find template 三 摄像情况及终端结果 1 find line segments 2 img find template
  • Lenet5实现及代码详解——以MINST数据集为例

    看了卷积神经网络 CNN 的原理及介绍 想着自己动手解决一个案例 在网上也看了很多博客 这里整理一下 顺便记录一下自己解决一个完成的CNN实例的过程 以便以后方便看 如果有不足之处 欢迎大家指正 数据获取与可视化操作 1 下载minst数据
  • 毕设:基于CNN卷积神经网络的猫狗识别、狗品种识别(Tensorflow、Keras、Kaggle竞赛)

    基于卷积神经网络的图像识别算法及其应用研究 毕业快一年了 拿出来分享给大家 我和网上唯一的区别就是 我能够同时实现两个方案 猫狗识别和狗品种识别 我当时也是网上各种查 花了2 3个月的时间 一个萝卜一个坑走过来的 深度学习真的是深似海呀 不
  • 文字识别:Tesseract OCR

    一 安装并配置Tesseract 1 下载Tesseract OCR 网上直接下载即可 2 双击安装 选择所有人均可使用 避免权限问题 勾选最后一项添加语言包 但是全部勾选需要1 3G 可以点开加号 选择自己所需的语言包即可 注意 这里最好
  • OpenCV与图像算法笔记

    本博客为 OpenCV算法精解 基于Python与C 一书 参阅源代码链接 的阅读笔记 根据理解对书中绝大多数算法做了总结和描述 对Numpy较为熟悉 Python方面仅对与C 不同的注意事项做了标注 书作者整体按照冈萨雷斯的经典教材 数字
  • Pytorch resnet花朵识别(5种花)附完整代码

    notebook运行结果图 随机从各种花的图片集中抽取一定数量的图片 因为设备限制 用所有的图片 图片太多 如果用cpu跑太慢了 用gpu太多图片会out of memory 所以用小部分图片 了解方法就好了 重写dataset类 显示图片
  • python实现车牌识别系统

    车牌识别系统 算法参考 http www zengqiang club blog 34 GUI参考 https blog csdn net wzh191920 article details 79589506 基于opencv的模板识别来实
  • opencv——训练自己的小狗分类器

    opencv python图像识别 训练自己的分类器 opencv支持训练自己的分类器 闲话少说 训练步骤 准备样本图像数据 样本数据预处理 正反样本数据生成正反txt vec文件 训练 测试结果 注意以下几点 首先应该注意样本数据量 预处
  • 基于opencv-python的人脸识别和鸟图识别

    目录 图像识别 人脸识别 鸟图识别 一 人脸识别 即使是地铁挤压的人脸 也是有尊严的 值得被检测 经过 OpenCV 的努力 成功检测 左图是正常被识别的人脸 中图由于挤地铁人脸已不可识别 右图OpenCV单应性变换后 拯救了被miss的人
  • 数字图像处理-数字水印的嵌入与提取

    数字水印嵌入与提取 本篇报告所有内容已上传csdn我的资源中 包括源码与报告word和ppt 欢迎大家下载进行进一步修改研究 摘要 本报告重点介绍数字水印的嵌入与提取算法 数字水印根据水印的嵌入技术不同分为空间域数字水印和变换域数字水印 本
  • VGGNet实现CIFAR-100图像识别-1(数据预处理,one-hot)

    VGGNet CIFAR 100 导入数据 数据预处理 方法1 方法2 可能会遇到的问题 解决办法 Normalization和拆分训练集 验证集 One hot编码 未完待续 接下来请看另一篇博文 VGGNet实现CIFAR 100图像识
  • 几个常用的图片处理和图像识别API

    鸟类识别 http www inspirvision cn www product 支持鸟类品种鉴别 不同种类鸟类检测 鸟类数量统计 提供API Camera360 https github com pinguo PGSkinPrettif
  • Yolov5配置傻瓜教程

    软硬件环境 Win10 anaconda python3 7 gtx 1660ti cuda 10 1 pytorch 1 7 YOLOv5 介绍 2020年6月25日 Ultralytics发布了YOLOV5 的第一个正式版本 其性能与Y
  • 关注公号: AI深度视线

    1 引言 摘要 在这项工作中 我们旨在构建一个性能强大的简单 直接和快速的实例分割框架 我们遵循SOLOv1方法的原理 SOLO 按位置分割对象 重要的是 我们通过动态学习目标分割器的mask head 具体来说 将mask分支解耦为mas
  • 入门图像处理与图像识别的知识框架

    小白一枚 和大家共同学习 编程基础 C 曾经我想用python来做图像处理 后来发现无论是二维图像处理 opencv 还是三维点云处理 PCL 都得学C 数据结构与算法 设计程序的基础课程 编译原理 操作系统 并行计算算法 linux等知识
  • opencv实现答题卡识别

    识别答题卡 import cv2 import numpy as np def showImg img name img cv2 imshow img name img cv2 waitKey cv2 destroyAllWindows d
  • 指针式仪表的自动读数与识别

    指针式仪表的自动读数与识别 前言 概述 步骤概括 1 仪表图像预处理 2 刻度线提取 2 1轮廓查找 2 2面积筛选 长宽比 距离 2 3刻度线轮廓拟合直线 3 指针轮廓提取 3 1 霍夫直线检测原理 4 结果 5 Pyqt5 5 1功能
  • 【从小项目学图片处理】#1 答题卡识别

    说明 项目皆参考于网上 代码也有大部分参考原文 仅用于学习和练习图像处理操作 项目原文 Bubble sheet multiple choice scanner and test grader using OMR Python and Op
  • 基于Fruits-360数据集构建CNN进行水果识别实验

    基于Fruits 360数据集的水果识别项目 前段时间导师要求做一个神经网络可视化的项目 要将水果数据集进行训练得到模型 用于TensorSpace可视化 前前后后捣鼓了很久 现在回过头总结一下整个项目过程 写下这篇博客记录遇到的问题 有任

随机推荐

  • Android Spider Charles - 夜神模拟器证书安装App抓包

    文章目录 前言 一 软件安装 1 Openssl安装 1 1下载安装 1 2配置环境变量 1 3查看openssl版本 输入命令 openssl version 2 夜神模拟器安装 1 1 下载安装 1 2工具准备 MT管理器 3 Char
  • NLP预处理之分词工具的使用(jieba,hanlp)

    文章目录 一 jieba简介 二 jieba的使用 1 精确模式分词 2 全模式分词 3 搜索引擎模式分词 4 使用用户自定义分词 三 hanlp简介 四 hanlp的使用 1 使用hanlp进行中文分词 2 使用hanlp进行英文分词 五
  • Python3学习之数字

    Python 数字数据类型用于存储数值 数据类型是不允许改变的 这就意味着如果改变数字数据类型的值 将重新分配内存空间 以下实例在变量赋值时 Number 对象将被创建 var1 1 var2 10 可以使用del语句删除一些数字对象的引用
  • msfvenom常用参数

    Kali中的 msfvenom 取代了msfpayload和msfencode 常用于生成后门木马 msfpayload是MSF攻击荷载生成器 用于生成shellcode和可执行代码 msfencode是MSF编码器 一 msfvenom
  • 【socket】listen函数及backlog参数

    man listen显示 LISTEN 2 Linux Programmer s Manual LISTEN 2 NAME listen listen for connections on a socket SYNOPSIS include
  • 华为OD机试 - 阿里巴巴找黄金宝箱(II)(Java & JS & Python)

    题目描述 一贫如洗的樵夫阿里巴巴在去砍柴的路上 无意中发现了强盗集团的藏宝地 藏宝地有编号从0 N的箱子 每个箱子上面贴有箱子中藏有金币的数量 从金币数量中选出一个数字集合 并销毁贴有这些数字的每个箱子 如果能销毁一半及以上的箱子 则返回这
  • 第十八课,立方体贴图(加载天空盒)

    原理我在这里不再过多叙述 主要从代码的运行方向来解读立方体贴图 添加天空盒顶点 float skyboxVertices positions 1 0f 1 0f 1 0f 1 0f 1 0f 1 0f 1 0f 1 0f 1 0f 1 0f
  • mysql--部门表员工表练习题

    部门表 create table dept deptno int primary key auto increment 部门编号 dname varchar 14 部门名字 loc varchar 13 地址 insert into dep
  • java核心技术卷一学习(一)

    1 java的微型版Java Micro Edition可以适用于嵌入式编程 2 0X是十六进制 0是8进制 0B是2进制 字母大小写均可 3 java 8种基本类型4中整形 byte 1字节 short 2字节 int 4字节 long
  • 曝光:超级实习生们的训练不一般

    有同学反映在面试华为时 总共四面 到技术面的时候被毙掉了 而且短时间内不能进行二次投递 这就非常的痛苦 虽然现在网上有很多的面试资料 其中不乏一些干货精华 但是只收藏不会用或者只会背八股文 面试时会非常被动 在面试中 动手编程能力是最重要的
  • vue3加载element-plus,修改端口

    环境 最新的node js 最新的vue 安装element plus npm i element plus save legacy peer deps 加载element plus 之前的vue2的方法不适用 import Element
  • 外包三年半,人废了一半

    如果不是女朋友和我提分手 我估计现在还没醒悟 大专生 18年通过校招进入湖南某软件公司 干了3年多的CRUD 今年年初 感觉自己不能够在这样下去了 长时间呆在一个舒适的环境会让一个人堕落 而我已经在一个企业干了3年的CRUD 已经让我变得不
  • VUE+Element UI 展示json数据 [vue-json-viewer]

    1 安装组件vue json viewer npm install vue json viewer save 2 在main js中引入并使用vue json viewer import JsonViewer from vue json v
  • linux下安装git-lfs的两种方法

    一 方法一 推荐 首先安装git lfs ubuntu版 sudo apt get install git lfs centeros版 sudo yum install git lfs 然后验证安装成功 git lfs install 若显
  • 电商平台学习笔记(四)——Spring配置Mybatis简化DAO层省略Mybatis核心配置文件

    今天看到电商视频教程第三天的时候 惊奇的发现 这个电商平台一共有16张表 加上MyBatis的模板Bean 一共32个Bean 如下图 想到这里 如果有Mybatis的核心配置文件 mybatis config xml 仅对每一JavaBe
  • Java中匿名内部类

    含义 由于Java中接口和抽象类都不能实例化对象 故使用接口或抽象类时 必须有一个实现类 对应接口 或继承类 对应抽象类 而该实现类或继承类的对象被使用次数很少 不值得去专门编码时候 就可以使用匿名内部类 此时该类不必命名 并且对象只被创建
  • 4.7、漏洞利用-SMTP

    目录 4 7 漏洞利用 SMTP 1 SMTP环境搭建 1 1 邮件发送和接收模型 1 2 添加主机名和域名 1 3 Ubuntu下安装postfix 1 4 安装dovcot 2 利用搭建环境发送和接收邮件 3 枚举smtp用户名 3 2
  • secure注册码&许可向导

    secure许可向导搜了半天也没找到能用的 搜注册码一搜就搜到了 Name meisi Company TEAM ZWT Serial Number 03 14 367662 License Key ACCFAX R9FHJ7 QZVS2P
  • 适合零基础学习的IT编程技术

    现在很多应届生 不管是否是计算机专业 都想毕业后从事IT行业 不仅是因为IT行业的薪资高 更主要是IT行业就业需求多 发展好 工作稳定 学IT 技术在手 天下我走 当然 IT行业有很多学科方向 学习哪个方向很重要 选择方向这件事 有时候就是
  • Lenet5实现及代码详解——以MINST数据集为例

    看了卷积神经网络 CNN 的原理及介绍 想着自己动手解决一个案例 在网上也看了很多博客 这里整理一下 顺便记录一下自己解决一个完成的CNN实例的过程 以便以后方便看 如果有不足之处 欢迎大家指正 数据获取与可视化操作 1 下载minst数据