@@ -1194,7 +1194,7 @@ def run(
11941194 # Stack all results into a single tensor [B,H,W,C]
11951195 output_mask = torch .cat (output_mask ).permute (0 , 3 , 1 , 2 )
11961196
1197- return (output_mask [:, 0 : 1 , ...],)
1197+ return (output_mask [:, 0 , ...],)
11981198
11991199
12001200class Face2E :
@@ -1299,3 +1299,173 @@ def roll_mask(
12991299 roll_y = 0
13001300 roll_x = px_half
13011301 return (torch .roll (mask , shifts = (roll_y , roll_x ), dims = (1 , 2 )),)
1302+
1303+
1304+ class FaceMask2E :
1305+ """
1306+ Face Mask To Equirectangular
1307+ """
1308+
1309+ @classmethod
1310+ def INPUT_TYPES (s ) -> Dict :
1311+ return {
1312+ "required" : {
1313+ "mask" : ("MASK" , {"default" : None }),
1314+ "face" : (
1315+ ["Up" , "Down" , "Front" , "Right" , "Left" , "Back" ],
1316+ {"default" : "Down" },
1317+ ),
1318+ "base_equi_color" : ("FLOAT" , {"default" : 0.0 }),
1319+ "padding_mode" : (
1320+ ["bilinear" , "bicubic" , "nearest" ],
1321+ {"default" : "bilinear" },
1322+ ),
1323+ },
1324+ }
1325+
1326+ RETURN_TYPES = ("MASK" ,)
1327+ RETURN_NAMES = ("Equirectangular Mask" ,)
1328+
1329+ FUNCTION = "run_facemask2e"
1330+
1331+ CATEGORY = "pytorch360convert"
1332+
1333+ def run_facemask2e (
1334+ self ,
1335+ mask : torch .Tensor ,
1336+ face : str = "Down" ,
1337+ base_equi_color : float = 0.0 ,
1338+ padding_mode : str = "bilinear" ,
1339+ ) -> Tuple [torch .Tensor ]:
1340+ assert mask .dim () == 3 , f"Image should have 3 dimensions, got { mask .shape } "
1341+
1342+ output_mask = []
1343+ for f_mask in mask :
1344+ f_mask = f_mask = f_mask [None , ...]
1345+ cubemap_dict = {}
1346+ for face_name in ["Front" , "Right" , "Back" , "Left" , "Up" , "Down" ]:
1347+ if face_name != face :
1348+ cubemap_dict [face_name ] = torch .ones_like (f_mask ) * base_equi_color
1349+ else :
1350+ cubemap_dict [face_name ] = mask .reshape (1 , * mask .shape [1 :])
1351+ output_mask += [
1352+ c2e (
1353+ cubemap = cubemap_dict ,
1354+ cube_format = "dict" ,
1355+ mode = padding_mode ,
1356+ channels_first = True ,
1357+ )
1358+ ]
1359+ return (torch .cat (output_mask ),)
1360+
1361+
1362+ class EMask2Face :
1363+ """
1364+ Equirectangular Mask to Face
1365+ """
1366+
1367+ @classmethod
1368+ def INPUT_TYPES (s ) -> Dict :
1369+ return {
1370+ "required" : {
1371+ "mask" : ("MASK" , {"default" : None }),
1372+ "face_width" : ("INT" , {"default" : - 1 }),
1373+ "padding_mode" : (
1374+ ["bilinear" , "bicubic" , "nearest" ],
1375+ {"default" : "bilinear" },
1376+ ),
1377+ "cube_face" : (
1378+ ["Up" , "Down" , "Right" , "Left" , "Front" , "Back" ],
1379+ {"default" : "Front" },
1380+ ),
1381+ },
1382+ }
1383+
1384+ RETURN_TYPES = ("MASK" ,)
1385+ RETURN_NAMES = ("Face MASK" ,)
1386+
1387+ FUNCTION = "run_emask2face"
1388+
1389+ CATEGORY = "pytorch360convert"
1390+
1391+ def run_emask2face (
1392+ self ,
1393+ mask : torch .Tensor ,
1394+ face_width : int = - 1 ,
1395+ padding_mode : str = "bilinear" ,
1396+ cube_face : str = "Front" ,
1397+ ) -> Tuple [torch .Tensor ]:
1398+
1399+ B , H , W = mask .shape
1400+ outputs = []
1401+
1402+ for i in range (B ):
1403+ singlmask = mask [i : i + 1 ][..., None ] # [H,W,C]
1404+ # Determine face width
1405+ face_w = H // 2 if face_width < 1 else face_width
1406+
1407+ # Convert single equirectangular mask to cubemap dict
1408+ cubemap = e2c (
1409+ singlmask ,
1410+ face_w = face_w ,
1411+ mode = padding_mode ,
1412+ cube_format = "dict" ,
1413+ channels_first = False ,
1414+ )
1415+
1416+ # Pick requested face
1417+ face_tensor = cubemap [cube_face ] # [face_w, face_w, C]
1418+
1419+ outputs .append (face_tensor ) # [1,H,W,C]
1420+
1421+ # Concatenate into [B,H,W,C]
1422+ output_batch = torch .cat (outputs , dim = 0 )[..., 0 ]
1423+ return (output_batch ,)
1424+
1425+
1426+ class MaskE2ENode :
1427+ """
1428+ Mask Equirectangular Rotation
1429+ """
1430+
1431+ @classmethod
1432+ def INPUT_TYPES (s ) -> Dict :
1433+ return {
1434+ "required" : {
1435+ "mask" : ("MASK" , {"default" : None }),
1436+ "roll" : ("FLOAT" , {"default" : 0.0 }),
1437+ "h_deg" : ("FLOAT" , {"default" : 0.0 }),
1438+ "v_deg" : ("FLOAT" , {"default" : 0.0 }),
1439+ "padding_mode" : (
1440+ ["bilinear" , "bicubic" , "nearest" ],
1441+ {"default" : "bilinear" },
1442+ ),
1443+ },
1444+ }
1445+
1446+ RETURN_TYPES = ("MASK" ,)
1447+ RETURN_NAMES = ("Rotated Mask" ,)
1448+
1449+ FUNCTION = "mask_e2e"
1450+
1451+ CATEGORY = "pytorch360convert"
1452+
1453+ def mask_e2e (
1454+ self ,
1455+ mask : torch .Tensor ,
1456+ roll : float = 0.0 ,
1457+ h_deg : float = 0.0 ,
1458+ v_deg : float = 0.0 ,
1459+ padding_mode : str = "bilinear" ,
1460+ ) -> Tuple [torch .Tensor ]:
1461+ assert mask .dim () == 3 , f"mask should have 3 dimensions, got { mask .dim ()} "
1462+ return (
1463+ e2e (
1464+ e_img = mask [..., None ],
1465+ h_deg = h_deg ,
1466+ v_deg = v_deg ,
1467+ roll = roll ,
1468+ mode = padding_mode ,
1469+ channels_first = False ,
1470+ )[..., 0 ],
1471+ )
0 commit comments