学习笔记TF015:加载图像、图像格式、图像操作、颜色

TensorFlow支持JPG、PNG图像格式,RGB、RGBA颜色空间。图像用与图像尺寸相同(heightwidthchnanel)张量表示。通道表示为包含每个通道颜色数量标量秩1张量。图像所有像素存在磁盘文件,需要被加载到内存。

图像加载与二进制文件相同。图像需要解码。输入生成器(tf.train.string_input_producer)找到所需文件,加载到队列。tf.WholeFileReader加载完整图像文件到内存,WholeFileReader.read读取图像,tf.image.decode_jpeg解码JPEG格式图像。图像是三阶张量。RGB值是一阶张量。加载图像格式为[batch_size,image_height,image_width,channels]。批数据图像过大过多,占用内存过高,系统会停止响应。

大尺寸图像输入占用大量系统内存。训练CNN需要大量时间,加载大文件增加更多训练时间,也难存放多数系统GPU显存。大尺寸图像大量无关本征属性信息,影响模型泛化能力。

tf.image.decode_jpeg解码JPEG格式图像。tf.image.decode_png解码PNG格式图像。 差别在alpha(透明度)信息。移除区域alpha值设0,有助于标识。JPEG图像频繁操作会留下伪影(atrifact)。PNG格式无损压缩,保留原始文件全部信息(被缩放或降采样除外),文件体积较大。

TensorFlow内置文件格式TFRecord,二进制数据和训练类别标签数据存储在同一文件。模型训练前图像转换为TFRecord格式。TFRecord文件是protobuf格式。数据不压缩,可快速加载到内存。

独热编码(one-hot encoding)格式,表示多类分类(单)标签数据。图像加载到内存,转换为字节数组,添加到tf.train.Example文件,SerializeToString 序列化为二进制字符,保存到磁盘。序列化将内存对象转换为可安全传输文件格式,可被加载,可被反序列化为样本格式。直接加载TFRecord文件,可以节省训练时间。支持写入多个样本。

TFRecordReader对象读取TFRecord文件。tf.parse_single_example不解码图像,解析TFRecord,图像按原始字节读取(tf.decode-raw)。tf.reshape调整形状,使布局符合tf.nn.conv2d要求([image_height,image_width,image_channels])。tf.expand扩展维数,把batch_size维添加到input_batch。tf.equal检查是否加载同一图像。sess.run(tf.cast(tf_record_features['label'], tf.string))查看从TFRecord文件加载的标签。使用图像数据推荐使用TFRecord文件存储数据与标签。做好图像预处理并保存结果。

最好在预处理阶段完成图像操作,裁剪、缩放、灰度调整等。图像加载后,翻转、扭曲,使输入网络训练信息多样化,缓解过拟合。Python图像处理框架PIL、OpenCV。TensorFlow提供部分图像处理方法。裁剪,tf.image.central_crop,移除图像区域,完全丢弃其中信息,与tf.slice(移除张量分量)类似,基于图像中心返回结果。训练时,如果背景有用,tf.image.crop_to_bounding_box(只接收确定形状张量,输入图像需要事先在数据流图运行) 随机裁剪区域起始位置到图像中心的偏移量。

tf.image.pad_to_bounding_box 用0填充边界,使输入图像符合期望尺寸。尺寸过大过小图像,边界填充灰度值0像素。tf.image.resize_image_with_crop_or_pad,相对图像中心,裁剪或填充同时进行。

翻转,每个像素位置沿水平或垂真方向翻转。随机翻转图像,可以防止过拟合。tf.slice选择图像数据子集。tf.image.flip_left_right 完成水平翻转。tf.image.flip_up_down 完成垂直翻转。seed参数控制翻转随机性。

编辑过图像训练,误导CNN模型。属性随机修改,使CNN精确匹配编辑过或不同光照图像特征。tf.image.adjust_brightness 调整灰度。tf.image.adjust_contrast 调整对比度。调整对比度,选择较小增量,避免“过曝”,达到最大值无法恢复,可能全白全黑。tf.slice 突出改变像素。tf.image.adjust_hue 调整色度,色彩更丰富。delta参数控制色度数量。tf.image.adjust_saturation 调整饱和度,突出颜色变化。

单一颜色图像,灰度颜色空间,单颜色通道,只需要单个分量秩1张量。缩减颜色空间可以加速训练。灰度图具有单个分量,取值范围[0,255]。tf.image.rgb_to_grayscale 把RGB图像转换为灰度图。灰度变换,每个像素所有颜色值取平均。tf.image.rgb_to_hsv RGB图像转换为HSV, 色度、饱和度、灰度构成HSV颜色空间,3个分量秩1张量。更贴近人类感知属性。HSB,B亮度值。tf.image.hsv_to_rgb HSV图像转换为RGB,tf.image.grayscale_to_rgb 灰度图像转换为RGB。python-colormath提供LAB颜色空间,颜色差异映射贴近人类感知,两个颜色欧氏距离反映人类感受的颜色差异。

tf.image.convert_image_dtype(image, dtype,saturate=False) 图像数据类型变化,像素值比例变化。

import tensorflow as tf
sess = tf.Session()
red = tf.constant([255, 0, 0])
file_names = ['./images/chapter-05-object-recognition-and-classification/working-with-images/test-input-image.jpg']
filename_queue = tf.train.string_input_producer(file_names)
image_reader = tf.WholeFileReader()
_, image_file = image_reader.read(filename_queue)
image = tf.image.decode_jpeg(image_file)
sess.run(tf.global_variables_initializer())
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(sess=sess,coord=coord)
print sess.run(image)
filename_queue.close(cancel_pending_enqueues=True)
coord.request_stop()
coord.join(threads)
print "------------------------------------------------------"
image_label = b'\x01'
image_loaded = sess.run(image)
image_bytes = image_loaded.tobytes()
image_height, image_width, image_channels = image_loaded.shape
writer = tf.python_io.TFRecordWriter("./output/training-image.tfrecord")
example = tf.train.Example(features=tf.train.Features(feature={
        'label': tf.train.Feature(bytes_list=tf.train.BytesList(value=[image_label])),
        'image': tf.train.Feature(bytes_list=tf.train.BytesList(value=[image_bytes]))
    }))
print example
writer.write(example.SerializeToString())
writer.close()
print "------------------------------------------------------"
tf_record_filename_queue = tf.train.string_input_producer(["./output/training-image.tfrecord"])
tf_record_reader = tf.TFRecordReader()
_, tf_record_serialized = tf_record_reader.read(tf_record_filename_queue)
tf_record_features = tf.parse_single_example(
tf_record_serialized,
features={
    'label': tf.FixedLenFeature([], tf.string),
    'image': tf.FixedLenFeature([], tf.string),
    })
tf_record_image = tf.decode_raw(
    tf_record_features['image'], tf.uint8)
tf_record_image = tf.reshape(
    tf_record_image,
    [image_height, image_width, image_channels])
print tf_record_image
tf_record_label = tf.cast(tf_record_features['label'], tf.string)
print tf_record_label
print "------------------------------------------------------"
sess.close()
sess = tf.Session()
sess.run(tf.global_variables_initializer())
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(sess=sess,coord=coord)
print sess.run(tf.equal(image, tf_record_image))
sess.run(tf_record_label)
coord.request_stop()
coord.join(threads)
print "------------------------------------------------------"
print sess.run(tf.image.central_crop(image, 0.1))
real_image = sess.run(image)
bounding_crop = tf.image.crop_to_bounding_box(
    real_image, offset_height=0, offset_width=0, target_height=2, target_width=1)
print sess.run(bounding_crop)
print "------------------------------------------------------"
real_image = sess.run(image)
pad = tf.image.pad_to_bounding_box(
    real_image, offset_height=0, offset_width=0, target_height=4, target_width=4)
print sess.run(pad)
print "------------------------------------------------------"
crop_or_pad = tf.image.resize_image_with_crop_or_pad(
    real_image, target_height=2, target_width=5)
print sess.run(crop_or_pad)
print "------------------------------------------------------"
sess.close()
sess = tf.Session()
top_left_pixels = tf.slice(image, [0, 0, 0], [2, 2, 3])
flip_horizon = tf.image.flip_left_right(top_left_pixels)
flip_vertical = tf.image.flip_up_down(flip_horizon)
sess.run(tf.global_variables_initializer())
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(sess=sess,coord=coord)
print sess.run([top_left_pixels, flip_vertical])
print "------------------------------------------------------"
top_left_pixels = tf.slice(image, [0, 0, 0], [2, 2, 3])
random_flip_horizon = tf.image.random_flip_left_right(top_left_pixels)
random_flip_vertical = tf.image.random_flip_up_down(random_flip_horizon)
print sess.run(random_flip_vertical)
print "------------------------------------------------------"
example_red_pixel = tf.constant([254., 2., 15.])
adjust_brightness = tf.image.adjust_brightness(example_red_pixel, 0.2)
print sess.run(adjust_brightness)
print "------------------------------------------------------"
adjust_contrast = tf.image.adjust_contrast(image, -.5)
print sess.run(tf.slice(adjust_contrast, [1, 0, 0], [1, 3, 3]))
print "------------------------------------------------------"
adjust_hue = tf.image.adjust_hue(image, 0.7)
print sess.run(tf.slice(adjust_hue, [1, 0, 0], [1, 3, 3]))
print "------------------------------------------------------"
adjust_saturation = tf.image.adjust_saturation(image, 0.4)
print sess.run(tf.slice(adjust_saturation, [1, 0, 0], [1, 3, 3]))
print "------------------------------------------------------"
gray = tf.image.rgb_to_grayscale(image)
print sess.run(tf.slice(gray, [0, 0, 0], [1, 3, 1]))
print "------------------------------------------------------"
hsv = tf.image.rgb_to_hsv(tf.image.convert_image_dtype(image, tf.float32))
print sess.run(tf.slice(hsv, [0, 0, 0], [3, 3, 3]))
print "------------------------------------------------------"
rgb_hsv = tf.image.hsv_to_rgb(hsv)
rgb_grayscale = tf.image.grayscale_to_rgb(gray)
print rgb_hsv, rgb_grayscale
print "------------------------------------------------------"

参考资料:
《面向机器智能的TensorFlow实践》

欢迎加我微信交流:qingxingfengzi
我的微信公众号:qingxingfengzigz
我老婆张幸清的微信公众号:qingqingfeifangz

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,636评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,890评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,680评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,766评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,665评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,045评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,515评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,182评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,334评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,274评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,319评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,002评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,599评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,675评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,917评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,309评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,885评论 2 341

推荐阅读更多精彩内容