15
15
16
16
from __future__ import annotations
17
17
18
+ import math
18
19
import sys
19
20
from dataclasses import dataclass , field
20
21
from functools import partial
@@ -56,6 +57,8 @@ class ColmapDataParserConfig(DataParserConfig):
56
57
"""How much to scale the camera origins by."""
57
58
downscale_factor : Optional [int ] = None
58
59
"""How much to downscale images. If not set, images are chosen such that the max dimension is <1600px."""
60
+ downscale_rounding_mode : Literal ["floor" , "round" , "ceil" ] = "floor"
61
+ """How to round downscale image height and Image width."""
59
62
scene_scale : float = 1.0
60
63
"""How much to scale the region of interest by."""
61
64
orientation_method : Literal ["pca" , "up" , "vertical" , "none" ] = "up"
@@ -355,7 +358,9 @@ def _generate_dataparser_outputs(self, split: str = "train", **kwargs):
355
358
camera_type = camera_type ,
356
359
)
357
360
358
- cameras .rescale_output_resolution (scaling_factor = 1.0 / downscale_factor )
361
+ cameras .rescale_output_resolution (
362
+ scaling_factor = 1.0 / downscale_factor , scale_rounding_mode = self .config .downscale_rounding_mode
363
+ )
359
364
360
365
if "applied_transform" in meta :
361
366
applied_transform = torch .tensor (meta ["applied_transform" ], dtype = transform_matrix .dtype )
@@ -452,18 +457,39 @@ def _load_3D_points(self, colmap_path: Path, transform_matrix: torch.Tensor, sca
452
457
out ["points3D_points2D_xy" ] = torch .stack (points3D_image_xy , dim = 0 )
453
458
return out
454
459
455
- def _downscale_images (self , paths , get_fname , downscale_factor : int , nearest_neighbor : bool = False ):
460
+ def _downscale_images (
461
+ self ,
462
+ paths ,
463
+ get_fname ,
464
+ downscale_factor : int ,
465
+ downscale_rounding_mode : str = "floor" ,
466
+ nearest_neighbor : bool = False ,
467
+ ):
468
+ def calculate_scaled_size (original_width , original_height , downscale_factor , mode = "floor" ):
469
+ if mode == "floor" :
470
+ return math .floor (original_width / downscale_factor ), math .floor (original_height / downscale_factor )
471
+ elif mode == "round" :
472
+ return round (original_width / downscale_factor ), round (original_height / downscale_factor )
473
+ elif mode == "ceil" :
474
+ return math .ceil (original_width / downscale_factor ), math .ceil (original_height / downscale_factor )
475
+ else :
476
+ raise ValueError ("Invalid mode. Choose from 'floor', 'round', or 'ceil'." )
477
+
456
478
with status (msg = "[bold yellow]Downscaling images..." , spinner = "growVertical" ):
457
479
assert downscale_factor > 1
458
480
assert isinstance (downscale_factor , int )
481
+ filepath = next (iter (paths ))
482
+ img = Image .open (filepath )
483
+ w , h = img .size
484
+ w_scaled , h_scaled = calculate_scaled_size (w , h , downscale_factor , downscale_rounding_mode )
459
485
# Using %05d ffmpeg commands appears to be unreliable (skips images).
460
486
for path in paths :
461
487
nn_flag = "" if not nearest_neighbor else ":flags=neighbor"
462
488
path_out = get_fname (path )
463
489
path_out .parent .mkdir (parents = True , exist_ok = True )
464
490
ffmpeg_cmd = [
465
491
f'ffmpeg -y -noautorotate -i "{ path } " ' ,
466
- f"-q:v 2 -vf scale=iw/ { downscale_factor } :ih/ { downscale_factor } { nn_flag } " ,
492
+ f"-q:v 2 -vf scale={ w_scaled } : { h_scaled } { nn_flag } " ,
467
493
f'"{ path_out } "' ,
468
494
]
469
495
ffmpeg_cmd = " " .join (ffmpeg_cmd )
@@ -488,7 +514,7 @@ def get_fname(parent: Path, filepath: Path) -> Path:
488
514
if self ._downscale_factor is None :
489
515
if self .config .downscale_factor is None :
490
516
test_img = Image .open (filepath )
491
- h , w = test_img .size
517
+ w , h = test_img .size
492
518
max_res = max (h , w )
493
519
df = 0
494
520
while True :
@@ -508,12 +534,17 @@ def get_fname(parent: Path, filepath: Path) -> Path:
508
534
CONSOLE .print (
509
535
f"[bold red]Downscaled images do not exist for factor of { self ._downscale_factor } .[/bold red]"
510
536
)
511
- if Confirm .ask ("\n Would you like to downscale the images now?" , default = False , console = CONSOLE ):
537
+ if Confirm .ask (
538
+ f"\n Would you like to downscale the images using '{ self .config .downscale_rounding_mode } ' rounding mode now?" ,
539
+ default = False ,
540
+ console = CONSOLE ,
541
+ ):
512
542
# Install the method
513
543
self ._downscale_images (
514
544
image_filenames ,
515
545
partial (get_fname , self .config .data / self .config .images_path ),
516
546
self ._downscale_factor ,
547
+ self .config .downscale_rounding_mode ,
517
548
nearest_neighbor = False ,
518
549
)
519
550
if len (mask_filenames ) > 0 :
@@ -522,6 +553,7 @@ def get_fname(parent: Path, filepath: Path) -> Path:
522
553
mask_filenames ,
523
554
partial (get_fname , self .config .data / self .config .masks_path ),
524
555
self ._downscale_factor ,
556
+ self .config .downscale_rounding_mode ,
525
557
nearest_neighbor = True ,
526
558
)
527
559
if len (depth_filenames ) > 0 :
@@ -530,6 +562,7 @@ def get_fname(parent: Path, filepath: Path) -> Path:
530
562
depth_filenames ,
531
563
partial (get_fname , self .config .data / self .config .depths_path ),
532
564
self ._downscale_factor ,
565
+ self .config .downscale_rounding_mode ,
533
566
nearest_neighbor = True ,
534
567
)
535
568
else :
0 commit comments