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