PyOPIA 2.16.4__tar.gz → 2.16.5__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.
Files changed (38) hide show
  1. {pyopia-2.16.4 → pyopia-2.16.5}/PKG-INFO +1 -1
  2. pyopia-2.16.5/pyopia/__init__.py +1 -0
  3. {pyopia-2.16.4 → pyopia-2.16.5}/pyopia/process.py +91 -7
  4. pyopia-2.16.4/pyopia/__init__.py +0 -1
  5. {pyopia-2.16.4 → pyopia-2.16.5}/.gitignore +0 -0
  6. {pyopia-2.16.4 → pyopia-2.16.5}/LICENSE +0 -0
  7. {pyopia-2.16.4 → pyopia-2.16.5}/README.md +0 -0
  8. {pyopia-2.16.4 → pyopia-2.16.5}/pyopia/auxillarydata.py +0 -0
  9. {pyopia-2.16.4 → pyopia-2.16.5}/pyopia/background.py +0 -0
  10. {pyopia-2.16.4 → pyopia-2.16.5}/pyopia/cf_metadata.json +0 -0
  11. {pyopia-2.16.4 → pyopia-2.16.5}/pyopia/classify.py +0 -0
  12. {pyopia-2.16.4 → pyopia-2.16.5}/pyopia/classify_torch.py +0 -0
  13. {pyopia-2.16.4 → pyopia-2.16.5}/pyopia/cli.py +0 -0
  14. {pyopia-2.16.4 → pyopia-2.16.5}/pyopia/dataexport/__init__.py +0 -0
  15. {pyopia-2.16.4 → pyopia-2.16.5}/pyopia/dataexport/ecotaxa.py +0 -0
  16. {pyopia-2.16.4 → pyopia-2.16.5}/pyopia/exampledata.py +0 -0
  17. {pyopia-2.16.4 → pyopia-2.16.5}/pyopia/instrument/__init__.py +0 -0
  18. {pyopia-2.16.4 → pyopia-2.16.5}/pyopia/instrument/common.py +0 -0
  19. {pyopia-2.16.4 → pyopia-2.16.5}/pyopia/instrument/holo.py +0 -0
  20. {pyopia-2.16.4 → pyopia-2.16.5}/pyopia/instrument/silcam.py +0 -0
  21. {pyopia-2.16.4 → pyopia-2.16.5}/pyopia/instrument/uvp.py +0 -0
  22. {pyopia-2.16.4 → pyopia-2.16.5}/pyopia/io.py +0 -0
  23. {pyopia-2.16.4 → pyopia-2.16.5}/pyopia/metadata.py +0 -0
  24. {pyopia-2.16.4 → pyopia-2.16.5}/pyopia/pipeline.py +0 -0
  25. {pyopia-2.16.4 → pyopia-2.16.5}/pyopia/plotting.py +0 -0
  26. {pyopia-2.16.4 → pyopia-2.16.5}/pyopia/realtime.py +0 -0
  27. {pyopia-2.16.4 → pyopia-2.16.5}/pyopia/simulator/__init__.py +0 -0
  28. {pyopia-2.16.4 → pyopia-2.16.5}/pyopia/simulator/silcam.py +0 -0
  29. {pyopia-2.16.4 → pyopia-2.16.5}/pyopia/statistics.py +0 -0
  30. {pyopia-2.16.4 → pyopia-2.16.5}/pyopia/tests/__init__.py +0 -0
  31. {pyopia-2.16.4 → pyopia-2.16.5}/pyopia/tests/test_auxillarydata.py +0 -0
  32. {pyopia-2.16.4 → pyopia-2.16.5}/pyopia/tests/test_classify.py +0 -0
  33. {pyopia-2.16.4 → pyopia-2.16.5}/pyopia/tests/test_io.py +0 -0
  34. {pyopia-2.16.4 → pyopia-2.16.5}/pyopia/tests/test_notebooks.py +0 -0
  35. {pyopia-2.16.4 → pyopia-2.16.5}/pyopia/tests/test_pipeline.py +0 -0
  36. {pyopia-2.16.4 → pyopia-2.16.5}/pyopia/tests/test_process.py +0 -0
  37. {pyopia-2.16.4 → pyopia-2.16.5}/pyopia/tests/test_realtime.py +0 -0
  38. {pyopia-2.16.4 → pyopia-2.16.5}/pyproject.toml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyOPIA
3
- Version: 2.16.4
3
+ Version: 2.16.5
4
4
  Summary: A Python Ocean Particle Image Analysis toolbox.
5
5
  Project-URL: Repository, https://github.com/sintef/pyopia
6
6
  Project-URL: Documentation, https://pyopia.readthedocs.io
@@ -0,0 +1 @@
1
+ __version__ = "2.16.5"
@@ -204,6 +204,59 @@ def extract_roi(input_image, bbox):
204
204
  return roi
205
205
 
206
206
 
207
+ def expand_bbox(bbox, image_shape, fraction):
208
+ '''Expand a bounding box by a fraction of its width and height, clamped to image bounds.
209
+
210
+ The expansion is split evenly on each side, so a fraction of 0.10 grows the
211
+ bounding box by 5% on each side (total +10% width, +10% height). Coordinates
212
+ are clamped to remain inside the image. Useful for adding visual context
213
+ around exported particle ROIs without altering the underlying regionprops
214
+ measurements.
215
+
216
+ Parameters
217
+ ----------
218
+ bbox : array-like of int
219
+ [min_row, min_col, max_row, max_col], following the skimage regionprops
220
+ convention where ``max_row`` and ``max_col`` are exclusive.
221
+ image_shape : tuple
222
+ Shape of the full image. Only the first two elements (H, W) are used,
223
+ so passing ``imc.shape`` works for both 2-D and 3-D images.
224
+ fraction : float
225
+ Total fractional expansion of width and height. ``0.1`` = +10%.
226
+ ``0`` (or ``None``) returns the bbox unchanged. Must be non-negative.
227
+
228
+ Returns
229
+ -------
230
+ expanded : ndarray of int, shape (4,)
231
+ Expanded and clamped bounding box, integer-valued.
232
+
233
+ Raises
234
+ ------
235
+ ValueError
236
+ If ``fraction`` is negative.
237
+ '''
238
+ bbox_int = np.asarray(bbox, dtype=int)
239
+ if fraction is None or fraction == 0:
240
+ return bbox_int
241
+ if fraction < 0:
242
+ raise ValueError(f'bbox_expansion must be non-negative, got {fraction}')
243
+
244
+ r1, c1, r2, c2 = bbox_int
245
+ H, W = image_shape[0], image_shape[1]
246
+
247
+ h = r2 - r1
248
+ w = c2 - c1
249
+ pad_r = int(round(h * fraction / 2.0))
250
+ pad_c = int(round(w * fraction / 2.0))
251
+
252
+ return np.array([
253
+ max(0, r1 - pad_r),
254
+ max(0, c1 - pad_c),
255
+ min(H, r2 + pad_r),
256
+ min(W, c2 + pad_c),
257
+ ], dtype=int)
258
+
259
+
207
260
  def put_roi_in_h5(export_outputpath, HDF5File, roi, filename, i):
208
261
  '''Adds rois to an open hdf file if export_outputpath is not None.
209
262
  For use within {func}`pyopia.process.export_particles`
@@ -232,7 +285,8 @@ def put_roi_in_h5(export_outputpath, HDF5File, roi, filename, i):
232
285
 
233
286
  def extract_particles(imc, timestamp, Classification, region_properties,
234
287
  export_outputpath=None, min_length=0, propnames=['major_axis_length', 'minor_axis_length',
235
- 'equivalent_diameter']):
288
+ 'equivalent_diameter'],
289
+ bbox_expansion=0.0):
236
290
  '''Extracts the particles to build stats and export particle rois to HDF5 files
237
291
 
238
292
  Parameters
@@ -253,6 +307,13 @@ def extract_particles(imc, timestamp, Classification, region_properties,
253
307
  Specifies list of skimage regionprops to export to the output file.
254
308
  Must contain default values that can be appended to,
255
309
  by default ['major_axis_length', 'minor_axis_length', 'equivalent_diameter']
310
+ bbox_expansion : float, optional
311
+ Fractional expansion of the bounding box used when cropping each ROI for
312
+ export. ``0.0`` (default) preserves prior behaviour. ``0.1`` grows the
313
+ crop by 10% in width and height (5% on each side), clamped to image
314
+ bounds. Only the exported ROI image is affected; the ``minr/minc/maxr/
315
+ maxc`` columns saved in stats continue to report the un-expanded
316
+ regionprops bbox so that measurements are unchanged.
256
317
 
257
318
  Returns
258
319
  -------
@@ -304,8 +365,10 @@ def extract_particles(imc, timestamp, Classification, region_properties,
304
365
  if ((data[i, 0] > min_length) & (data[i, 1] > 2)):
305
366
 
306
367
  nb_extractable_part += 1
307
- # extract the region of interest from the corrected colour image
308
- roi = extract_roi(imc, bboxes[i, :].astype(int))
368
+ # extract the region of interest from the corrected colour image,
369
+ # optionally with the bbox expanded by `bbox_expansion` to add context
370
+ roi_bbox = expand_bbox(bboxes[i, :], imc.shape, bbox_expansion)
371
+ roi = extract_roi(imc, roi_bbox)
309
372
 
310
373
  if Classification is not None:
311
374
  # run a prediction on what type of particle this might be
@@ -426,7 +489,8 @@ def statextract(imbw, timestamp, imc,
426
489
  max_particles=5000,
427
490
  export_outputpath=None,
428
491
  min_length=0,
429
- propnames=['major_axis_length', 'minor_axis_length', 'equivalent_diameter']):
492
+ propnames=['major_axis_length', 'minor_axis_length', 'equivalent_diameter'],
493
+ bbox_expansion=0.0):
430
494
  '''Extracts statistics of particles in a binary images (imbw)
431
495
 
432
496
  Parameters
@@ -452,6 +516,9 @@ def statextract(imbw, timestamp, imc,
452
516
  Specifies list of skimage regionprops to export to the output file.
453
517
  Must contain default values that can be appended to,
454
518
  by default ['major_axis_length', 'minor_axis_length', 'equivalent_diameter']
519
+ bbox_expansion : float, optional
520
+ Fractional expansion of bounding boxes when cropping ROI images for export.
521
+ See :func:`extract_particles`. Defaults to 0.0 (no expansion).
455
522
 
456
523
  Returns
457
524
  -------
@@ -479,7 +546,8 @@ def statextract(imbw, timestamp, imc,
479
546
 
480
547
  stats = extract_particles(imc, timestamp, Classification, region_properties,
481
548
  export_outputpath=export_outputpath, min_length=min_length,
482
- propnames=propnames)
549
+ propnames=propnames,
550
+ bbox_expansion=bbox_expansion)
483
551
 
484
552
  return stats, saturation
485
553
 
@@ -558,6 +626,19 @@ class CalculateStats():
558
626
  roi_source: (str, optional)
559
627
  Key of an image in Pipeline.data that is used for outputting ROIs and passing to the classifier.
560
628
  Defaults to 'im_corrected'
629
+ bbox_expansion: (float, optional)
630
+ Fractional expansion applied to each particle bounding box before the
631
+ ROI is cropped and exported, e.g. ``0.1`` enlarges the crop by 10% in
632
+ width and height (5% on each side, clamped to image bounds). The
633
+ regionprops measurements and the ``minr/minc/maxr/maxc`` columns
634
+ written into stats are unaffected. Defaults to ``0.0`` (no expansion).
635
+
636
+ Configure from a TOML pipeline as::
637
+
638
+ [steps.statextract]
639
+ pipeline_class = "pyopia.process.CalculateStats"
640
+ export_outputpath = "/path/to/rois"
641
+ bbox_expansion = 0.1
561
642
 
562
643
  Returns
563
644
  -------
@@ -572,7 +653,8 @@ class CalculateStats():
572
653
  export_outputpath=None,
573
654
  min_length=0,
574
655
  propnames=['major_axis_length', 'minor_axis_length', 'equivalent_diameter'],
575
- roi_source='im_corrected'):
656
+ roi_source='im_corrected',
657
+ bbox_expansion=0.0):
576
658
 
577
659
  self.max_coverage = max_coverage
578
660
  self.max_particles = max_particles
@@ -580,6 +662,7 @@ class CalculateStats():
580
662
  self.min_length = min_length
581
663
  self.propnames = propnames
582
664
  self.roi_source = roi_source
665
+ self.bbox_expansion = bbox_expansion
583
666
 
584
667
  self.calc_image_stats = CalculateImageStats()
585
668
 
@@ -591,7 +674,8 @@ class CalculateStats():
591
674
  max_particles=self.max_particles,
592
675
  export_outputpath=self.export_outputpath,
593
676
  min_length=self.min_length,
594
- propnames=self.propnames)
677
+ propnames=self.propnames,
678
+ bbox_expansion=self.bbox_expansion)
595
679
  stats['timestamp'] = data['timestamp']
596
680
  stats['saturation'] = saturation
597
681
 
@@ -1 +0,0 @@
1
- __version__ = "2.16.4"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes