How to get Bokeh to scale scatter plot size according to zoom - bokeh

Some of the folks on my team, including myself, find it pretty disorienting that in a Bokeh scatter plot, say using the circle method, that for an initial autoscale fit of the data on the figure we can dial in a reasonable size for our data, using for example something like plot.circle( x , y , size=3 )
However when we interactively zoom into our data the glyph sizes as displayed are invariant to the zoom. Is there a way to have them scale proportionally to the zoom we've dialed into? Something akin to an vector graphics interaction (eg svg). If memory serves me right matlab figures and matplotlib figures should maintain zoom proportionality behavior. To demonstrate the behavior we're seeing consider the first image and the red box I approximately zoom into on the second image.
Just as a quick demo using Powerpoint to illustrate the sort of desired behavior...

For circles, set the radius kwarg instead of the size value. (There similar, glyph-specific values for the other glyph-types).
i.e.:
plot.circle(x=[1,2,3], y=[1,2,3], radius=0.5)
size is always rendered in screen coordinates (pixels), but radius and the related properties are computed in data coordinates and should change in magnitude with zooming.

Here's a good demo by Bryan Van de Ven showing the difference between pixel coordinates (size) and data coordinates (radius) given in this conference talk:
Intro to Data Visualization with Bokeh - Part 2 - Strata Hadoop San Jose 2016
... the point is all of these attributes can be vectorized. We could
for instance say size equals you know 2, 4, 6, 8, 10, and now the size
is modulated right. So we have one that has size 2 and one that has
size 4. Size is usually in pixels, radius is usually in data dimension
units. But all the other ones here as well all the colors, all the
visual attributes can be vectorized in this way. You can either give
them a single value as we've done for instance with the line fill
color, or you can give them a vector of values in which case all of
the things are different.
So next exercise here you go to this
notebook this is that second notebook "02 - plotting" it is to try to
create the same example but now set the radius instead of the size and
sort of see what's the difference if you set if you set radius instead
of size.

Related

ILNumerics V5: 3d plot gets distorted when rotate or pan

I have an problem: My 3d plot gets distorted, if I rotate or pan the plot. I know this behaviour is intended to show the user the most at all times, but it looks silly, so I want an orthogonal view or Axes which are equally long.
Earth distorted.
I have an WPF Application, where the ILN Form/Control is hosted via WindowsFormsHost.
I tried every possibility regarding Plotcube.Projection, have set Plotcube.Limits, changed ILN_Panel autosize etc. My next idea was that maybe I need to configure the WPF and/or Forms window itself.
Thanks!
I think that is not possible. At least not easy within PlotCube. If you do not need PlotCube just put the object into the Camera node and set Projection to Orthogonal. And you are done.
With PlotCube it is much more complicated. You must make sure that all containers have equal aspect ratio (width / height) WinformsHostControl, PlotCube, PlotCube.ScreenRect, PlotCube.DataScreenRect, PlotCube.Plots (data group), and its Limits. If you want to rotate everything free you must make sure to have equal aspect ration on all 3 dimensions wehere applicable.

Cel shading/alpha shape in current visualization

I am playing around with rgl and I have created a 3D rendering of the mouse brain, in which structures can be isolated and coloured separately.
The original data is a 3D array containing evenly spaced voxels.
Every voxel is coded with a structure ID.
Every structure is rendered separately as a mesh by marching cubes, and smoothed using Laplacian smoothing as implemented by Rvcg.
Some of these structures can be quite small, and it would make sense to look at them within the context of the whole brain structure.
One of the options is to create a low-threshold mesh of the whole set of voxels, so that only the outer surface of the brain is included in the mesh.
This surface can be smoothed and represented using a low alpha in rgl::shade3d colouring faces. This however seems to be quite taxing for the viewport as it slows down rotation etc especially when alpha levels are quite low.
I was wondering if there is any way to implement some sort of cel shading in rgl, e.g. outlining in solid colours the alpha hull of the 2D projection to the viewport in real time.
In case my description was not clear, here's a photoshopped example of what I'd need.
Ideally I would not render the gray transparent shell, only the outline.
Cel shading example
Does anybody know how to do that without getting deep into OpenGL?
Rendering transparent surfaces is slow because OpenGL requires the triangles making them up to be sorted from back to front. The sort order changes as you rotate, so you'll be doing a lot of sorting.
I can't think of any fast way to render the outline you want. One thing that might work given that you are starting from evenly spaced voxels is to render the outside surface using front="points", back="points", size = 1. Doing this with the ?surface3d example gives this fake transparency:
If that's not transparent enough, you might be able to improve it by getting rid of lighting (lit = FALSE), plotting in a colour close to the background (color = "gray90"), or some other thing like that. Doing both of those gives this:
You may also be able to cull your data so the surface has fewer vertices.

How to deal with arbitrary size for Laplacian Pyramid?

Recently I had much fun with the Laplacian Pyramid algorithm (http://persci.mit.edu/pub_pdfs/pyramid83.pdf). But one big problem is that the original paper is limited to 2^m+1*2^n+1 images. My question is: What is the best way to deal with arbitrary w*h instead? I can think of a couple of options:
Up sample the input to the next 2^m+1,2^n+1 up front
Pad even lines. How exactly? Wouldn't it shift the signal?
Shift even lines by half a sample? Wouldn't it loose half a sample?
Does anybody have experience with this? What is the most practical and efficient approach? Also any pointers to papers dealing with this would be very welcome.
One approach is to create an image with a width and height equal to the next 2^m+1,2^n+1, but instead of up-sampling the image to fill the expanded dimensions, just place it in the top-left corner and fill the empty space to the right and below with a constant value (the average value for the image is a good choice for this). Then encode in the normal way, storing the original image dimensions along with the pyramid. When decoding, decode and then crop to the original size.
This won't introduce any visual artifacts or degradation because you aren't stretching or offsetting the image in any way.
Because the empty space to the right and below the original image is a constant value, the high-pass bands at each level in the image pyramid will be all zero in this area. So if you are using a compression scheme like run length encoding to store each level this will be automatically taken care off and these areas will be compressed to almost nothing. If not then you can simply store the top-left (potentially non-zero) area of each level and then fill out the rest with zeros when decoding.
You could find the min and max x and y bounding rectangle of the non-zero values for each level and store this along with the level, cropped to include only non-zero values. The decoder could also be optimized so that areas of the image that are going to be cropped away are not actually decoded in the first place, by only processing the top-left of each level.
Here's an illustration of the technique:
Instead of just filling the lower-right area with a flat color, you could fill it with horizontally and vertically mirrored copies of the image to the right and below, and a copy mirrored in both directions to the bottom-right, like this:
This will avoid the discontinuities of the first technique, although there will be a discontinuity in dx (e.g. if the value was gradually increasing from left to right it will suddenly be decreasing). Choosing a mirror that keeps dx constant and ddx zero will avoid this second-order discontinuity by linearly extrapolating the values.
Another technique, which is similar to what some JPEG encoders do to pad out an image to a whole number of MCU blocks, is to take the last pixel value of each row and repeat it, and likewise for columns, with the bottom-right-most pixel of the image used to fill the bottom-right area:
This last technique could easily be modified to extrapolate the gradient of values or even the gradient of gradients instead of just repeating the same value for the remainder of the row or column.

Automatically extract data from graph

I have a graph like:
I would like to generate a set of (x,y) pairs that correspond to points of this graph.
Maybe one for each horizontal pixel.
How would I go about doing this?
If I had the image in uncompressed bitmap format, maybe cropped to the actual graph, I could examine each vertical strip for the blackest point...
I would prefer to work in Python, but I'm interested in any technique.
I answered a question like this a while back. It should be fairly easy to detect the grid, from there you can get the pixel's coordinates relatively to the grid. However, it wasn't clear how to extract the numbers, which you need to do in order to get the the scale of the grid. Although, it might be possible fairly easily if you can match the font and font size (which might be possible via scaling). Otherwise, you'd have to enter the numbers manually.
To extract the grid, you'd start from the top right and move diagonally until you find the start of the grid. From there you can follow the vertical and horizontal lines (of the grid) until they end. This should allow you to say with fairly high probability where the outer rectangle of the grid is and what the x and y intervals of the grid are in terms of pixels. The blackest parts within the grid should do for finding the curve, but it may require some interpolation depending on how many data points you need/want.
It also may be useful to look into techniques for reversing anti-aliasing effects. Although, the uncompressed bitmap image may not need it.

Matlab Bwareaopen equivalent function in OpenCV

I'm trying to find similar or equivalent function of Matlabs "Bwareaopen" function in OpenCV?
In MatLab Bwareaopen(image,P) removes from a binary image all connected components (objects) that have fewer than P pixels.
In my 1 channel image I want to simply remove small regions that are not part of bigger ones? Is there any trivial way to solve this?
Take a look at the cvBlobsLib, it has functions to do what you want. In fact, the code example on the front page of that link does exactly what you want, I think.
Essentially, you can use CBlobResult to perform connected-component labeling on your binary image, and then call Filter to exclude blobs according to your criteria.
There is not such a function, but you can
1) find contours
2) Find contours area
3) filter all external contours with area less then threshhold
4) Create new black image
5) Draw left contours on it
6) Mask it with a original image
I had the same problem and came up with a function that uses connectedComponentsWithStats():
def bwareaopen(img, min_size, connectivity=8):
"""Remove small objects from binary image (approximation of
bwareaopen in Matlab for 2D images).
Args:
img: a binary image (dtype=uint8) to remove small objects from
min_size: minimum size (in pixels) for an object to remain in the image
connectivity: Pixel connectivity; either 4 (connected via edges) or 8 (connected via edges and corners).
Returns:
the binary image with small objects removed
"""
# Find all connected components (called here "labels")
num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(
img, connectivity=connectivity)
# check size of all connected components (area in pixels)
for i in range(num_labels):
label_size = stats[i, cv2.CC_STAT_AREA]
# remove connected components smaller than min_size
if label_size < min_size:
img[labels == i] = 0
return img
For clarification regarding connectedComponentsWithStats(), see:
How to remove small connected objects using OpenCV
https://www.programcreek.com/python/example/89340/cv2.connectedComponentsWithStats
https://python.hotexamples.com/de/examples/cv2/-/connectedComponentsWithStats/python-connectedcomponentswithstats-function-examples.html
The closest OpenCV solution to your question is the morphological closing or opening.
Say you have white regions in your image that you need to remove. You can use morphological opening. Opening is erosion + dilation, in that order. Erosion is when the white regions in your image are shrunk. Dilation is (the opposite) where white regions in your image are enlarged. When you perform an opening operation, your small white region is eroded until it vanishes. Larger white features will not vanish but will be eroded from the boundary. The subsequent dilation step restores their original size. However, since the small element(s) vanished during the erosion step, they will not appear in the final image after dilation.
For example consider this image where we want to remove the small white regions but retain the 3 large white ellipses. Running the following code removes the white regions and displays the clean image
import cv2
im = cv2.imread('sample.png')
clean = cv2.morphologyEx(im, cv2.MORPH_OPEN, np.ones((10, 10)))
cv2.imshwo("Clean image", clean)
The clean image output would be like this.
The command above uses a square block of size 10 as the kernel. You can modify this to suit your requirement. You can even generate a more advanced kernel using the function getStructuringElement().
Note that if your image is inverted, i.e., with black noise on a white background, you simply need to use the morphological closing operation (cv2.MORPH_CLOSE method) instead of opening. This reverses the order of operation - first the image is eroded and then dilated.

Resources