在2D成像世界中,PIL就像this answer一样方便。
考虑3d体积:
import numpy as np
from PIL import Image, ImageChops
im = np.zeros((10, 10))
im[4:6, 4:6] = np.ones((2, 2))
im = Image.fromarray(im).convert("L")
vlm = np.zeros((10, 10, 10))
vlm[4:6, 4:6, 4:6] = np.ones((2, 2, 2))
它涉及三个阶段:
1)识别边界像素(3D体积中的体素)。
2D:bg = Image.new(im.mode, im.size, im.getpixel((0, 0)))
3D:vbg = vlm[0, 0, 0]
2)定义内部“框”的坐标,宽度,高度(和3D深度)
2D:bbox = ImageChops.difference(im, bg).getbbox()
3D:bbox3d = MAGIC(vlm, vbg) # return (4, 4, 4, 6, 6, 6)
←问题
3)裁剪“盒子”
2D:im = im.crop(bbox) # same as im[bbox[0]:bbox[2], bbox[1]:bbox[3]]
3D:vlm = vlm[bbox3d[0]:bbox3d[3], bbox3d[1]:bbox3d[4], bbox3d[2]:bbox3d[5]]
因此,问题很明显。
如何实现ImageChops.difference(im, bg).getbbox()
的3D版本?
有没有可用的现有库?
我已经实现了MAGIC()
的幼稚方法:
def bbox3d(volume):
slices = np.moveaxis(volume, 2, 0)
bboxes = []
for s in slices:
img = Image.fromarray(s)
bg = Image.new(img.mode, img.size)
diff = ImageChops.difference(img, bg)
bbox = ImageChops.add(diff, diff, 2.0, -100).getbbox()
bboxes.append(bbox)
z, zd = 0, len(bboxes)
for i in range(len(bboxes)):
if bboxes[i] and z == 0:
z = i
break
for i in reversed(range(len(bboxes))):
if bboxes[i] and zd == len(bboxes):
zd = i + 1
break
assert z <= zd
x = min([b[0] for b in bboxes if b])
y = min([b[1] for b in bboxes if b])
xd = max([b[2] for b in bboxes if b])
yd = max([b[3] for b in bboxes if b])
return (x, y, z, xd, yd, zd)