经过前三节官方教程的学习后,对于如何使用imgaug对图像进行图像增强有了一定的了解。其中涉及到比较细致的图像和关键点Keypoints一起增强,多核处理等实际问题。但对于KeyPoints和其他标记的具体使用还不是特别清楚。本节以及接下来的5节将会分别介绍关于图像中常用的标记类型的具体使用,包括:
-
Keypoints (本节)
-
BBox
-
-
Heatmaps
-
Segmentation Maps
-
Line Strings
分别对应不同类型的图像问题,e.g.关键点检测,目标检测,目标分割,直线检测等。
Keypoints/LandMarks
在之前的学习中,也谈及过关键点Keypoints的使用。Keypoints在imgaug中是通过x和y坐标在图像上构成的点。在学术界也常把Keypoints称之为landmarks,通常出现在人体姿态识别领域。
在imgaug中,关键点只会受一些图像几何形态转变增强技巧的影响,例如水平翻转、仿射变换等。其他例如高斯噪声这些并不会对关键点造成影响。
imgaug中提供了两个用于增强关键点的类:Keypoint && KeypointsOnImage。还有一些其他的API,例如增强关键点aug.augment(images=..., keypoints=...) && aug.augment_keypoints()。
API: Keypoint
Keypoint是生成关键点实例最简单的方式,其使用方式为Keypoint(x=..., y=...)。具体方式如下:
1 import imgaug as ia 2 3 keypoint = ia.Keypoint(x=151, y=106)
生成的keypoint具有3种常用的方法:
-
project(from_shape, to_shape)
-
通常用于图像缩放时。
-
-
shift(x=0, y=0)
-
通常使用该方式对keypoint进行位移。
-
-
draw_on_image(img, color=(0, 255, 0), alpha=1.0, size=3, copy=True,raise_if_out_of_image=False)
-
将关键点绘制到图像上,通过color,alpha,size等控制关键点的颜色,透明度和尺寸大小。
-
具体使用详见下述代码(包含shift、 project、draw_on_image):
1 import imageio 2 import imgaug as ia 3 import numpy as np 4 %matplotlib inline 5 img = imageio.imread('./pick1.jpg') 6 # initial 7 keypoint = ia.Keypoint(x=151, y=106) 8 # draw -- draw_on_image 9 print("draw_on_image example") 10 ia.imshow(np.hstack([img, keypoint.draw_on_image(img, color=(255, 255, 0), size=10)])) 11 # shift 12 print("shift example") 13 keypoint_1 = keypoint.shift(x=100, y=10) 14 ia.imshow(np.hstack([img, keypoint_1.draw_on_image(img, color=(255, 0, 0), size=15)])) 15 # resize -- project 16 print("project example") 17 shape = img.shape[0:2] 18 img_resize= ia.imresize_single_image(img, 300) # 非等比缩放 搞成300*300 19 shape_resize = img_resize.shape[0:2] 20 keypoint_2 = keypoint.project(shape, shape_resize) 21 ia.imshow(np.hstack([img_resize, keypoint_2.draw_on_image(img_resize, color=(255, 255, 0), size=10)]))
draw_on_image example
shift example
project example
API:KeypointsImage
KeypointsImage提供了将一组由列表构成的keypoints整合在一起的方法,避免需要对每个keypoint对象进行在图像上的绘制。该列表中包含的keypoint需要是同一张图像的。
KeypointsImage()实例的生成方式为KeypointsOnImage(keypoints, shape),具体方式如下:
1 import imgaug as ia 2 image_keypoints = ia.KeypointsOnImage([ 3 ia.Keypoint(x=151, y=106), 4 ia.Keypoint(x=247, y=78), 5 ia.Keypoint(x=179, y=140), 6 ia.Keypoint(x=206, y=134) 7 ], shape=img.shape)
既然该类的作用是将一张图像上的一系列keypoints整合在一起,那么其首先会包含Keypoint类中具有的方法,其次会有一些将关键点与numpy数组之间的关联,最后还会有与欧式距离图之间的关联。
-
draw_on_image(image, color=(0, 255, 0), alpha=1.0, size=3, copy=True, raise_if_out_of_image=False)
-
shift(x=0, y=0)
-
to_xy_array()
-
from_xy_array(xy, shape)
-
to_distance_maps(inverted=False)
-
from_distance_maps(distance_maps, inverted=False, if_not_found_coords={"x": -1, "y": -1}, threshold=None, nb_channels=None)
具体使用详见下述代码和结果:
1 import imageio 2 import imgaug as ia 3 import numpy as np 4 %matplotlib inline 5 img = imageio.imread('./pick1.jpg') 6 7 image_keypoints = ia.KeypointsOnImage([ 8 ia.Keypoint(x=151, y=106), 9 ia.Keypoint(x=247, y=78), 10 ia.Keypoint(x=179, y=140), 11 ia.Keypoint(x=206, y=134) 12 ], shape=img.shape) 13 # draw_on_img 14 print("draw_on_img example") 15 ia.imshow(np.hstack([img, image_keypoints.draw_on_image(img, color=(255, 255, 0), size=10)])) 16 # to_xy_array() 17 print("to_xy_array example") 18 xy_arr = image_keypoints.to_xy_array() 19 print(xy_arr) 20 # from_xy_array(xy, shape) 21 # 并不能创建一个空的KeypointsOnImage对象,只能在原有的基础上修改,即keypoint发生变化时 22 print("from_xy_array example") 23 image_keypoints_shift = image_keypoints.shift(x=50, y=40) 24 #ia.imshow(np.hstack([img, image_keypoints_shift.draw_on_image(img, color=(255, 255, 0), size=10)])) 25 image_keypoints_shift_1 = image_keypoints_shift.from_xy_array(xy_arr, shape=img.shape) 26 ia.imshow(np.hstack([img, 27 image_keypoints_shift.draw_on_image(img, color=(255, 255, 0), size=10), 28 image_keypoints_shift_1.draw_on_image(img, color=(255, 255, 0), size=10) 29 ])) 30 # to_distance_maps(inverted=False) 31 print("to_distance_maps example") 32 distance_map = image_keypoints.to_distance_maps(inverted=False) 33 ia.imshow(np.hstack([distance_map[:, :, 0], 34 distance_map[:, :, 1], 35 distance_map[:, :, 2], 36 distance_map[:, :, 3]]))
draw_on_img example
to_xy_array example
[[151. 106.]
[247. 78.]
[179. 140.]
[206. 134.]]
from_xy_array example
to_distance_maps example
Example
Basic
1 import imageio 2 import imgaug as ia 3 %matplotlib inline 4 img = imageio.imread('./samoye.jpg') 5 # img = ia.imresize_single_image(img, (300, 200)) # 可以缩放 6 ia.imshow(img)
1 from imgaug.augmentables.kps import Keypoint, KeypointsOnImage 2 kps = [Keypoint(x=277, y=78), 3 Keypoint(x=314, y=73), 4 Keypoint(x=281, y=108)] 5 kpsoi = KeypointsOnImage(kps, shape=img.shape) 6 ia.imshow(kpsoi.draw_on_image(img, size=7))
KeypointsOnImage对象会有keypoints的属性,如下述所示:
print(kpsoi.keypoints)
[Keypoint(x=277.00000000, y=78.00000000), Keypoint(x=314.00000000, y=73.00000000), Keypoint(x=281.00000000, y=108.00000000)]
使用增强手段对图像和关键点进行增强处理:
1 import imgaug.augmenters as iaa 2 ia.seed(3) 3 4 seq = iaa.Sequential([ 5 iaa.Affine(translate_px={"x": (10, 30)}, rotate=(-10, 10)), 6 iaa.AddToHueAndSaturation((-50, 50)) # color jitter, only affects the image 7 ]) 8 image_aug, kpsoi_aug = seq(image=img, keypoints=kpsoi) 9 10 ia.imshow( 11 np.hstack([ 12 kpsoi.draw_on_image(img, size=7), 13 kpsoi_aug.draw_on_image(image_aug, size=7) 14 ]) 15 )
将关键点投射到其他图像上
在实际使用时,常常会因为模型结构输入的影响调整图像的尺寸,KeypointsOnImage.on(image or shape)的功能就是在改变的图像上重新计算keypoints的坐标。
假如将图像非等比缩放成416*416
1 image_change = ia.imresize_single_image(img, 416) 2 ia.imshow(image_change)
1 print("original image %s with keypoints:" %(img.shape,)) 2 ia.imshow(kpsoi.draw_on_image(img, size=7)) 3 4 print("changed image %s with original keypoints:"%(img.shape,)) 5 ia.imshow(kpsoi.draw_on_image(image_change, size=7)) 6 7 print("changed image %s with changed(on) keypoints") 8 ia.imshow(kpsoi.on(image_change).draw_on_image(image_change, size=7))
original image (406, 500, 3) with keypoints:
changed image (406, 500, 3) with original keypoints:
changed image %s with changed(on) keypoints
此处值得记忆的代码使用方式 on: 输入为变换的图像!
ia.imshow(kpsoi.on(image_change).draw_on_image(image_change, size=7))
移动keypoints
on()方法可以应对图像尺寸的改变,可当图像被填充后,发生了位置的偏移,就需要使用shift()方法对关键点进行平移。
1 image_pad = ia.pad(img, left=100) # 左侧填充100个像素 2 kpsoi_pad = kpsoi.shift(x=100) # x位移100 3 ia.imshow(kpsoi_pad.draw_on_image(image_pad, size=7))
shift()方法中x=,y=都是朝着坐标轴正方向移动。
绘制keypoints
1 ia.imshow(np.hstack([ 2 kpsoi.draw_on_image(img, size=1), 3 kpsoi.draw_on_image(img, size=3), 4 kpsoi.draw_on_image(img, size=5), 5 kpsoi.draw_on_image(img, size=7) 6 ]))
使用color字段控制keypoints的颜色:
1 ia.imshow(np.hstack([ 2 kpsoi.draw_on_image(img, size=5, color=(0, 255, 0)), 3 kpsoi.draw_on_image(img, size=5, color=(0, 0, 255)), 4 kpsoi.draw_on_image(img, size=5, color=(255, 128, 255)), 5 kpsoi.draw_on_image(img, size=5, color=(255, 255, 255)) 6 ]))
为了提高性能,draw_on_image()方法还提供了一个copy字段,可以将其设置为False,以便在适当的位置修改图像。
1 image_draw = np.copy(img) 2 kpsoi.draw_on_image(image_draw, size=5, color=(0, 255, 0), copy=False) 3 kpsoi.shift(x=-70).draw_on_image(image_draw, size=5, color=(255, 0, 255), copy=False) 4 kpsoi.shift(x=70).draw_on_image(image_draw, size=5, color=(0, 0, 0), copy=False) 5 ia.imshow(image_draw)
通过运行结果可以看出,将copy字段设置为False,将会将关键点直接绘制到原图像上。
另外,对于关键点的颜色,当关键点个数较多时,手动设置可能比较繁琐,可以直接将其写到一个颜色列表中。在绘制时使用zip的循环方式进行绘制。 虽然,这并不是imgaug中提供的方法。
1 colors = [(0, 255, 0), 2 (255, 255, 255), 3 (128, 255, 64)] 4 image_drawn = np.copy(img) 5 for kp, color in zip(kpsoi.keypoints, colors): 6 image_drawn = kp.draw_on_image(image_drawn, color=color, size=9, copy=False) 7 ia.imshow(image_drawn)
将关键点转换为距离图
从最初API介绍中,限于个人能力,展示出的距离图是黑白的,并没有paper中展示的那种高大上。这里再一探究竟吧!!!
to_distance_maps()
首先,看一下生成的distance_maps的属性
1 distance_maps = kpsoi.to_distance_maps() 2 print("Image shape:", kpsoi.shape) 3 print("Distance maps shape:", distance_maps.shape) 4 print("Distance maps dtype:", distance_maps.dtype) 5 print("Distance maps min:", distance_maps.min(), "max:", distance_maps.max())
Image shape: (406, 500, 3)
Distance maps shape: (406, 500, 3)
Distance maps dtype: float32
Distance maps min: 0.0 max: 456.96826
** 可以看出,其相当于是对于每一个关键点的一个距离二维矩阵。**
从上述返回的距离矩阵可以看出,距离矩阵的值并没有进行标准化。所以,首先根据返回的最大值和最小值将其归一化。
1 height, width = kpsoi.shape[0:2] 2 max_distance = np.linalg.norm(np.float32([height, width])) 3 distance_maps_normalized = distance_maps / max_distance 4 print("min:", distance_maps.min(), "max:", distance_maps_normalized.max())
min: 0.0 max: 0.7094925
1 from imgaug.augmentables.heatmaps import HeatmapsOnImage 2 heatmaps = HeatmapsOnImage(distance_maps_normalized, shape=kpsoi.shape) 3 ia.imshow(np.hstack(heatmaps.draw_on_image(img)))
原来距离图是通过热力图HeatmapsOnImage绘制的,怪不得之前的那么丑
整理总结
本节主要围绕标记之一关键点Keypoints进行介绍,主要介绍Keypoints和KeypointsOnImage