@@ -10,8 +10,8 @@ def Inner(func): return lambda *args, **kwargs: func(*args, **kwargs)
1010from PIL import Image
1111
1212
13- def create_stereoimages (original_image , depthmap , divergence , separation = 0.0 , modes = None , stereo_balance = 0.0 ,
14- fill_technique = 'polylines_sharp' ):
13+ def create_stereoimages (original_image , depthmap , divergence , separation = 0.0 , modes = None ,
14+ stereo_balance = 0.0 , stereo_offset_exponent = 1.0 , fill_technique = 'polylines_sharp' ):
1515 """Creates stereoscopic images.
1616 An effort is made to make them look nice, but beware that the resulting image will have some distortion.
1717 The correctness was not rigorously tested.
@@ -28,6 +28,8 @@ def create_stereoimages(original_image, depthmap, divergence, separation=0.0, mo
2828 Some of the supported modes are: 'left-right', 'right-left', 'top-bottom', 'bottom-top', 'red-cyan-anaglyph'.
2929 :param float stereo_balance: has to do with how the divergence will be split among the two parts of the image,
3030 must be in the [-1.0; 1.0] interval.
31+ :param float stereo_offset_exponent: Higher values move objects residing
32+ between close and far plane more to the far plane
3133 :param str fill_technique: applying divergence inevitably creates some gaps in the image.
3234 This parameter specifies the technique that will be used to fill in the blanks in the two resulting images.
3335 Must be one of the following: 'none', 'naive', 'naive_interpolating', 'polylines_soft', 'polylines_sharp'.
@@ -42,9 +44,11 @@ def create_stereoimages(original_image, depthmap, divergence, separation=0.0, mo
4244 original_image = np .asarray (original_image )
4345 balance = (stereo_balance + 1 ) / 2
4446 left_eye = original_image if balance < 0.001 else \
45- apply_stereo_divergence (original_image , depthmap , + 1 * divergence * balance , - 1 * separation , fill_technique )
47+ apply_stereo_divergence (original_image , depthmap , + 1 * divergence * balance , - 1 * separation ,
48+ stereo_offset_exponent , fill_technique )
4649 right_eye = original_image if balance > 0.999 else \
47- apply_stereo_divergence (original_image , depthmap , - 1 * divergence * (1 - balance ), separation , fill_technique )
50+ apply_stereo_divergence (original_image , depthmap , - 1 * divergence * (1 - balance ), separation ,
51+ stereo_offset_exponent , fill_technique )
4852
4953 results = []
5054 for mode in modes :
@@ -70,7 +74,7 @@ def create_stereoimages(original_image, depthmap, divergence, separation=0.0, mo
7074 return [Image .fromarray (r ) for r in results ]
7175
7276
73- def apply_stereo_divergence (original_image , depth , divergence , separation , fill_technique ):
77+ def apply_stereo_divergence (original_image , depth , divergence , separation , stereo_offset_exponent , fill_technique ):
7478 depth_min = depth .min ()
7579 depth_max = depth .max ()
7680 normalized_depth = (depth - depth_min ) / (depth_max - depth_min )
@@ -79,17 +83,18 @@ def apply_stereo_divergence(original_image, depth, divergence, separation, fill_
7983
8084 if fill_technique in ['none' , 'naive' , 'naive_interpolating' ]:
8185 return apply_stereo_divergence_naive (
82- original_image , normalized_depth , divergence_px , separation_px , fill_technique
86+ original_image , normalized_depth , divergence_px , separation_px , stereo_offset_exponent , fill_technique
8387 )
8488 if fill_technique in ['polylines_soft' , 'polylines_sharp' ]:
8589 return apply_stereo_divergence_polylines (
86- original_image , normalized_depth , divergence_px , separation_px , fill_technique
90+ original_image , normalized_depth , divergence_px , separation_px , stereo_offset_exponent , fill_technique
8791 )
8892
8993
9094@njit (parallel = False )
9195def apply_stereo_divergence_naive (
92- original_image , normalized_depth , divergence_px : float , separation_px : float , fill_technique ):
96+ original_image , normalized_depth , divergence_px : float , separation_px : float , stereo_offset_exponent : float ,
97+ fill_technique : str ):
9398 h , w , c = original_image .shape
9499
95100 derived_image = np .zeros_like (original_image )
@@ -99,7 +104,7 @@ def apply_stereo_divergence_naive(
99104 # Swipe order should ensure that pixels that are closer overwrite
100105 # (at their destination) pixels that are less close
101106 for col in range (w ) if divergence_px < 0 else range (w - 1 , - 1 , - 1 ):
102- col_d = col + int ((normalized_depth [row ][col ] ** 2 ) * divergence_px + separation_px )
107+ col_d = col + int ((normalized_depth [row ][col ] ** stereo_offset_exponent ) * divergence_px + separation_px )
103108 if 0 <= col_d < w :
104109 derived_image [row ][col_d ] = original_image [row ][col ]
105110 filled [row * w + col_d ] = 1
@@ -155,7 +160,8 @@ def apply_stereo_divergence_naive(
155160
156161@njit (parallel = True ) # fastmath=True does not reasonably improve performance
157162def apply_stereo_divergence_polylines (
158- original_image , normalized_depth , divergence_px : float , separation_px : float , fill_technique ):
163+ original_image , normalized_depth , divergence_px : float , separation_px : float , stereo_offset_exponent : float ,
164+ fill_technique : str ):
159165 # This code treats rows of the image as polylines
160166 # It generates polylines, morphs them (applies divergence) to them, and then rasterizes them
161167 EPSILON = 1e-7
@@ -172,7 +178,7 @@ def apply_stereo_divergence_polylines(
172178 pt [pt_end ] = [- 1.0 * w , 0.0 , 0.0 ]
173179 pt_end += 1
174180 for col in range (0 , w ):
175- coord_d = (normalized_depth [row ][col ] ** 2 ) * divergence_px
181+ coord_d = (normalized_depth [row ][col ] ** stereo_offset_exponent ) * divergence_px
176182 coord_x = col + 0.5 + coord_d + separation_px
177183 if PIXEL_HALF_WIDTH < EPSILON :
178184 pt [pt_end ] = [coord_x , abs (coord_d ), col ]
0 commit comments