-
Notifications
You must be signed in to change notification settings - Fork 7
/
DepthMaskFilter.py
138 lines (116 loc) · 4.65 KB
/
DepthMaskFilter.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# Note: This node is outdated and archived as Meshroom python node example
#
# Requirements:
# enum34;python_version<"3.4"
# PySide2==5.13.0
# markdown==2.6.11
# numpy
# Pillow
# Imath
# OpenEXR
#
# https://github.com/alicevision/meshroom/pull/641
# Node by ALfuhrmann https://github.com/ALfuhrmann
#
# This node includes the minor fix by tpontin https://github.com/alicevision/meshroom/pull/641#issuecomment-603876386
# As this node was intended as Meshroom contribution, it is licensed under MPLv2
#
# Node inputs:
# Input: cameraInit.sfm for input image file names (.sfm only, no alembic)
# Filtered Depth Maps Folder: depth maps folder output of DepthMaskFilter
# Mask Folder: folder containing b/w mask .PNG images with the same names as the associated input files
# The masks have to be rectified, so you cannot use your generated masks directly, but have to run them through a PrepareDenseScene node
# (https://github.com/alicevision/meshroom/pull/641)
#
# See https://github.com/alicevision/meshroom/pull/708 for the latest DepthMaskFilter implementation in Meshroom
from __future__ import print_function
__version__ = "1.0"
from meshroom.core import desc
import json, shutil, glob
import OpenEXR
import Imath
import numpy as np
from PIL import Image
import os.path
import logging
class DepthMaskFilter(desc.Node):
inputs = [
desc.File(
name='input',
label='Input',
description='SfMData file.',
value='',
uid=[0],
),
desc.File(
name="depthMapsFilterFolder",
label='Filtered Depth Maps Folder',
description='Input filtered depth maps folder',
value='',
uid=[0],
),
desc.File(
name="MasksFolder",
label="Masks Folder",
description="Input masks folder",
value="",
uid=[0],
),
]
outputs = [
desc.File(
name='output',
label='Output',
description='Output folder for masked depth maps.',
value=desc.Node.internalFolder,
uid=[],
),
]
def maskEXR(self, filename, maskname, fill_value):
(basename, extension) = os.path.splitext(filename)
infile = OpenEXR.InputFile(filename) # read depth map
header = infile.header()
if (header['channels']['Y'].type == Imath.PixelType(Imath.PixelType.FLOAT)):
pt = Imath.PixelType(Imath.PixelType.FLOAT)
dt = np.float32
elif (header['channels']['Y'].type == Imath.PixelType(Imath.PixelType.HALF)):
pt = Imath.PixelType(Imath.PixelType.HALF)
dt = np.float16
else:
print('Integer images not supported!')
exit(-1)
dw = header['dataWindow']
size = (dw.max.x - dw.min.x + 1, dw.max.y - dw.min.y + 1)
Ystr = infile.channel('Y', pt)
Y = np.frombuffer(Ystr, dtype=dt)
Y.shape = (size[1], size[0])
maskImage = Image.open(maskname)
if (size != maskImage.size): # check if depthmaps were downsampled
print("Resizing mask: {}".format(maskname))
maskImage = maskImage.resize(size, Image.NEAREST)
imgmask = np.array(maskImage)[:, :, 0] # read only greyscale images
Y_masked = np.ma.array(Y, mask=(imgmask == 0)).filled(fill_value) # fill masked areas
infile.close()
# write masked depth map
exr = OpenEXR.OutputFile(filename, header)
exr.writePixels({'Y': Y_masked})
exr.close()
def processChunk(self, chunk):
print("DepthMask Node start\n")
with open(chunk.node.input.value, 'r') as f:
sfm = json.load(f)
for view in sfm["views"]: # loop over all views/images
viewId = view["viewId"]
source_image_path = view["path"]
(src_path, src_name) = os.path.split(source_image_path)
(filename, ext) = os.path.splitext(src_name)
depth_map_name = os.path.join(chunk.node.output.value, viewId+"_depthMap.exr")
mask_name = os.path.join(chunk.node.MasksFolder.value, viewId+".png")
# duplicate all maps
files = glob.glob(os.path.join(chunk.node.depthMapsFilterFolder.value, viewId+"_*Map.*"))
for f in files:
shutil.copy(f, chunk.node.output.value)
# masking depth maps
print("Masking depth map: {}".format(depth_map_name))
if os.path.exists(mask_name): self.maskEXR(depth_map_name, mask_name, -1.0)
print('DepthMask Node end')