Expose number of subsamples in ImageItem auto-level determination (#1638)
* exposed number of subsamples in auto-level determination * Removing print statement at @NilsNemitz's request * make levelSamples count pixels, not pixels * channels * minimum number of samples can be 2 if we look at pixels anyway * adjusted minimum levelSamples to 4: Otherwise a 2x2 image downsamples to a single pixel * extended docstring for level to make the user aware of auto-level subsampling * subsample towards square array for auto-leveling * eliminated duplicated code between level downsampling and samples and QuickMinMax method Co-authored-by: Ogi Moore <ognyan.moore@gmail.com>
This commit is contained in:
parent
823988d51c
commit
f002d70adc
@ -343,6 +343,12 @@ class ImageItem(GraphicsObject):
|
|||||||
If False, the search will be omitted.
|
If False, the search will be omitted.
|
||||||
|
|
||||||
The default is `False` if a ``levels`` keyword argument is given, and `True` otherwise.
|
The default is `False` if a ``levels`` keyword argument is given, and `True` otherwise.
|
||||||
|
|
||||||
|
levelSamples: int, default 65536
|
||||||
|
When determining minimum and maximum values, ImageItem
|
||||||
|
only inspects a subset of pixels no larger than this number.
|
||||||
|
Setting this larger than the total number of pixels considers all values.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
profile = debug.Profiler()
|
profile = debug.Profiler()
|
||||||
|
|
||||||
@ -378,10 +384,8 @@ class ImageItem(GraphicsObject):
|
|||||||
else:
|
else:
|
||||||
autoLevels = True
|
autoLevels = True
|
||||||
if autoLevels:
|
if autoLevels:
|
||||||
img = self.image
|
level_samples = kargs.pop('levelSamples', 2**16)
|
||||||
while img.size > 2**16:
|
mn, mx = self.quickMinMax( targetSize=level_samples )
|
||||||
img = img[::2, ::2]
|
|
||||||
mn, mx = self._xp.nanmin(img), self._xp.nanmax(img)
|
|
||||||
# mn and mx can still be NaN if the data is all-NaN
|
# mn and mx can still be NaN if the data is all-NaN
|
||||||
if mn == mx or self._xp.isnan(mn) or self._xp.isnan(mx):
|
if mn == mx or self._xp.isnan(mn) or self._xp.isnan(mx):
|
||||||
mn = 0
|
mn = 0
|
||||||
@ -457,11 +461,15 @@ class ImageItem(GraphicsObject):
|
|||||||
Returns (`min`, `max`).
|
Returns (`min`, `max`).
|
||||||
"""
|
"""
|
||||||
data = self.image
|
data = self.image
|
||||||
while data.size > targetSize:
|
if targetSize < 2: # keep at least two pixels
|
||||||
ax = self._xp.argmax(data.shape)
|
targetSize = 2
|
||||||
sl = [slice(None)] * data.ndim
|
while True:
|
||||||
sl[ax] = slice(None, None, 2)
|
h, w = data.shape[:2]
|
||||||
data = data[sl]
|
if h * w <= targetSize: break
|
||||||
|
if h > w:
|
||||||
|
data = data[::2, ::] # downsample first axis
|
||||||
|
else:
|
||||||
|
data = data[::, ::2] # downsample second axis
|
||||||
return self._xp.nanmin(data), self._xp.nanmax(data)
|
return self._xp.nanmin(data), self._xp.nanmax(data)
|
||||||
|
|
||||||
def updateImage(self, *args, **kargs):
|
def updateImage(self, *args, **kargs):
|
||||||
|
Loading…
Reference in New Issue
Block a user