3D scatterplot of an image
alexander.engineering
alexander.engineering
It was literally both cheaper and faster to have a grad student count the cells.
Let's be clear though: the researchers weren't interested in the cells; they were interested in having a pretty-darn-good count of cancerous cells vs. non-cancerous cells. Turns out, cancerous cells were a different color (brighter blue * brighter green) than healthy cells. So, instead, I just converted every image into RGB 3D space, counted all the pixels near 'dark green * dark blue', all the pixels near 'bright green * bright blue' then divided by the average area (in pixels) of each type of cell. The resulting counts were within 1% of the value the grad students could get, and the ratio was even more accurate.
We could get the cell count in a single linear, forward pass, as fast as the camera could take pictures.
Instead of trying to segment objects, remove backgrounds, do skeleton tracking, etc., just count pixels that fall within a 3D bounding volume.
Simple solutions are sometimes underappreciated. It helps, as you allude to after "let's be clear," to know what problem you really are trying to solve.
I wish I had more examples of algorithms where it is best explained as acting on a data structure that is not actually present, but all I can think of right now is using generators to represent a list.
In the application I remember, the average color of a loaf was tracked on an RBG plot as a function of time. The idea was that the baking process followed a trajectory in the RGB space that was dependent on the temperature of the oven and the elapsed time. This can be used as feedback for process control-- to signal when to pull out the bread or to change the temperature.
In a similar way the color of paintings change as they age. The individual points in the OP's plots could be parameterized in time and according to paint's chemistry. It might be possible, after some calibration studies, to accurately simulate aging. Or better, simulate the reversal of aging to show what an old aged painting looked like when it was new.
Thank you for including both HSV and HSL. Not enough people appear to understand/care about the difference between the two, and for painters the distinction is everything.
(Disclaimer: I largely wrote the wikipedia article about HSL and HSV, years ago.)
* Take fourier transform of the image for each color R, G, B
* Randomly scramble the phase of the transformed image.
* Perform the fourier inverse of that scrambled phase image.
The result is another 2D image with the same colors AND spatial frequencies as the original image. It looks like you took the original photo and vaporized it into gas. Interesting.
I should have probably written more comments, but I really need to go sleep now.
library(imager)
download.file("https://upload.wikimedia.org/wikipedia/en/2/24/Lenna.png",'lena.png', mode = 'wb')
lena <- load.image("./lena.png")
plot(lena)
lena_fft <- FFT(lena)
lena_pwr <- sqrt( lena_fft$real^2 + lena_fft$imag^2)
lena_ph <- atan2(lena_fft$imag, lena_fft$real)
lena_ph[1:512,1:512,1,] <- matrix(runif(512*512,-pi,pi),ncol=512)
lena_mess <- FFT(lena_pwr*cos(lena_ph),lena_pwr*sin(lena_ph),inverse = TRUE)
plot(sqrt(lena_mess$real^2 + lena_mess$imag^2))Let's say if we have a 4096 times 4096 image we can reach and fill all values in the 3d representation, if we want to!
Now I would pose another question: would it be possible to make a human-recognizable 3D-object in all the four color spaces that is also a pretty picture in 2D?
However the luminance component of the image could probably be adjusted within certain error margins and vice versa. Perhaps by some form of bruteforce!
To know for sure I suppose coding is needed!
Has a few extra features like being able to see different visualisation methods and how basic colour correction influences those - also animates the visualisation while going through the image
Realluy caught me off-guard because I used both the starry sky and the monalisa painting back in the days as well!
Do you have an online demo handy?
If you want 16 colors, just find 16 clusters and their centroids (e.g. let k=16 for k-means clustering). Replace each pixel with the closest centroid. Then, your image is quantized (and can perhaps be stored more efficiently)!
Effectively you are non-uniformly resampling based on distribution, so relative values/distances go out the window but you keep "detail" in the lower fidelity signal.
In the example images, the sand in the sand+sky picture is the only thing this is really true for.
Now imagine you rolled the card into a cylinder. The result would depend on the lighting, but most likely you'd be able to see some shading across the object, so that there are some darker and lighter pixels. In, the HSV colour space you'd now have a line - all the H and S values for those pixels would be the same, but there would be a range of values for V.
Now imagine you replaced the matt card with a shiny piece. You might see a whitish specular highlights where the object reflects a light source or the sky. The added whiteness would have made some pixels have a lower saturation (S). So now you have variation in S and V, but not H. That would form a plane in the HSV plot.
http://beneast.com/wp-content/uploads/2017/09/fahrelnissa-ze...
Well, not that flat actually, the way the image were processed also makes them flatter than they really are see
https://uploads2.wikiart.org/images/vincent-van-gogh/the-sta...
for example.
Another way to explain why a cylinder is only good for representing two dimensions is simply that a circle asserts that length(x) == width(y) leaving only 2 values represented by a cylinder: (x,y) and z.
https://bainbridgecode.wordpress.com/2012/04/24/beating-png-...
and
https://bainbridgecode.wordpress.com/2012/05/07/beating-png-...
There are plots at the end of part 3 showing the image channels separately for YCrCb and my custom PCA derived space. They clearly show that there's a lot less duplication of data between channels with the latter. And that in turn is obviously good for compression.
"One Million Colors" https://upload.wikimedia.org/wikipedia/commons/thumb/d/d6/1M...
"RGB HSV Image" https://www.gimp.org/tutorials/Digital_Black_and_White_Conve...
Color in image reproduction is notoriously difficult to measure by simply looking at a whole image. Much of what we perceive as color characteristics are contextually dependent. And while the characteristics may not vary, the level of contextual dependence seems to. Females are more likely to have more reliable contextually affected color perception than males.
If you look at such an image, you will have two clusters of pixels, one for the green screen, and one for the actor. By selecting the appropriate cluster you now know which pixels you need to replace for compositing your actor in front of a CGI background.
Here is a shameless plug for one of my color extracting library: https://github.com/jathu/UIImageColors/
It currently takes around ~0.3s on average to extract the colors. However, with my new PR (https://github.com/jathu/UIImageColors/pull/54), it takes around ~0.14s on average. IMO this is still slow, I would like to bring it below 0.1s.
I tried to optimize this with k-means to reduce total number of colors, but the result was slower and worse color choices. If anyone has methods to improve the performance, please make a PR.
Just in case the author is here, I tried on an iPad Pro, and got "WebGL is not supported by your browser". WebGL is in fact supported by mobile Safari, so I'm guessing this site is using a user agent whitelist or some other fallible method of detecting WebGL. The best way to detect WebGL support is to attempt to create the 3d context and wait until after it actually fails. That, or simply do not check for WebGL failure; the browsers all handle it anyway.
Next up: Finding patterns in the graph for certain artists, themes, styles, etc.
I daresay technically this applies to all useful visualizations of the data. I don't think they'd be very useful if they weren't, in some way, based on the pixel values.