Image Processing 必备(四):Imgaug之增强标记KeyPoints


Date:2020-09-04

官方教程:https://nbviewer.jupyter.org/github/aleju/imgaug-doc/blob/master/notebooks/B01%20-%20Augment%20Keypoints.ipynb

经过前三节官方教程的学习后,对于如何使用imgaug对图像进行图像增强有了一定的了解。其中涉及到比较细致的图像和关键点Keypoints一起增强多核处理等实际问题。但对于KeyPoints和其他标记的具体使用还不是特别清楚。本节以及接下来的5节将会分别介绍关于图像中常用的标记类型的具体使用,包括:

  • Keypoints (本节)

  • BBox

  • Polygons

  • 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

png

shift example

png

project example

png

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

png

to_xy_array example
[[151. 106.]
[247. 78.]
[179. 140.]
[206. 134.]]
from_xy_array example

png

to_distance_maps example

png

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)

png

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))

png

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 )

png

将关键点投射到其他图像上

在实际使用时,常常会因为模型结构输入的影响调整图像的尺寸,KeypointsOnImage.on(image or shape)的功能就是在改变的图像上重新计算keypoints的坐标。

假如将图像非等比缩放成416*416

1 image_change = ia.imresize_single_image(img, 416)
2 ia.imshow(image_change)

png

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:

png

changed image (406, 500, 3) with original keypoints:

png

changed image %s with changed(on) keypoints

png

此处值得记忆的代码使用方式 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))

png

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 ]))

png

使用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 ]))

png

为了提高性能,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)

png

通过运行结果可以看出,将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)

png

将关键点转换为距离图

从最初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)))

png

原来距离图是通过热力图HeatmapsOnImage绘制的,怪不得之前的那么丑

整理总结

本节主要围绕标记之一关键点Keypoints进行介绍,主要介绍KeypointsKeypointsOnImage两个API中的方法。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM