numpyimage 3.5.2__tar.gz → 3.5.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: numpyimage
3
- Version: 3.5.2
3
+ Version: 3.5.3
4
4
  Summary: Load, save, & manipulate image files as numpy arrays
5
5
  Author-email: Jasper Phelps <jasper.s.phelps@gmail.com>
6
6
  License: MIT License
@@ -637,13 +637,20 @@ def get_voxels_within_distance(distance, center=None, ndims=None,
637
637
  """
638
638
  Generates a list of voxel coordinates within a given distance of a given
639
639
  center point.
640
- center, tuple : Voxel coordinate to be used as the center.
641
- Defaults to the origin.
642
- distance, float : How far away from the center point to include.
643
- metric, string : How to calculate distance. Options are:
644
- euclidian (default)
645
- manhattan (sum of coordinates)
646
- chebyshev (max of coordinates)
640
+
641
+ Parameters
642
+ ----------
643
+ center : tuple
644
+ Voxel coordinate to be used as the center. Defaults to the origin.
645
+
646
+ distance : float
647
+ How far away from the center point to include.
648
+
649
+ metric : string, default 'euclidian'
650
+ How to calculate distance. Options are:
651
+ - euclidian (default)
652
+ - manhattan (sum of coordinates)
653
+ - chebyshev (max of coordinates)
647
654
  """
648
655
  assert metric in ['euclidian', 'manhattan', 'chebyshev']
649
656
 
@@ -40,6 +40,19 @@ codec_aliases = {
40
40
  'hev1': 'libx265',
41
41
  'h265': 'libx265',
42
42
  'H.265': 'libx265',
43
+ 'libvpx': 'libvpx',
44
+ 'vp8': 'libvpx',
45
+ 'libvpx-vp9': 'libvpx-vp9',
46
+ 'vp9': 'libvpx-vp9',
47
+ }
48
+
49
+ # Default codec for each container format
50
+ extension_default_codecs = {
51
+ 'mp4': 'libx264',
52
+ 'mkv': 'libx264',
53
+ 'avi': 'libx264',
54
+ 'mov': 'libx264',
55
+ 'webm': 'libvpx-vp9',
43
56
  }
44
57
 
45
58
  supported_extensions = ['mp4', 'mkv', 'avi', 'mov', 'webm']
@@ -256,7 +269,7 @@ class VideoStreamer:
256
269
  pts_deltas = np.diff(frames_pts) if len(frames_pts) > 1 else None
257
270
  if pts_deltas is not None and (pts_deltas == pts_deltas[0]).all():
258
271
  # The video is constant framerate
259
- self.pts_delta = pts_deltas[0]
272
+ self.pts_delta = int(pts_deltas[0])
260
273
  self._framerate = 1 / (self.pts_delta * self.time_base)
261
274
  if self._framerate.denominator == 1:
262
275
  self._framerate = self._framerate.numerator
@@ -572,12 +585,13 @@ class AVVideoWriter:
572
585
  compression_speed : str, default 'medium'
573
586
  Compression speed preset: 'ultrafast', 'superfast', 'veryfast',
574
587
  'faster', 'fast', 'medium', 'slow', 'slower', 'veryslow'.
575
- codec : Literal['libx264', 'libx265'], default 'libx264'
576
- The video codec to use for encoding. Can be any of a number of aliases for
577
- these two codecs, including avc1/h264 vs hevc/hvc1/hev1/h265.
588
+ codec : str or None, default None
589
+ The video codec to use for encoding. If None, automatically chosen based
590
+ on the file extension (e.g. libx264 for .mp4, libvpx-vp9 for .webm).
591
+ Accepts aliases like h264, h265, vp8, vp9, etc.
578
592
  """
579
593
  def __init__(self, filename, framerate=30, crf=23, compression_speed='medium',
580
- codec: Literal['libx264', 'libx265'] = 'libx264',
594
+ codec: Literal['libx264', 'libx265', 'libvpx', 'libvpx-vp9', None] = None,
581
595
  overwrite=False):
582
596
  self.av = _import_av()
583
597
  filename = Path(filename).expanduser()
@@ -588,11 +602,20 @@ class AVVideoWriter:
588
602
  self._framerate = utils.limit_fraction(framerate)
589
603
  self.crf = crf
590
604
  self.compression_speed = compression_speed
591
- self.codec = codec_aliases[codec.lower()]
605
+
606
+ if codec is None:
607
+ ext = filename.suffix.lower().lstrip('.')
608
+ self.codec = extension_default_codecs.get(ext, 'libx264')
609
+ else:
610
+ self.codec = codec_aliases[codec.lower()]
611
+
592
612
  self.container = self.av.open(filename, mode='w')
593
613
  self.stream = self.container.add_stream(self.codec, rate=self._framerate)
594
614
  self.stream.pix_fmt = 'yuv420p'
595
- self.stream.options = {'crf': str(crf), 'preset': compression_speed}
615
+ if self.codec in ('libvpx', 'libvpx-vp9'):
616
+ self.stream.options = {'crf': str(crf), 'b:v': '0'}
617
+ else:
618
+ self.stream.options = {'crf': str(crf), 'preset': compression_speed}
596
619
  self._closed = False
597
620
  self.stream.width = 0
598
621
  self.stream.height = 0
@@ -676,14 +699,15 @@ class FFmpegVideoWriter:
676
699
  compression_speed : str, default 'medium'
677
700
  Compression speed preset: 'ultrafast', 'superfast', 'veryfast',
678
701
  'faster', 'fast', 'medium', 'slow', 'slower', 'veryslow'.
679
- codec : Literal['libx264', 'libx265'], default 'libx264'
680
- The video codec to use for encoding. Can be any of a number of aliases for
681
- these two codecs, including avc1/h264 vs hevc/hvc1/hev1/h265.
702
+ codec : str or None, default None
703
+ The video codec to use for encoding. If None, automatically chosen based
704
+ on the file extension (e.g. libx264 for .mp4, libvpx-vp9 for .webm).
705
+ Accepts aliases like h264, h265, vp8, vp9, etc.
682
706
  overwrite : bool, default False
683
707
  Whether to overwrite the file if it already exists.
684
708
  """
685
709
  def __init__(self, filename, framerate=30, crf=23, compression_speed='medium',
686
- codec: Literal['libx264', 'libx265'] = 'libx264',
710
+ codec: Literal['libx264', 'libx265', 'libvpx', 'libvpx-vp9', None] = None,
687
711
  overwrite=False):
688
712
  filename = Path(filename).expanduser()
689
713
  if filename.exists() and not overwrite:
@@ -693,7 +717,12 @@ class FFmpegVideoWriter:
693
717
  self._framerate = utils.limit_fraction(framerate)
694
718
  self.crf = crf
695
719
  self.compression_speed = compression_speed
696
- self.codec = codec_aliases[codec.lower()]
720
+
721
+ if codec is None:
722
+ ext = filename.suffix.lower().lstrip('.')
723
+ self.codec = extension_default_codecs.get(ext, 'libx264')
724
+ else:
725
+ self.codec = codec_aliases[codec.lower()]
697
726
 
698
727
  # Initialize process state
699
728
  self._process = None
@@ -725,9 +754,13 @@ class FFmpegVideoWriter:
725
754
  '-c:v', self.codec,
726
755
  '-pix_fmt', 'yuv420p', # Output pixel format
727
756
  '-crf', str(self.crf),
728
- '-preset', self.compression_speed,
729
- self.filename
730
757
  ]
758
+ if self.codec in ('libvpx', 'libvpx-vp9'):
759
+ # VP8/VP9 need -b:v 0 for constant quality (CRF) mode
760
+ command += ['-b:v', '0']
761
+ else:
762
+ command += ['-preset', self.compression_speed]
763
+ command.append(str(self.filename))
731
764
 
732
765
  # Start FFmpeg process
733
766
  self._process = subprocess.Popen(
@@ -823,7 +856,7 @@ VideoWriter = FFmpegVideoWriter
823
856
 
824
857
  def save_video(data, filename, time_axis=0, color_axis=None, overwrite=False,
825
858
  dim_order='yx', framerate=30, crf=23, compression_speed='medium',
826
- progress_bar=True, codec: Literal['libx264', 'libx265'] = 'libx264') -> None:
859
+ progress_bar=True, codec: Literal['libx264', 'libx265', 'libvpx', 'libvpx-vp9', None] = None) -> None:
827
860
  """
828
861
  Save a 3D numpy array of greyscale values OR a 4D numpy array of RGB values as a video
829
862
 
@@ -869,9 +902,10 @@ def save_video(data, filename, time_axis=0, color_axis=None, overwrite=False,
869
902
  progress_bar : bool, default True
870
903
  If True, display a progress bar.
871
904
 
872
- codec : Literal['libx264', 'libx265'], default 'libx264'
873
- The video codec to use for encoding. Can be any of a number of aliases for
874
- these two codecs, including avc1/h264 vs hevc/hvc1/hev1/h265.
905
+ codec : str or None, default None
906
+ The video codec to use for encoding. If None, automatically chosen based
907
+ on the file extension (e.g. libx264 for .mp4, libvpx-vp9 for .webm).
908
+ Accepts aliases like h264, h265, vp8, vp9, etc.
875
909
  """
876
910
 
877
911
  filename = str(filename)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: numpyimage
3
- Version: 3.5.2
3
+ Version: 3.5.3
4
4
  Summary: Load, save, & manipulate image files as numpy arrays
5
5
  Author-email: Jasper Phelps <jasper.s.phelps@gmail.com>
6
6
  License: MIT License
@@ -4,7 +4,7 @@ build-backend = 'setuptools.build_meta'
4
4
 
5
5
  [project]
6
6
  name = 'numpyimage'
7
- version = '3.5.2'
7
+ version = '3.5.3'
8
8
  description = 'Load, save, & manipulate image files as numpy arrays'
9
9
  readme.file = 'README.md'
10
10
  readme.content-type = 'text/markdown'
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes