經過前三節官方教程的學習后,對於如何使用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