Skip to content

Commit 1c94293

Browse files
author
committed
fix for issue leetenki#13
1 parent 26524e2 commit 1c94293

File tree

1 file changed

+70
-42
lines changed

1 file changed

+70
-42
lines changed

lib/image_generator.py

+70-42
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from PIL import Image
66
from lib.utils import *
77

8+
89
# src_imageの背景画像に対して、overlay_imageのalpha画像を貼り付ける。pos_xとpos_yは貼り付け時の左上の座標
910
def overlay(src_image, overlay_image, pos_x, pos_y):
1011
# オーバレイ画像のサイズを取得
@@ -16,75 +17,93 @@ def overlay(src_image, overlay_image, pos_x, pos_y):
1617
overlay_image_RGBA = cv2.cvtColor(overlay_image, cv2.COLOR_BGRA2RGBA)
1718

1819
# PILに変換
19-
src_image_PIL=Image.fromarray(src_image_RGBA)
20-
overlay_image_PIL=Image.fromarray(overlay_image_RGBA)
20+
src_image_PIL = Image.fromarray(src_image_RGBA)
21+
overlay_image_PIL = Image.fromarray(overlay_image_RGBA)
2122

2223
# 合成のため、RGBAモードに変更
2324
src_image_PIL = src_image_PIL.convert('RGBA')
2425
overlay_image_PIL = overlay_image_PIL.convert('RGBA')
2526

2627
# 同じ大きさの透過キャンパスを用意
27-
tmp = Image.new('RGBA', src_image_PIL.size, (255, 255,255, 0))
28+
tmp = Image.new('RGBA', src_image_PIL.size, (255, 255, 255, 0))
2829
# 用意したキャンパスに上書き
2930
tmp.paste(overlay_image_PIL, (pos_x, pos_y), overlay_image_PIL)
3031
# オリジナルとキャンパスを合成して保存
3132
result = Image.alpha_composite(src_image_PIL, tmp)
3233

33-
return cv2.cvtColor(np.asarray(result), cv2.COLOR_RGBA2BGRA)
34+
return cv2.cvtColor(np.asarray(result), cv2.COLOR_RGBA2BGRA)
35+
3436

3537
# 画像周辺のパディングを削除
36-
def delete_pad(image):
38+
def delete_pad(image):
3739
orig_h, orig_w = image.shape[:2]
38-
mask = np.argwhere(image[:, :, 3] > 128) # alphaチャンネルの条件、!= 0 や == 255に調整できる
39-
(min_y, min_x) = (max(min(mask[:, 0])-1, 0), max(min(mask[:, 1])-1, 0))
40-
(max_y, max_x) = (min(max(mask[:, 0])+1, orig_h), min(max(mask[:, 1])+1, orig_w))
40+
mask = np.argwhere(image[:, :, 3] > 128) # alphaチャンネルの条件、!= 0 や == 255に調整できる
41+
(min_y, min_x) = (max(min(mask[:, 0]) - 1, 0), max(min(mask[:, 1]) - 1, 0))
42+
(max_y, max_x) = (min(max(mask[:, 0]) + 1, orig_h), min(max(mask[:, 1]) + 1, orig_w))
4143
return image[min_y:max_y, min_x:max_x]
4244

45+
4346
# 画像を指定した角度だけ回転させる
4447
def rotate_image(image, angle):
4548
orig_h, orig_w = image.shape[:2]
46-
matrix = cv2.getRotationMatrix2D((orig_h/2, orig_w/2), angle, 1)
49+
matrix = cv2.getRotationMatrix2D((orig_h / 2, orig_w / 2), angle, 1)
4750
return cv2.warpAffine(image, matrix, (orig_h, orig_w))
4851

52+
4953
# 画像をスケーリングする
5054
def scale_image(image, scale):
5155
orig_h, orig_w = image.shape[:2]
52-
return cv2.resize(image, (int(orig_w*scale), int(orig_h*scale)))
56+
return cv2.resize(image, (int(orig_w * scale), int(orig_h * scale)))
57+
5358

5459
# 背景画像から、指定したhとwの大きさの領域をランダムで切り抜く
55-
def random_sampling(image, h, w):
60+
def random_sampling(image, h, w):
5661
orig_h, orig_w = image.shape[:2]
57-
y = np.random.randint(orig_h-h+1)
58-
x = np.random.randint(orig_w-w+1)
59-
return image[y:y+h, x:x+w]
62+
y = np.random.randint(orig_h - h + 1)
63+
x = np.random.randint(orig_w - w + 1)
64+
return image[y:y + h, x:x + w]
65+
6066

6167
# 画像をランダムに回転、スケールしてから返す
6268
def random_rotate_scale_image(image, min_scale, max_scale, rand_angle):
63-
image = rotate_image(image, np.random.randint(rand_angle*2)-rand_angle)
64-
image = scale_image(image, min_scale + np.random.rand() * (max_scale-min_scale)) # 1 ~ 3倍
69+
image = rotate_image(image, np.random.randint(rand_angle * 2) - rand_angle)
70+
image = scale_image(image, min_scale + np.random.rand() * (max_scale - min_scale)) # 1 ~ 3倍
6571
return delete_pad(image)
6672

73+
6774
# overlay_imageを、src_imageのランダムな場所に合成して、そこのground_truthを返す。
6875
def random_overlay_image(src_image, overlay_image, minimum_crop):
6976
src_h, src_w = src_image.shape[:2]
7077
overlay_h, overlay_w = overlay_image.shape[:2]
71-
shift_item_h, shift_item_w = overlay_h * (1-minimum_crop), overlay_w * (1-minimum_crop)
72-
scale_item_h, scale_item_w = overlay_h * (minimum_crop*2-1), overlay_w * (minimum_crop*2-1)
73-
y = int(np.random.randint(src_h-scale_item_h) - shift_item_h)
74-
x = int(np.random.randint(src_w-scale_item_w) - shift_item_w)
78+
shift_item_h, shift_item_w = overlay_h * (1 - minimum_crop), overlay_w * (1 - minimum_crop)
79+
scale_item_h, scale_item_w = overlay_h * (minimum_crop * 2 - 1), overlay_w * (
80+
minimum_crop * 2 - 1)
81+
y_max = src_h - scale_item_h
82+
x_max = src_w - scale_item_w
83+
if y_max > 0:
84+
y = int(np.random.randint(src_h - scale_item_h) - shift_item_h)
85+
else:
86+
y = int(-shift_item_h)
87+
if x_max > 0:
88+
x = int(np.random.randint(src_w - scale_item_w) - shift_item_w)
89+
else:
90+
x = int(-shift_item_w)
7591
image = overlay(src_image, overlay_image, x, y)
76-
bbox = ((np.maximum(x, 0), np.maximum(y, 0)), (np.minimum(x+overlay_w, src_w-1), np.minimum(y+overlay_h, src_h-1)))
92+
bbox = ((np.maximum(x, 0), np.maximum(y, 0)),
93+
(np.minimum(x + overlay_w, src_w - 1), np.minimum(y + overlay_h, src_h - 1)))
7794

7895
return image, bbox
7996

97+
8098
# 4点座標のbboxをyoloフォーマットに変換
8199
def yolo_format_bbox(image, bbox):
82100
orig_h, orig_w = image.shape[:2]
83101
center_x = (bbox[1][0] + bbox[0][0]) / 2 / orig_w
84102
center_y = (bbox[1][1] + bbox[0][1]) / 2 / orig_h
85103
w = (bbox[1][0] - bbox[0][0]) / orig_w
86104
h = (bbox[1][1] - bbox[0][1]) / orig_h
87-
return(center_x, center_y, w, h)
105+
return (center_x, center_y, w, h)
106+
88107

89108
def maximum_iou(box, boxes):
90109
max_iou = 0
@@ -94,7 +113,9 @@ def maximum_iou(box, boxes):
94113
max_iou = iou
95114
return max_iou
96115

116+
97117
class ImageGenerator():
118+
98119
def __init__(self, item_path, background_path):
99120
self.bg_files = glob.glob(background_path + "/*")
100121
self.item_files = glob.glob(item_path + "/*")
@@ -104,38 +125,40 @@ def __init__(self, item_path, background_path):
104125
for item_file in self.item_files:
105126
image = cv2.imread(item_file, cv2.IMREAD_UNCHANGED)
106127
center = np.maximum(image.shape[0], image.shape[1])
107-
pixels = np.zeros((center*2, center*2, image.shape[2]))
108-
y = int(center - image.shape[0]/2)
109-
x = int(center - image.shape[1]/2)
110-
pixels[y:y+image.shape[0], x:x+image.shape[1], :] = image
128+
pixels = np.zeros((center * 2, center * 2, image.shape[2]))
129+
y = int(center - image.shape[0] / 2)
130+
x = int(center - image.shape[1] / 2)
131+
pixels[y:y + image.shape[0], x:x + image.shape[1], :] = image
111132
self.items.append(pixels.astype(np.uint8))
112133
self.labels.append(item_file.split("/")[-1].split(".")[0])
113134

114135
for bg_file in self.bg_files:
115136
self.bgs.append(cv2.imread(bg_file))
116137

117-
def generate_random_animation(self, loop, bg_index, crop_width, crop_height, min_item_scale, max_item_scale):
138+
def generate_random_animation(self, loop, bg_index, crop_width, crop_height, min_item_scale,
139+
max_item_scale):
118140
frames = []
119141
sampled_background = random_sampling(self.bgs[bg_index], crop_height, crop_width)
120142
bg_height, bg_width, _ = sampled_background.shape
121143
for i in range(loop):
122144
#class_id = np.random.randint(len(self.labels))
123145
class_id = i % len(self.labels)
124146
item = self.items[class_id]
125-
item = scale_image(item, min_item_scale + np.random.rand() * (max_item_scale-min_item_scale))
147+
item = scale_image(item, min_item_scale + np.random.rand() *
148+
(max_item_scale - min_item_scale))
126149
orig_item = item
127150
item_height, item_width, _ = item.shape
128151
edges = [-item_width, -item_height, bg_width, bg_height]
129152
r = np.random.randint(2)
130-
rand1 = np.random.randint(edges[r+2] - edges[r]) + edges[r]
131-
center = edges[r] + (edges[r+2] - edges[r]) / 2
132-
edges[r+2] = int(center + (center - rand1))
153+
rand1 = np.random.randint(edges[r + 2] - edges[r]) + edges[r]
154+
center = edges[r] + (edges[r + 2] - edges[r]) / 2
155+
edges[r + 2] = int(center + (center - rand1))
133156
edges[r] = rand1
134157
print(edges)
135158

136159
r = np.random.randint(2)
137-
start_point = (edges[r*2], edges[r*2+1])
138-
end_point = (edges[r*2-2], edges[r*2-1])
160+
start_point = (edges[r * 2], edges[r * 2 + 1])
161+
end_point = (edges[r * 2 - 2], edges[r * 2 - 1])
139162
w_distance = end_point[0] - start_point[0]
140163
h_distance = end_point[1] - start_point[1]
141164
animate_frames = np.random.randint(30) + 50
@@ -148,20 +171,24 @@ def generate_random_animation(self, loop, bg_index, crop_width, crop_height, min
148171
angle *= -1
149172
total_angle += angle
150173
item = rotate_image(orig_item, total_angle)
151-
frame = overlay(sampled_background, item, start_point[0] + int(w_distance * j / animate_frames), start_point[1] + int(h_distance * j / animate_frames))
174+
frame = overlay(sampled_background, item,
175+
start_point[0] + int(w_distance * j / animate_frames),
176+
start_point[1] + int(h_distance * j / animate_frames))
152177
frames.append(frame[:, :, :3])
153178
return frames
154179

155-
def generate_samples(self, n_samples, n_items, crop_width, crop_height, min_item_scale, max_item_scale, rand_angle, minimum_crop, delta_hue, delta_sat_scale, delta_val_scale):
180+
def generate_samples(self, n_samples, n_items, crop_width, crop_height, min_item_scale,
181+
max_item_scale, rand_angle, minimum_crop, delta_hue, delta_sat_scale,
182+
delta_val_scale):
156183
x = []
157184
t = []
158185
for i in range(n_samples):
159186
bg = self.bgs[np.random.randint(len(self.bgs))]
160187
sample_image = random_sampling(bg, crop_height, crop_width)
161-
188+
162189
ground_truths = []
163190
boxes = []
164-
for j in range(np.random.randint(n_items)+1):
191+
for j in range(np.random.randint(n_items) + 1):
165192
class_id = np.random.randint(len(self.labels))
166193
item = self.items[class_id]
167194
item = random_rotate_scale_image(item, min_item_scale, max_item_scale, rand_angle)
@@ -173,7 +200,7 @@ def generate_samples(self, n_samples, n_items, crop_width, crop_height, min_item
173200
boxes.append(box)
174201
one_hot_label = np.zeros(len(self.labels))
175202
one_hot_label[class_id] = 1
176-
ground_truths.append({
203+
ground_truths.append({
177204
"x": yolo_bbox[0],
178205
"y": yolo_bbox[1],
179206
"w": yolo_bbox[2],
@@ -183,12 +210,13 @@ def generate_samples(self, n_samples, n_items, crop_width, crop_height, min_item
183210
})
184211
sample_image = tmp_image[:, :, :3]
185212
t.append(ground_truths)
186-
sample_image = random_hsv_image(sample_image, delta_hue, delta_sat_scale, delta_val_scale)
213+
sample_image = random_hsv_image(sample_image, delta_hue, delta_sat_scale,
214+
delta_val_scale)
187215

188216
#for ground_truth in ground_truths:
189-
# cv2.rectangle(sample_image,
190-
# (int((ground_truth["x"]-ground_truth["w"]/2)*crop_width), int((ground_truth["y"]-ground_truth["h"]/2)*crop_height)),
191-
# (int((ground_truth["x"]+ground_truth["w"]/2)*crop_width), int((ground_truth["y"]+ground_truth["h"]/2)*crop_height)),
217+
# cv2.rectangle(sample_image,
218+
# (int((ground_truth["x"]-ground_truth["w"]/2)*crop_width), int((ground_truth["y"]-ground_truth["h"]/2)*crop_height)),
219+
# (int((ground_truth["x"]+ground_truth["w"]/2)*crop_width), int((ground_truth["y"]+ground_truth["h"]/2)*crop_height)),
192220
# (0, 0, 255), 3
193221
# )
194222
#cv2.imshow("w", sample_image)

0 commit comments

Comments
 (0)