图片标注问题image_caption

article/2025/8/19 2:44:00

数据集:

  • 数据集中的训练集使用的是coco train 2014,82783张图片,测试集使用的是 val 2017 ,5000张图片,对应的caption是captions_train2014.json,和captions_val2017.json。
    该文件中是以字典的形式包含其内容信息,key值由“info”,”licenses“,”images“,”annotations“组成。
    info:其中包括数据集建立的时间。下载地址,版本号等。
    licenses:是数据集使用条款。
    images:包括图片的filename,height,width ,图片对应的网址,图片对应的caption的id。
    annotation:包含image_id,对应的caption的id,和每个图片对应的5句描述

  • 训练:

    训练集使用的是coco train 2014中的全部数据。

  • 测试:

    测试集使用的是coco val 2017中的的数据。

  • 数据预处理:

    build_data.py中定义了以下几个函数:

  1.def load_and_process_metadata(captions_file,image_dir): with open(captions_file, encoding='utf-8') as f:lines = f.readline()d = json.loads(lines)print(d)f.close()

d[“images”]
######d[“images”]中包含的内容
[{‘license’:6,‘file_name’:‘000000492110.jpg’,‘coco_url’:'http://images.cocodataset.org/val2017/000000492110.jpg’, ‘height’: 427, ‘width’: 640, ‘date_captured’: ‘2013-11-24 00:43:28’, ‘flickr_url’: 'http://farm9.staticflickr.com/8195/8139005828_fda85b4b72_z.jpg’, ‘id’: 492110}]
######d[“annotations”]中包含的内容
[{‘image_id’: 54592, ‘id’: 562033, ‘caption’: ‘Couple of people walking up the snowy mountain with skis’},
{‘image_id’: 23034, ‘id’: 561930, ‘caption’: ‘A man smiles watching a rider approach with two horses.’}]

captions_file:caption_train2014.json和val_2014.json文件的路径。
image_dir:train_2014和val_2014的路径。
函数作用:
读取json文件将image和对应的caption对应,将内容封装到 ImageMetadata中,这时的一个image_id对应一个filename对应五个captions

效果

COCO_train2014_000000458922.jpg

描述captions
’ Beef and other food on a plate next to a wine glass’,
‘A finished steak dinner and glass of wine are on a table.’,
‘some food and a fork is on a plate’,
‘A plate with fork and steak and a wine glass on placemat with papers in background.’,
'a rare steak with a fork and a glass of wine

COCO_train2014_000000058245.jpg

图片描述captions
‘A blue vase filled with colorful flowers sitting on the ground.’,
‘A blue vase on table holding red flowers next to door.’,
‘A bunch of orange flowers in a blue vase on a runner on a table.’,
‘A blue glass vase with some flowers on a table.’,
'A blue glass vase with red and yellow flowers

namedtuple(“ImageMetadata”,[“image_id”,“filename”,‘captions’]

1.读取json文件使用json中的json.loads()方法。
2.索取json中的信息就直接使用字典中的方法就好。

      2.def process_caption(caption):tokenized_caption=[FLAGS.start_word]tokenized_caption.extend(nltk.tokenize.word_tokenize(caption.lower()))tokenized_caption.extend(FLAGS.end_word)

函数作用:将”start_word“和”end_word“加载到每句话中的开始和结束,作用类似于起始密码子,终止密码子,蛋白质合成的起始,和终止。并把caption变成小写,目的不让同一个单词在vocabulary字典中出现两次节省资源。
1.使用方法是用列表中的entend方法

     3.def create_vocab(captions):counter = Counter()for c in captions:counter.update(c)word_counts = [x for x in counter.items() if x[1] >= 4]word_counts.sort(key=lambda x: x[1], reverse=True)

函数作用:统计caption中的所有单词,和出现的频率,并把单词以及单词出现的频率
写入到txt文件中。
1.使用到的方法有collections 中 Counter,Counter是一个计数器,将单词输入其中可
直接将单词的出现频率显示出来。并将重复的单词去除。并只取单词中频率大于4的。并从小到大排序。然后创建一个字典将排序好的单词取出,将单词从0~vocab_size给单词赋一个id。

 4.class Vocabulary(object):def __init__(self, vocab, unk_id):

vocab:是单词带有对应id的字典。
unk_id:是对应vocab_size,也就是单词的长度,如果单词没在制作的dict中就返回
一个空的字符。

word_to_id(self, word):

给定caption中的单词,如果单词在dict中返回对应的word_id,不在就返回unk_id。

5. def process_dataset()

函数作用:这时的一个image仍然是对应一个caption。将image遍历,使每一个image对应一个caption。然后将caption,和image读入tfrecord中。

images = [ImageMetadata(image.image_id, image.filename, [caption])
for image in images for caption in image.captions]
random.seed(12345)
random.shuffle(images)

使用random的方法将image_caption的顺序打乱。

  • tfrecord的使用方法

定义写入tfrecord文件地writer
writer=tf.python_io.TFRecordwriter(filename) # filename:tfrecord保存的地址
文件名队列在上述的images中已经构造好了
for i in range(len(images))
image=images[i]:
获取每个image对应的图片地址+文件名
image_filename=image.filename
获取每句image的描述
caption=image.captions
获得每句caption的id
caption_id=word_to_id(caption)

  • 读入image,并解码

    with tf.gfile.FastGFile(image.filename, “rb”) as f:
    encoded_image = f.read()

解码:
1. tf.decode_csv() 解码文件文本内容
2.tf.image.decode_jpeg(countent) 将jpeg编码的图像解码为uint8张量
3.tf.image.decode_png(content) 将png编码的图像解码为uint8张量
4.tf.decode_raw(value,uint8)解码二进制内容

构造example:

def _int64_feature(value):"""将int 64特性插入序列中的包装器"""return tf.train.Feature(int64_list=tf.train.Int64List(value=[value]))
def _bytes_feature(value):"""将字节特性插入序列示例Proto的包装器"""value = tf.compat.as_bytes(value)return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))
def _int64_feature_list(values):"""将int 64 FeatureList插入序列的包装器-示例Proto"""return tf.train.FeatureList(feature=[_int64_feature(v) for v in values])
def _bytes_feature_list(values):"""将字节FeatureList插入序列示例Proto的包装器"""return tf.train.FeatureList(feature=[_bytes_feature(v) for v in values])context = tf.train.Features(feature={     "image/image_id":_int64_feature(image.image_id),"image/data": _bytes_feature(encoded_image),})
feature_lists = tf.train.FeatureLists(feature_list={"image/caption": _bytes_feature_list(caption),"image/caption_ids": _int64_feature_list(caption_ids)})

那么什么样的数据需要映射为FeatureList或Feature?
我的理解是数字表示,二分类就是0或1,那么就class=0映射为tf.train.Feature(tf.train.Int64List(value=[0])), 只要这个字段包含的数据维度是固定的,就可以封装为 Feature。
对于长度不固定的字段类型,映射为FeatureList。比如NLP样本有一个特征是一句话,那么一句话的长度是不固定的,NLP中一般是先分词,然后把每个词对应为该词在字典中的索引,一句话就用一个一维整形数组来表示 [2, 3, 5, 20, …],这个数组的长度是不固定的,我们就映射为
这里将caption通过上述的函数word_to_id中将caption转化为caption_id。
sequence_example = tf.train.SequenceExample(
context=context, feature_lists=feature_lists)

将caption的feature和images的feature保存到tf.train.SequenceExample中,
将序列化后的example写入文件

wtiter.write(example.SerializeToString())
write.close()

读取tfrecord
  • 构造文件名读取队列

1.将需要读取的文件名放入到文件名队列中

tf.train.string_input_producer(data_file,shuffle=True)
data_file:tfrecord的文件名
shuffle=True:默认文件名随机打乱

  • 读取

使用TFRecorder的方法读入
_,serialized_example=reader.read(filename_queue)

  • 解析example
context, sequence = tf.parse_single_sequence_example(example_serialized,context_features={image_feature: tf.FixedLenFeature([], dtype=tf.string)},sequence_features={caption_feature: tf.FixedLenSequenceFeature([], dtype=tf.int64) })
self.encoded_image = context[image_feature]
self.caption = sequence[caption_feature]
  • 解码

解码仍然使用上述中的解码方法
tf.image.decode_jpeg(self.encoded_image)
使用tf.cast()方法将其转换为tf.float32,由于每张图片的大小可能不是统一大小的,为了方便后面的cnn提取特征,将图片统一大小。使用tf.image.resize_images(image,size=[])

在图片处理时将图片进行数据归一化,优点是
1.归一化后加快梯度下降求最优解的速度
2.归一化后有可能提高精度
3.使用梯度法求最优解时,归一化往往非常有必要,否则模型很难收敛,甚至不能收敛

方法1
image = tf.image.convert_image_dtype(image, dtype=tf.float32) # 将图片像素值变为[0,1]
image = tf.subtract(image, 0.5) # 图片像素值域由[0, 1]变换为[-0.5,0.5]
image = tf.multiply(image, 2.0) # 图片像素值域由[0,0.5]变为[-1,1]

方法2
def image_to_float(image)
image = tf.image.convert_image_dtype(image, dtype=tf.float32)
return (image/127.5) - 1.0

方法3
在人脸识别中用到的直接将特征值除以255的简单缩放法

图片处理

在对图片处理时要进行以下操作,目的是为了防止过拟合,过拟合是指我们训练的模型“实在是太好了”对与训练的数据分类预测效果都特别好,而面对新的数据时变现的效果可能就没那么好了。我们训练数据的目的是让模型既不过拟合,也不是欠拟合,而是处于过拟合与欠拟合之间的一种状态。欠拟合是指无论是对于测试集还是训练集的效果,表现得都不是很好。就比如我们复习数学吧,我们只把课本上的题会做理解,而考试面对新的题,可能只是修改个数我们就做的不太好,这种状态称为过拟合。而我们连书的内容看都不看的话,啥题都不会的情况就是欠拟合。

 image = tf.image.random_flip_left_right(image)
调整图片的随机亮度
image = tf.image.random_brightness(image, max_delta=32 / 255)调整图片饱和度image = tf.image.random_saturation(image, lower=0.5, upper=1.5)随机调整RGB图像的色调image = tf.image.random_hue(image, max_delta=0.032)在某范围随机调整图片对比度
image = tf.image.random_contrast(image, lower=0.5, upper=1.5)
输入一个张量image,把image中的每一个元素的值都压缩在min和max之间。小于min的让它等于min,大于max的元素值等于max
image = tf.clip_by_value(image, 0, 1.0)
  • 对caption构造input_sequence,target_sequence
       images_and_captions = []images_and_captions.append([image, self.caption])enqueue_list = []for image, caption in images_and_captions:# 获取每个句子的长度caption_length = tf.shape(caption)[0]# 将句子id向后移动一input_length = tf.expand_dims(tf.subtract(caption_length, 1), 0)# 真正句子的idinput_seq = tf.slice(caption, [0], input_length)# 句子向有移动后的句子id目的是为了预测下一个单词target_seq = tf.slice(caption, [1], input_length)indicator = tf.ones(input_length, dtype=tf.int32)enqueue_list.append([image, input_seq, target_seq, indicator])
  • 构造批出理队列

有两种方法:tf.train.batch和tf.train.batch_join的区别,一般来说,单一文件多线程,那么选用tf.train.batch(需要打乱样本,有对应的tf.train.shuffle_batch);而对于多线程多文件的情况,一般选用tf.train.batch_join来获取样本(打乱样本同样也有对应的tf.train.shuffle_batch_join使用)。

第一种
tf.train.batch_join(enqueue_list,batch_size=self.batch_size,capacity=queue_capacity,dynamic_pad=True,name="batch_and_pad"))
第二种
tf.train.batch(enquene_list,batch=self.batch_size,capacity=queue_capacity,name="batch_and_pad") 
  • 构造image_embedding
    将解码后的图片经过CNN的全连接层后生成[batch_size,512]的向量
  • 构造caption_embedding

将输入的seq变成词向量,词向量才能在lstm中进行训练计算
原理就是image.png
这里假设词表中有“我,爱,河,南,科,技”6个字,在类比one-hot编码的时候就形成了一个[6,6]的矩阵emdedding-map,然后我如果想取出其中的两个单词“河”,“南”那么就需要查emdedding-map。进行类似的矩阵相乘得到两个词的词向量。

embedding_map=tf.get_variable(name=“map”,shape[vocab_size,512],initializer=self.initializer)
seq_embeddings = tf.nn.embedding_lookup(embedding_map, self.input_seqs)
返回的是tensor 的 shape是 [batch_size,word_size,512]

模型:

1.结构

  • CNN

1,cnn使用的是inceptionv3模型:主要提取图片的特征,
inceptionv3具有很少的参数量,节省计算时间加快学习速度;5x5的卷积核用两个3x3的 卷积核代替增强表达能力,为减少计算复杂度将卷积转化为稀疏连接以下展示cnn的结构图;
7D7A837EF287B16474B652BF3EE657EA.jpg
290284015DEB91BC4B9006A7E4D66F5C.jpg
225EBB66053EF93D5E7263B64BA6319E.jpg

10EEDBD008D7BD87A4846F2F3BC0CA54.jpg

35642BE60F475B4592BE6A50E809DB3C.jpg

2.模型输入的image尺寸为299x299X3 ,batch_size=32 数据类型为float32

shape:[batch_size, height, width, channels]

4.使用batch_normalization.(简称BN)

BN是一种解决深度神经网络层数太多,而没有办法有效向前传递的问题,因为每一层的输出值都会有不同的均值,和方差,所以输出的数据分布也不一样。
优点:
1.他不仅加快模型的收敛速度,而且更重要的是在一定程度上缓解了深度网络中的“梯度弥散”(就是在靠近输出层的hidden layer梯度越大,参数更新快,但是靠近输入层的hidden layer梯度小,参数更新慢,几乎和初始状态一样,随机分布。梯度爆炸与之相反)总体来说就是梯度相当不稳定。
2.控制过拟合可以减少或不用dropout
3.降低网络对初始化权重不敏感
4.允许使用较大的学习率
所以使用BN可以使得模型训练更加容易和稳定。BN从字面意思来说就是每一批数据进行归一化,这里分批在前面的数据准备里已经进行了分批处理。BN可以在网络中任意一层进行归一化处理,V3-inception使用到的优化器是SGD。
没有使用BN的时候每层的值迅速全部变为零,也就是说所有的神经元都已经死了,而有BN,relu过后,每层的值都能有一个比较好的分布效果。
QQ截图20190604122213.png

数据如果在梯度很小的区域,那么学习率就会很慢甚至长时间停滞,但是减均值除方差后,数据就被移到中心区域,如右图所示,对于大多数激活函数来说,这个区域的梯度都是很大的。这个用来解决梯度消失。但是如果每一层都是这样做的话,数据的分布总是随着变化敏感的区域,相当于不用考虑数据分布变化了这样训练起来更有效率。但是减均值除方差得到的分布是正态分布,但是并不是正态分布就是最好或者最能体现我们训练样本的特征分布。因为数据本身很多情况下是不对称的,或者激活函数未必是对方差为1的数据最好的效果,就比如sigmoid激活函数,在-1到1之间的梯度变化不大。这样的话对于非线性变化的作用就不能很好的提现,换言之就是,均方误差操作后可能会削弱网络的性能,所以再加一步利用优化变一下方差大小和均值位置,使得新的分布更切合数据的真实分布,保证模型的非线性表达能力。

卷积层

作用:通过在原始图像上平移来提取特征

tf.nn.conv2(input,fitter,strides,padding)

input:是传入四个维度的图片或者上一层卷积得到的tensor
fitter:卷积核相当于权重有初始值有形状,
strides:步长大小,决定卷积核每次移动的步长,决定了卷积后的图片大小。
padding:可设置为‘’SAME“,"VALID"当padding=SAME时下一层的图片长宽计算new_widh=w/s(向上取整)。padding=VALID时new_width=(w-f+1)/s。w为图片的长宽,f是卷积核大小,s是步长

激活函数

作用:增加非线性分割能力,对输入的数据原始空间进行扭曲。

  • relu
    1,有效的解决了梯度小时问题
    2,计算速比较快
    SGD:(批梯度下降)的求解速度远快于sigmoid和tanh
    sigmoid:采用sigmoid缺点:计算量相对大,而采用relu激活函数,整个过程的计算量节省很多,在深层神经网络中,sigmoid函数反向传播时很容易出现梯度消失的情况

池化层

作用:减小学习参数,降低网络的复杂度
池化层分为最大池化和平均池化,一般最常用最大池化,最大池化是在卷积核大小的feature_map上取最大值,因为这个最大值可以反映了这个feature周围的特征。
内部的池化窗口和卷积核类似,以及步长,padding

Incpetion V3中将5×5的卷积替换成了两个3×3的卷积
而且在这个module中还是用了卷积的分解,将一个7×7的卷积拆分成了一个1×7的卷积和一个7×1的卷积,不仅能够大大节省参数降低模型的过拟合,还能比一个7×7的卷积多一个非线性的变换。另外inceptionv3将卷积网络进行了拆分,其结果比对称的拆分为几个相同的小卷积核效果更明显,可以处理更多,更丰富的空间特征,增加特征多样性。

  • LSTM

对于LSTM神经网络无论是从什么角度描述,中间做的一堆事情,还是找什么样的特征是最适合做这样的一个分类任务,最终连接softmax是用于分类。时序t就是每个单词输入的先后顺序,它结合上一时刻的输出同时乘以权重当做这一时刻的输入20181205233257613.png

定义RNN的基本单元

lstm_cell=tf.contrib.rnn.BasicLSTMCell(num_units=512,state_is_tuple=True)

为了防止过拟合,在LSTM中也添加了dropout层,分别使input,和output的值控制在0.7

lstm_cell=tf.contrib.rnn.DropoutWrapper(lstm_cell,input_keep_prob=0.7,
output_keep_prob=0.7)

定义图中的隐状态:hi,可以把隐状态视作记忆体,它捕捉了之前时间点上的信息。记忆体在RNN迭代的过程也在不断地更新内部的记忆,就像人的大脑一样,不断地记住新的东西,又在忘记旧的

获得lstm全零状态
zero_state=lstm_cell.zero_state(batch_size=batch_size,dtype=tf.float32)
更新lstm状态,这里将经过CNN后提取得到的特征向量输入到lstm_cell
_,initial_state=lstm_cell(self.image_embeddings,zero_state)

定义RNN循环,在这里将句子的特征向量self.seq_embeddings输入到RNN中.sequence_length:图片对应的caption的句子长度。
initial_state:更新后的initial_state。

lstm_outputs, _ = tf.nn.dynamic_rnn(cell=lstm_cell, inputs=self.seq_embeddings,
sequence_length=sequence_length,
initial_state=initial_state,
dtype=tf.float32,
scope=lstm_scope)

在lstm最后添加一个全连接层作为最终的输出
num_outputs:定义输出的维度
weights_initializer:设置权重参数,
该函数默认使用relu的激活函数

logits = tf.contrib.layers.fully_connected(
inputs=lstm_outputs,
num_outputs=10000,
activation_fn=None,
weights_initializer=self.initializer,
scope=logits_scope)

2.原理

  • 构造损失函数

损失函数使用softmax的交叉熵损失函数,target是logits经过向右移动一后得到的caption的id,target经过tf.cast(tf.reshape(self.seq_target,[-1]),dtype=tf.float32)后才能传到交叉熵中计算logits对于target的偏离程度

方法1
losses=tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits, labels=targets)

weights:是一个数值全为1的shape=[batch_size*word_size]的一维数组
因为每个批次的数据都会产生不同的loss值,将每个批次得到的损失值除以批次大小,得到每个批次的平均损失

batch_loss=tf.div(tf.reduce_sum(tf.multiply(losses,weights)),tf.reduce_sum(weights),name=“batch_loss”)
tf.losses.add_loss(batch_loss)
total_loss=tf.losses.get_total_loss()

方法2


正确的答案,这里将[batch_size,num_steps]二维数组转换为一维数组损失的权重。在这里所有的权重都为1,也就是说不同batch和不同时刻的重要程度是一样的。loss=tf.contrib.legacy_seq2seq.sequence_loss_by_example([logits],[tf.reshape(self.targets,[-1][tf.ones([batch_size*num_steps],dtype=tf.float32)] )计算得到每个batch的平均损失total_cost=tf.reduce_sum(loss)/batch_size

3.实验

最初设置learning_rate=2.0
tf.train.exponential_decay(learning_rate,global_step,decay_steps=decay_step,decay_rate=0.5 , staircase=True)
1,global_step:用于衰减计算的全局步数。喂入一次batch_size 计为一次global_step
2,decay_step:衰减速度(num_examples_per_epoch/batch_size)*num_epochs_per_decay
num_example_per_epoch:所有的image_caption的数量
batch_size:batch_size一般设置为2的n次幂,这里设置为32
num_epochs_per_decay设置的是8
3,decay_rate:衰减系数

多项式学习率衰减

polynomial_decay(learning_rate, global_step, decay_steps,end_learning_rate=0.0001, power=1.0,cycle=False, name=None):

在对抗神经网络中使用的一种学习率衰减方法,特点是确定结束的学习率,学习率更新公式是:

decayed_learning_rate = (learning_rate - end_learning_rate) *(1 - global_step / decay_steps) ^ (power) + end_learning_rate

对于神经网络中三个参数的概念:

epoch: 训练时,所有训练数据都训练一次,即所有数据的个数
batch:使用训练集中的一小部分样本对模型进行一次反向传播的参数更新,这一小部分样本称为“一批数据”。
batch_size: 在训练集中选择一组样本用来更新权值。一个batch_size包含的样本数目,通常设为2的n次幂,常用的包括32,64,128,256,网络较小的时候使用256,较大时使用32,或者16.

####实例:
数据集中有50000张训练的图片数量,现在选择batch_size=256对模型进行训练。

  • 每个epoch要训练的图片数量:50000

  • 训练集具有的batch数50000/256=196(向上取整)

  • 每个epoch需要完成的batch数196

  • 每个epoch中发生的模型权重更新次数:196

  • 不同次的epoch训练虽然用的都是训练集的五万张图片,但是对模型的权重跟新值却是不同的,因为不同次的模型处于的loss在空间上的不同位置,模型的训练次数越靠后,越接近谷底,loss也就越小。

优化函数

优化函数使用的是随机梯度下降SGD:SGD是每一次迭代计算mini-batch的梯度,然后对参数进行更新,计算梯度的方法是求偏导,对于训练数据集,我们首先将其分成n个batch,每个batch包含m个样本。我们每次更新都利用一个batch的数据,而非整个训练集、
优点:
当训练数据太多时,将训练集分成一个一个批次,可以减少机器的压力,并且可以更快地收敛

p是概率,因为生成的图片描述不是只有三句,所以三句话的概率和不为零,只是挑选了三句概率最大的打印出来。

QQ浏览器截图20190526085307.png

  • 结果分析
效果由于在训练时loss值没有下降到最小,所以效果不是太好,图中是两个长颈鹿站在草地上,但是在后面两句将长颈鹿预测成大象。

参考链接:

1.在构建读取队列时可以开启多线程:https://zhuanlan.zhihu.com/p/47760620和https://zhuanlan.zhihu.com/p/40588218
2.在lstm的构建和理解:https://www.cnblogs.com/hypnus-ly/p/8407905.html
3.caption的词向量方面:https://www.bilibili.com/video/av35575799/?p=7
4.cnn模型https://blog.csdn.net/loveliuzz/article/details/79135583


http://chatgpt.dhexx.cn/article/XKGqPTaV.shtml

相关文章

OpenCV —— 频率域滤波(傅里叶变换,低通和高通滤波,带通和带阻滤波,同态滤波)

频率域滤波 基本概念傅里叶变换二维离散的傅里叶变换快速傅里叶变换傅里叶幅度谱与相位谱谱残差显著性检测卷积与傅里叶变换的 频率域滤波低通滤波和高通滤波带通和带阻滤波同态滤波 基本概念 频率域滤波 —— 百度百科 频率域滤波是对图像进行傅里叶变换,将图像由…

基于matlab的数字图像基本处理运算

一、实验目的 (1)掌握线性拉伸和非线性拉伸的概念实现方法 (2)掌握图像代数运算的概念和实现方法 (3)掌握图像放大、缩小、平移、镜像、旋转原理和实现方法 (4)掌握最邻近插值和…

实验二 图像增强方法编程与应用

目录 一、实验目的 1. 理解常见图像增强方法的原理和特点; 2. 掌握常见的灰度线性和非线性变换方法; 3. 掌握直方图均衡增强的原理与应用方法; 4. 掌握模板卷积的概念、原理与实现方法 5. 掌握均值滤波的技术原理与实现方法&#xff1b…

PyTorch:tensor、torch.nn、autograd、loss等神经网络学习手册(持续更新)

PyTorch1:tensor2、torch.nn、autograd、loss等神经网络学习手册(持续更新) 链接:画图、读写图片 文章目录 一、tensor二、完整训练过程:数据、模型、可学习参数、保存与加载1、数据dataa、构建网络-数据b、补充知识&…

Android编译libjpeg-turbo so高效压缩图片

https://www.jianshu.com/p/8ebe0ddd21f7 https://www.jianshu.com/p/f305fb008ab6 一 . 图片的基本知识 图像是由像素组成的,而像素实际上是带着坐标的位置和颜色信息的。它是有若干行和若干列的点组成的,他们相交就会有无数个点。假如我们随便取出一个…

(数字图像处理MATLAB+Python)第二章数字图像处理基础-第三、四节:数字图像的生成和数值描述

文章目录 一:数字图像的生成与表示(1)图像信号的数字化(2)数字图像类型 二:数字图像的数值描述(1)常用坐标系(2)数字图像的数据结构(3&#xff09…

MATLAB GUI设计 图像处理基本操作(二)

一、直方图及直方图均衡化 直方图是从图像灰度图中提取的亮度信息,包含灰度级和像素数,对于uint8图像其灰度级为0~255(2^8256),用imhist()函数显示。imhist()/numel可获…

ff

文章目录 1.变数与变量存档1.1变量类型转换1.1.1语法说明1.1.2单一字元1.1.3多元字元1.1.3.1说明1.1.3.2创建对象1.1.3.3逻辑运算和分配 1.2结构体1.2.1存储异构数据的方法1.2.2向结构添加信息2.2.2.1延伸拓展 1.3结构功能1.3.1功能基础语法1.3.2功能语法举例 1.4嵌套结构1.5元…

数字图像处理学习笔记 四 傅里叶变换和频率域滤波

目录 一 预备知识:傅里叶级数的介绍 1、一维傅里叶变换数学推导 2、图像傅里叶变换的物理意义 3、二维傅里叶变换 二、频率域滤波 1、频率域与空间域之间的关系 2、频率域滤波的基本步骤 3、使用频率域滤波平滑图像 4、使用频率域滤波锐化图像 5、选择率滤波…

第五章 DirectX 光照,材质和纹理(下)

在计算机三维世界中,想要模拟出真实的物体,让它的表面看起来更加逼真,就需要使用“纹理映射”技术,简单讲就是一种将2D图像映射到3D物体上面。一般来说,纹理是表示物体表面细节的一幅或多幅2D图像,也称为纹…

数组属性和基本操作

数组属性和基本操作 np.arange(start150,stop0,step-1) 将值倒过来 import numpy as np #matplotlib画图的,也可以读取图片 import matplotlib.pyplot as plt np.arange(150, 1, step-1) 输出 array([150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 1…

灰度增强和去噪

futurehello博客 http://blog.csdn.net/xixi_0921/article/details/50533487 整理笔记 一、前言 图像的灰度变换则不同,其对像素的计算仅仅依赖于当前像素和灰度变换函数。 灰度变换也被称为图像的点运算(只针对图像的某一像素点)是所有图…

Chapter_06 更改图像的对比度和亮度

文章目录 一. 本章目标① 目标② 理论③ 代码 二. 实例① 亮度和对比度调整② 伽马校正③ 纠正曝光不足的图像 三. 图形渲染中的伽马校正(附加资源) 一. 本章目标 ① 目标 本教程中我们将学习如何: 访问像素值用零初始化矩阵学习cv::saturate_cast是做什么的,以及它有什么用获…

MATLAB和Intislim,matlab灰阶变换函数imadjust和stretchlim的c++实现

灰阶变换 首先介绍一下灰阶变换,一幅图像数据本身在存储的数据结构上为一个二维的矩阵,即一幅图像为m*n个密密麻麻的像素点构成。 image.png 然后,这些像素点有着一个值,这个值成为灰度值或者亮度值,值的范围为[0,255]…

一个app开发周期是多久?快速开发才是主流

app的出现,极大的方便了人们的生活、社交和工作,各种各样的app为人们提供了各种便利的服务,真正让移动互联网服务大众。许多行业看到在app上爆发出的巨大潜能,都纷纷主动进行app制作来迎接移动互联网浪潮。 开发app一个很重的问题…

如何开发app软件?程序员揭秘你还没听过的1种方法

如何开发app软件?app软件开发需要多少钱?现在手机app这么火,很多企业都想开发一个app软件开拓市场。但是在开发app的时候往往会感觉力不从心,因为app开发门槛比较高,大家对app软件开发需要的技术、成本并不了解。 现…

商城APP软件开发要素有哪些

商城APP软件体系是当今电商行业经常会运用的商城体系,既支撑企业对企业的运营形式,也支撑卖家对消费者的运营形式,便是现在常见的B2C,B2B的电商形式APP,跟着现在的互联网的遍及现在这些电商都是成为了电商商家开展的不…

app软件怎么开发 盘点3种app制作方式

现在智能手机给大家的生活带来了很多便利,利用手机,随时随地看新闻、手机打车提前预定、网上订餐不用等、商家服务提前预约、学习内容随时看、购物更是随时买。各式各样的手机App,让生活方式方式了重大改变。 1、组建团队开发APP 自己有团队…

app应用软件开发流程是怎样的?

从入职这行业到创业已有 7 载,对 APP 产品开发的流程已经再熟悉不过了,现在把这几年积累的一些经验和大家分享一下,一个产品是怎么从想法一步一步落地为具体成品的,这个过程中会经历一些怎样的必要流程呢,下面大致说一…

三阶魔方傻瓜指南

三阶魔方20分钟完全自救指南——包学包会 前言 寒假宅在家里,闲来无事,偶得一个三阶魔方,便从网上找公式摸索。发现了很多版本,但是大多局部最优,缺少易于小白理解的全局最优方法。所以做次总结,集各家所…