""" params:
- scale: int 2.2>scale>0
- img_array: list or tuple of opencv mat img and string label (matImg,"mat-img" )
- columns: int:optional - acts as manual override to control how many columns you want to display the number of images you sent, defaults to 4 and does some calculations for assumpions.
Usage: cv2.imshow("stacked", stack_images(1.2, (img, "img-label")))
"""
def stack_images(scale, img_array, columns=4):
formatted_arr = []
max_w = sorted([x.shape[1] for (x, _) in img_array], reverse=True)[0]
max_h = sorted([x.shape[0] for (x, _) in img_array], reverse=True)[0]
aggregate_cols = lambda arr_len, cols: cols if arr_len % cols == 0 and cols / arr_len >= 0.255\
else aggregate_cols(arr_len, cols + 1)
padding_space = np.zeros((max_w, max_h), np.uint8)
for img, label in img_array:
img = cv2.resize(img, (int(max_w * scale), int(max_h * scale))) # resize all images
if len(img.shape) == 2:
img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR) # add color channel
cv2.putText(img, label, (int(img.shape[1] * 10 / 100), int(img.shape[0] * 10 / 100),),
cv2.FONT_HERSHEY_SIMPLEX, 1.1, (120, 222, 0), 2) # add label
formatted_arr.append(img)
if len(img_array) % 2 != 0: # pad image array to make it even
formatted_arr.insert(len(img_array), cv2.resize(cv2.cvtColor(padding_space, cv2.COLOR_GRAY2BGR),
(int(max_w * scale), int(max_h * scale))))
denominator = aggregate_cols(len(formatted_arr), columns)
print("denominator\t", denominator, "\narr_len\t", len(formatted_arr), "\n ratio\t", columns/len(formatted_arr))
acc = np.split(np.stack(formatted_arr), denominator)
return np.concatenate([np.vstack(a) for a in acc[:]], axis=1)
```