一、tensorflow实现图像大小重调
## Resizing
* @{tf.image.resize_images}
* @{tf.image.resize_area}
* @{tf.image.resize_bicubic}
* @{tf.image.resize_bilinear}
* @{tf.image.resize_nearest_neighbor}
resize_images是总的接口,该接口的参数如下:
resize_images(images, size, method=ResizeMethod.BILINEAR, align_corners=False)
形参:
images:shape 为`[batch, height, width, channels]`的4-D图像张量或者shape为 `[height, width, channels]`的3-D图像张量,如果传入图像张量不兼容所制定规则会报错
size:一个dtype为int32拥有两个元素的1-D张量,格式为[new_height, new_width]
method:resize使用的方法,有四种方式,分别为:
ResizeMethod.BILINEAR --> 双线性内插,其核心思想是在两个方向分别进行一次线性插值。
ResizeMethod.NEAREST_NEIGHBOR --> 最近邻插值法,将变换后的图像中的原像素点最邻近像素的灰度值赋给原像素点的方法,返回图像张量dtype与所传入的相同。
ResizeMethod.BICUBIC --> 双三次插值,双三次插值是一种更加复杂的插值方式,它能创造出比双线性插值更平滑的图像边缘。
ResizeMethod.AREA --> 基于区域的图像插值算法,首先将原始低分辨率图像分割成不同区域,然后将插值点映射到低分辨率图像, 判断其所属区域, 最后根据插值点的邻域像素设计不同的插值公式, 计算插值点的值。
align_corners:精确对准输入输出图像的四个角,默认为false不精确对准。
return:dtype为float的3-D或4-D图像张量,其shape分别为[batch, new_height, new_width, channels]和[new_height, new_width, channels]
而其余四个接口则是具体的不同实现图像缩放处理的方法,他们的参数都形如:
(images, size, align_corners=False, name=None)
第一个参数要求其shape一定是形如[batch, height, width, channels]的4-D格式,中间两个参数如resize_image所解释,后一个name是操作的名称,可有可无。
下面是用matplotlib来显示四种不同缩放处理方法后的图像对比图自写源代码例子,之所以不用opencv来显示那是因为它的format是BGR格式会导致图像显示颜色异常:
import tensorflow as tf
import matplotlib.pyplot as plt
img_name = ["/home/xsr-ai/study/beautiful.jpg"]
filename_queue = tf.train.string_input_producer(img_name)
img_reader = tf.WholeFileReader()
_,image_jpg = img_reader.read(filename_queue)
image_decode_jpeg = tf.image.decode_png(image_jpg)
image_decode_jpeg = tf.image.convert_image_dtype(image_decode_jpeg, dtype=tf.float32)
sess = tf.Session()
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(sess=sess, coord=coord)
image_bilinear = tf.image.resize_images(image_decode_jpeg, size=[1200,1920], method=tf.image.ResizeMethod.BILINEAR)
image_nearest_neighbor = tf.image.resize_images(image_decode_jpeg, size=[728,1280], method=tf.image.ResizeMethod.NEAREST_NEIGHBOR)
image_bicubic = tf.image.resize_images(image_decode_jpeg, size=[720,1440], method=tf.image.ResizeMethod.BICUBIC)
image_area = tf.image.resize_images(image_decode_jpeg, size=[1080,1920], method=tf.image.ResizeMethod.AREA)
print(image_bicubic.shape)
print(image_bicubic.dtype)
plt.figure()
plt.subplot(221)
plt.imshow(sess.run(image_bilinear))
plt.title("bilinear interpolation")
plt.subplot(222)
plt.imshow(sess.run(image_nearest_neighbor))
plt.title("nearest neighbor interpolation")
plt.subplot(223)
plt.imshow(sess.run(tf.image.convert_image_dtype(image_bicubic, dtype=tf.uint8)))
plt.title("bicubic interpolation")
plt.subplot(224)
plt.imshow(sess.run(tf.image.convert_image_dtype(image_area, dtype=tf.float32)))
plt.title("area interpolation")
plt.show()
效果如下图,可通过坐标来对比一下大小上的差异!
二、tensorflow实现图像标注
## Working with Bounding Boxes
* @{tf.image.draw_bounding_boxes}
* @{tf.image.non_max_suppression}
* @{tf.image.sample_distorted_bounding_box}
1)tf.image.draw_bounding_boxes介绍
形参:
(images, boxes, name=None)
images:这必须是一个dtype为float32且其shape为[batch, height, width, depth]的图像,我们得需要用到tf.image.convert_image_dtype来转换图像数据为float32,然后用tf.expand_dims来扩展图像的维度。
boxes:一个dtype为float32且其shape为[batch, num_bounding_boxes, 4],其格式为[y_min, x_min, y_max, x_max],这样我们会得到一个左下角和右上角的边框坐标系,比如图像为[h,w],那么我们得到左下角坐标[x_min*w, y_min*h],右下角坐标[x_max*w, y_max*h],这样即可画出一个边框。
name:操作的名字。
return:返回一个已经画好N个边框(N大于等于1)的图像。
这个函数我们可以拿来做变宽标注!
2)tf.image.non_max_suppression介绍
形参:
(boxes, scores, max_output_size, iou_threshold=0.5, name=None)
boxes:dtype为float且shape为[num_boxes, 4]的一系列矩形框
scores:dtype为float且share为[num_boxes]对应于boxes每个矩形框的分数
max_output_size:表示输出由非极大值抑制得到的矩形框的最大数量
iou_threshold:iou阈值,表示不超过与iou重叠的边框数量阈值
return:返回一个经过极大值抑制刷选了的边框切片
官方所给的例程如下:
selected_indices = tf.image.non_max_suppression(boxes, scores, max_output_size, iou_threshold)
selected_boxes = tf.gather(boxes, selected_indices)
该接口会根据非极大值抑制贪婪选择一些符合要求的边框坐标系以供我们使用!
2)tf.image.sample_distorted_bounding_box
形参:
(image_size, bounding_boxes, seed=None,
seed2=None, min_object_covered=None,
aspect_ratio_range=None, area_range=None,
max_attempts=None,
use_image_if_no_bounding_boxes=None,
name=None)
image_size:图像的大小,其格式为[height, width, channels],且其dtype只能是`uint8`, `int8`, `int16`, `int32`, `int64`的某一种
bounding_boxes:dtype为float且其shape为[batch, N, 4]的张量,batch表示图像的多个张,N表示有多少个box
seed/seed2:随机种子,如果非零则供随机生成器使用,否则由seed/seed2生成
min_object_covered:图像裁剪区域必须包含bounding_boxes内由其指定大小的内容,默认为0.1
aspect_ratio_range:宽高比缩放范围,默认为[0.75, 1.33]
area_range:图像裁剪区域必须包含有由这个参数定义范围的内容,默认是[0.05, 1]
max_attempts:约束生成裁剪区域的尝试最大次数,默认为100,如果失败则返回整张图像
use_image_if_no_bounding_boxes:True代笔如果没有边界框则默认使用整张图像,否则会报错,默认为false
return:返回(begin, size, bboxes),begin指定了多维张量的一个开始位置,size则表示从开始位置截断多少行多少列的数据,前两个参数一般供tf.slice使用,而bboxes则是一个经过变形了的边框,可直接使用tf.image.draw_bounding_boxes画出来!
官方提供的一个历程如下:
```python
# Generate a single distorted bounding box.
begin, size, bbox_for_draw = tf.image.sample_distorted_bounding_box(
tf.shape(image),
bounding_boxes=bounding_boxes)
# Draw the bounding box in an image summary.
image_with_box = tf.image.draw_bounding_boxes(tf.expand_dims(image, 0),
bbox_for_draw)
tf.image_summary('images_with_box', image_with_box)
# Employ the bounding box to distort the image.
distorted_image = tf.slice(image, begin, size)
```
以下是使用tf.image.draw_bounding_boxes画出的一个矩形框的源代码:
import tensorflow as tf
import matplotlib.pyplot as plt
img_name = ["/home/xsr-ai/study/beautiful.jpg"]
filename_queue = tf.train.string_input_producer(img_name)
img_reader = tf.WholeFileReader()
_,image_jpg = img_reader.read(filename_queue)
image_decode_jpeg = tf.image.decode_jpeg(image_jpg)
image_decode_jpeg = tf.image.convert_image_dtype(image_decode_jpeg, dtype=tf.float32)
img = image_decode_jpeg
image_decode_jpeg = tf.expand_dims(image_decode_jpeg, 0)
sess = tf.Session()
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(sess=sess, coord=coord)
box = tf.constant([[[0.2, 0.6, 0.5, 0.8]]])
image_bilinear = tf.image.draw_bounding_boxes(sess.run(image_decode_jpeg), box)
image_bilinear = tf.reshape(image_bilinear, [1200, 1920, 3])
plt.figure()
plt.subplot(121)
plt.imshow(sess.run(image_bilinear))
plt.axis('off')
plt.subplot(122)
plt.imshow(sess.run(img))
plt.axis('off')
plt.show()
效果如下图所示: