Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

synchronize default scaling among ImageShow, ImageView, and Plots? #7

Open
JeffBezanson opened this issue Jan 20, 2019 · 5 comments
Open

Comments

@JeffBezanson
Copy link

Given color components outside [0,1], currently we have the following:

  • ImageShow/IJulia: clamp
  • ImageView: uses minimum and maximum value as black and white
  • Plots: errors

It would be nice to handle this consistently. I prefer the ImageView.jl behavior, since it generally lets you see as much data as possible. However, I will also suggest the following algorithm:

  • Let lo, hi = extrema(image)
  • Black = 0 <= lo <= 1 ? 0 : lo
  • White = 0 <= hi <= 1 ? 1 : hi

The intuition is as follows:

  • If all values are between 0 and 1, just use them directly as intensities.
  • If the values are all over the place, use the min and max as black and white (what ImageView does now).
  • If values are generally in [0,1] but some go outside the range in one direction, rescale around 0 or 1 to bring those values back into range.

The advantage of this is that when some values overflow or underflow a bit, 0.5 still looks "grayish" just like it would if you clamped the values, but without losing information.

@mkborregaard
Copy link

mkborregaard commented Jan 21, 2019

Why not just have Black = 0; White = 1 though and clamp? That is the most accurate way of depicting the underlying color information in the matrix of Grays. If it's to use this to visualize matrix values (so you need relative contrasts to be as large as possible) then possibly a heatmap is more appropriate?

@JeffBezanson
Copy link
Author

Often a processed image has values in a different range, e.g. after convolution with certain kernels, or because it came from some data source with a strange representation. Now of course, in those cases you might eventually apply some custom scaling to get a real usable image out, but for development it's nice to be able to quickly look at the data with some reasonable default scaling.

I suppose if the Gray type means intensity from 0 to 1, then clamping is indeed the right thing, and it would be nice for all image-displaying packages to adopt that consistently. My problem is that I've been using Gray.(a) as a way to tell e.g. Plots that the data should be treated as an image. Do we have, or should we have, a way to label values as image-like without specifying a scale or color space? E.g. ScalarIntensity, or UnscaledGray or something like that?

@mkborregaard
Copy link

I agree completely on the consistency. But not sure I understand what you mean by telling Plots you want the data treated like an image. Isn't that what heatmap is for?

using Plots
a = 0.6rand(200,200).+0.2
plot(
          plot(Gray.(a)),
          heatmap(a, c = :grays),
          heatmap(a, c = :grays, clim = (0,1), legend = false),
          layout = (1,3), size = (800, 250)
          )

testgray

IIUC heatmap(a, c = :grays) does exactly what you'd want?

@JeffBezanson
Copy link
Author

Ok, I agree. We should consistently render Gray by clamping to [0,1], and at least when using Plots I'll just use a heatmap.

@mkborregaard
Copy link

Great, I'll implement the clamp.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants