和网络没有比较大的关系,而是在数据层面做处理。
比较常用的方法有:归一化、图像变换、色彩变换、多尺度。
归一化:
将数据归一化到一定的区间内,使网络更容易学习。
图像变换:
也就是为了使数据变多,方式有:对图像进行翻转、拉伸、裁剪、变形等。
色彩变换:
可以改变图像的对比度、亮度等。
多尺度:
就是将图像裁剪到不同大小。也就是使神经网络能够看到更多层面的图像信息,也能达到增加数据的效果。
eg:将某张图像缩减到256 * 256,之后裁剪224 * 224的块,其比例就是 224/256。多尺度可以是,将图像缩减为非 256 * 256的大小,然后用224采样。
1. 导入需要用到的数据包:
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
from matplotlib.pyplot import imshow
2. 显示原始图片
name = './gugong.jpg' # 图片路径
img_string = tf.read_file(name) # read_file :是将图片以字符串的形式进行读入
img_decoded = tf.image.decode_image(img_string) # 将 string 解析成一个图片
sess = tf.Session() # 启动进程
img_decoded_val = sess.run(img_decoded)
print(img_decoded_val.shape)
%matplotlib inline
# 在文档中显示图片
imshow(img_decoded_val)
结果:
常用的缩放 API:
(1)tf.image.resize_area
(2)tf.image.resize_bicubic :
用二次线性插值法对图片进行缩放,就是当图片缩小的时候,是没有损失的,直接压缩图片即可;
当图片进行放大的时候,像素使用二次线性函数的一个计算公式去进行计算的
(3)tf.image.resize_nearest_neighbor :
在放大的过程中,使用最相近的像素点去做该像素的一个值;缩小的时候,直接缩小就可以了
下面采用resize_bicubic这个API进行实现(按照出现问题并解决的方式):
name = './gugong.jpg'
img_string = tf.read_file(name) # read_file :是将图片以字符串的形式进行读入
img_decoded = tf.image.decode_image(img_string) # 将 string 解析成一个图片
resize_img = tf.image.resize_bicubic(img_decoded, [1328, 2400]) # 将图像的长和宽都扩大两倍,原来是[664, 1200]
sess = tf.Session()
img_decoded_val = sess.run(resize_img)
print(img_decoded_val.shape)
%matplotlib inline
# 在文档中显示图片
imshow(img_decoded_val)
这里与前面的“显示原始图片”大致是一样的。不同点在于,sess run的不是原始图片,而是对原始图片进行了一步缩放后的图片。缩放步骤是中间断开的位置。
但是!!!
运行程序出错了!!!(看报错的最后位置)
这一原因在于,input必须是一个四维的向量。因为这些API都是给模型训练进行使用的,而在模型训练中一般都是minibatch(批训练)的,一个minibatch中一般会有多张图片,所以tensorflow中的API设计一般都是针对多张图片去进行操作的,所以这里需要添加reshape操作。
同时由于这里只有一张图片,所以说要变成四维的向量,第一维设置为1。
更改程序为:
name = './gugong.jpg'
img_string = tf.read_file(name) # read_file :是将图片以字符串的形式进行读入
img_decoded = tf.image.decode_image(img_string) # 将 string 解析成一个图片
img_decoded = tf.reshape(img_decoded,[1, 664, 1200, 3]) # 最后一维是通道数
resize_img = tf.image.resize_bicubic(img_decoded, [1328, 2400]) # 将图像的长和宽都扩大两倍,原来是[664, 1200]
sess = tf.Session()
img_decoded_val = sess.run(resize_img)
img_decoded_val = img_decoded_val.reshape((1328, 2400, 3))
print(img_decoded_val.shape)
%matplotlib inline
# 在文档中显示图片
imshow(img_decoded_val)
注意:这里得到的值是一个混乱的一个图像。究其原因在于,做了线性插值之后,它的数值类型就变成了float值了,所以还需要将它变成int型的一个值。
这里有一个问题,为什么float显示的就是混乱的呢?
这是由于imshow所导致的。它的函数具有一定的局限性,不能自动的将float的图像变成int的图像。
再次更改程序:
name = './gugong.jpg'
img_string = tf.read_file(name) # read_file :是将图片以字符串的形式进行读入
img_decoded = tf.image.decode_image(img_string) # 将 string 解析成一个图片
img_decoded = tf.reshape(img_decoded,[1, 664, 1200, 3]) # 最后一维是通道数
resize_img = tf.image.resize_bicubic(img_decoded, [1328, 2400]) # 将图像的长和宽都扩大两倍,原来是[664, 1200]
sess = tf.Session()
img_decoded_val = sess.run(resize_img)
img_decoded_val = img_decoded_val.reshape((1328, 2400, 3))
img_decoded_val = np.array(img_decoded_val, np.uint8)
print(img_decoded_val.shape)
%matplotlib inline
# 在文档中显示图片
imshow(img_decoded_val)
在tensorflow中对图像进行裁剪的API有很多,这里列举几个:
(1)tf.image.pad_to_bounding_box:将图像放到一个画布上,然后图像的前后左右可以用pad去填充,从而使得图像的周边都是黑色的,中间就是我们的原始图像。
(2)tf.image.crop_to_bounding_box:在图像上用一个框去进行裁剪,然后得到一张新的图像
上面两个的区别在于:一个是填充,一个是裁剪
(3)tf.random_crop:随机的在原始图像上进行裁剪
下面以tf.image.pad_to_bounding_box为例:
name = './gugong.jpg'
img_string = tf.read_file(name) # read_file :是将图片以字符串的形式进行读入
img_decoded = tf.image.decode_image(img_string) # 将 string 解析成一个图片
img_decoded = tf.reshape(img_decoded,[1, 664, 1200, 3]) # 最后一维是通道数
padded_img = tf.image.pad_to_bounding_box(img_decoded,50,100,750,1400)
# 50,100:原始图像在新画布上的位置是什么
# 750,1400:画布的大小是多少
sess = tf.Session()
img_decoded_val = sess.run(padded_img)
img_decoded_val = img_decoded_val.reshape((750,1400,3))
img_decoded_val = np.array(img_decoded_val, np.uint8)
print(img_decoded_val.shape)
%matplotlib inline
# 在文档中显示图片
imshow(img_decoded_val)
这里需要注意一个问题,就是tf.image.pad_to_bounding_box中的最后两位数字(画布的大小),这两位数字需要大于原来图片的大小(也就是这里的(750,1400)> (664,1200));否则就会报错。
(1) tf.image.flip_up_down:上下翻转
(2)tf.image.flip_left_right:左右翻转
(3)tf.image.random_flip_up_down:随机上下翻转
(4)tf.image.random_flip_left_right:随机的左右翻转
以对图像进行上下翻转为例:
name = './gugong.jpg'
img_string = tf.read_file(name) # read_file :是将图片以字符串的形式进行读入
img_decoded = tf.image.decode_image(img_string) # 将 string 解析成一个图片
img_decoded = tf.reshape(img_decoded,[1, 664, 1200, 3]) # 最后一维是通道数
flipped_img = tf.image.flip_up_down(img_decoded)
sess = tf.Session()
img_decoded_val = sess.run(flipped_img)
img_decoded_val = img_decoded_val.reshape((664, 1200,3))
img_decoded_val = np.array(img_decoded_val, np.uint8)
print(img_decoded_val.shape)
%matplotlib inline
# 在文档中显示图片
imshow(img_decoded_val)
常用API:
(1)tf.image.adjust_brightness:有一个参数设置调整的程度
(2)tf.image.random_brightness:随机的调整光照
(3)tf.image.adjust_contrast:改变对比度
(4)tf.image.random_contrast:
以下以tf.image.adjust_brightness为例:
name = './gugong.jpg'
img_string = tf.read_file(name) # read_file :是将图片以字符串的形式进行读入
img_decoded = tf.image.decode_image(img_string) # 将 string 解析成一个图片
img_decoded = tf.reshape(img_decoded,[1, 664, 1200, 3]) # 最后一维是通道数
new_img = tf.image.adjust_brightness(img_decoded , -0.5)
# 参数:控制改变光照幅的大小,比如 -0.5 就是将普遍你的光照强度变成原来的 50%
sess = tf.Session()
img_decoded_val = sess.run(new_img)
img_decoded_val = img_decoded_val.reshape((664, 1200,3))
img_decoded_val = np.array(img_decoded_val, np.uint8)
print(img_decoded_val.shape)
%matplotlib inline
# 在文档中显示图片
imshow(img_decoded_val)