Correct scaling of circular markers in scatter plot - matlab

I have a system of finite size circular particles (say r=5cm) which I need to plot in a given domain (say L=5m). Since they are many, scatter is faster than any cyclic use of rectangle.
What is unclear to me is the correct way to define the diameter/radius of the circles/marker so to scale correctly with the domain geometry which is plotted as well. (By using rectangle, the diameter of the particle can be easily defined.)
Based on this answer, it is possible to have fine control of the marker size, although the real scaling is obscure to me.
Can anyone shed some light?

The SCATTER function expects its 'S' parameter to contain the marker
area in points squared. This area corresponds to the area of a square
bounding box around the marker.
The source is the technical solution "How do I specify the size of the markers created by the SCATTER plot in units proportional to the data being plotted in MATLAB 7.6 (R2008a)?"
Check out the code in the link.

The official documentation states:
MarkerSize
Marker size. Size of the marker in points. The default value is 6.
Note that one point is 1/72 of an inch, so it's an absolute measurement unit.
If you want to tune the marker sizes according to the axis scale of your plot, do a simple unit conversion: calibrate 1 tick in one of the axes to points (you can do it by trial and error), and then normalize all your marker sizes by it (it doesn't, however, occur to me how you'd keep the marker sizes relative to the plot's zoom level in a straightforward manner).
By the way, you can specify the sizes of the markers directly as the third parameter in the scatter command. With this, you can avoid the get and set manipulations mentioned in the answer to which have linked your question.

Related

Is it possible to find the depth of an internal point of an object using stereo images (or any other method)?

I have image of robot with yellow markers as shown
The yellow points shown are the markers. There are two cameras used to view placed at an offset of 90 degrees. The robot bends in between the cameras. The crude schematic of the setup can be referred.
https://i.stack.imgur.com/aVyDq.png
Using the two cameras I am able to get its 3d co-ordinates of the yellow markers. But, I need to find the 3d-co-oridnates of the central point of the robot as shown.
I need to find the 3d position of the red marker points which is inside the cylindrical robot. Firstly, is it even feasible? If yes, what is the method I can use to achieve this?
As a bonus, is there any literature where they find the 3d location of such internal points which I can refer to (I searched, but could not find anything similar to my ask).
I am welcome to a theoretical solution as well(as long as it assures to find the central point within a reasonable error), which I can later translate to code.
If you know the actual dimensions, or at least, shape (e.g. perfect circle) of the white bands, then yes, it is feasible and possible.
You need to do the following steps, which are quite non trivial to do, and I won't do them here:
Optional but extremely suggested: calibrate your camera, and
undistort it.
find the equation of the projection of a 3D circle into a 2D camera, for any given rotation. You can simplify this by assuming the white line will be completely horizontal. You want some function that takes the parameters that make a circle and a rotation.
Find all white bands in the image, segment them, and make them horizontal (rotate them)
Fit points in the corrected white circle to the equation in (1). That should give you the parameters of the circle in 3d (radious, angle), if you wrote the equation right.
Now that you have an analytic equation of the actual circle (equation from 1 with parameters from 3), you can map any point from this circle (e.g. its center) to the image location. Remember to uncorrect for the rotations in step 2.
This requires understanding of curve fitting, some geometric analytical maths, and decent code skills. Not trivial, but this will provide a solution that is highly accurate.
For an inaccurate solution:
Find end points of white circles
Make line connecting endpoints
Chose center as mid point of this line.
This will be inaccurate because: choosing end points will have more error than fitting an equation with all points, ignores cone shape of view of the camera, ignores geometry.
But it may be good enough for what you want.
I have been able to extract the midpoint by fitting an ellipse to the arc visible to the camera. The centroid of the ellipse is the required midpoint.
There will be wrong ellipses as well, which can be ignored. The steps to extract the ellipse were:
Extract the markers
Binarise and skeletonise
Fit ellipse to the arc (found a matlab function for this)
Get the centroid of the ellipse
hsv_img=rgb2hsv(im);
bin=new_hsv_img(:,:,3)>marker_th; %was chosen 0.35
%skeletonise
skel=bwskel(bin);
%use regionprops to get the pixelID list
stats=regionprops(skel,'all');
for i=1:numel(stats)
el = fit_ellipse(stats(i).PixelList(:,1),stats(i).PixelList(:,2));
ellipse_draw(el.a, el.b, -el.phi, el.X0_in, el.Y0_in, 'g');
The link for fit_ellipse function
Link for ellipse_draw function

How to draw a best fit mesh on a set of points in 2D

I have a problem where we have a grid of points and I'd like to fit a "deformed grid which would best fit the set of points.
The MatLab data can be found at:
https://drive.google.com/file/d/14fKKEC5BKGDOjzWupWFSmythqUrRXae4/view?usp=sharing
You will see that cenX and cenY are the x and y coordinates of these centroids.
Like on this image. To note is that there are points missing, and there are a few extra points. Moreover, You can see some lines are not one single line from left to right, however, we could safely assume that the fitting a line somewhat horizontally (+-5degrees) would properly link the points into a somewhat deformed grid.
The vertical lines are trivial because that is how we generated these dots. We can find the number of lines required through a mode of the count of points on each of the columns of the grid.
I'd like to be able to ensure that a point is only part of one line, as this is a grid.

how to change axes limits in a 3D matlab plot

I have a 3-D plot which I want to cut somehow to show the most interested part and avoid the flat parts (as shown in the picture the blue and orange parts to be the least). I think that it can be done using change of the axis limits in x but different for x_{back} and x_{front} which means I want to change the limits of x front axis to (-20,20) and x back to (-80,-40). How can I do this?
I think krisdestruction is right, it would be such an infrequently-used feature that it's probably not worth the development time or added complexity for TMW to implement.
But you could kludge it. If you were to rotate your data so that the feature aligns with the axes then you could crop the plot to the region of interest as desired. Then hide the grid and draw a new one yourself.
If you're careful you can arrange it so that you can still use the axis labels at the front, which will save you some time, but if not you can always use text to draw new ones on.
I would rotate the data using a rotational transform matrix, which will be pretty quick, and you might be able to pull the gridlines out of the gca object and apply the rotation matrix to those too, which would save you from having to compute them all explicitly.
If you expect to do this more than once or twice then you could encapsulate it all in a nice function that works out the rotation angle from a given pair of 'front' and 'back' axis limits.
Then you can post it to the file exchange : )

Rounded corner rectangle coordinate representation

Simple rounded corner rectangle code in Matlab can be written as follows.
rectangle('Position',[0,-1.37/2,3.75,1.37],...
'Curvature',[1],...
'LineWidth',1,'LineStyle','-')
daspect([1,1,1])
How to get the x and y coordinates arrays of this figure?
To get the axes units boundaries, do:
axisUnits = axis(axesHandle) % axesHandle could be gca
axisUnits will be an four elements array, with the following syntax: [xlowlim xhighlim ylowlim yhighlim], it will also contain the zlow and zhigh for 3-D plots.
But I think that is not what you need to know. Checking the matlab documentation for the rectangle properties, we find:
Position four-element vector [x,y,width,height]
Location and size of rectangle. Specifies the location and size of the
rectangle in the data units of the axes. The point defined by x, y
specifies one corner of the rectangle, and width and height define the
size in units along the x- and y-axes respectively.
It is also documented on the rectangle documentation:
rectangle('Position',[x,y,w,h]) draws the rectangle from the point x,y
and having a width of w and a height of h. Specify values in axes data
units.
See if this illustrate what you want. You have an x axis that goes from −100 to 100 and y axis that goes from 5 to 15. Suppose you want to put a rectangle from −30 to −20 in x and 8 to 10 in y.
rectangle('Position',[-30,8,10,2]);
As explained by the comments there appears to be no direct way to query the figure created by rectangle and extract x/y coordinates. On the other hand, I can think of two simple strategies to arrive at coordinates that will closely reproduce the curve generated with rectangle:
(1) Save the figure as an image (say .png) and process the image to extract points corresponding to the curve. Some degree of massaging is necessary but this is relatively straightforward if blunt and I expect the code to be somewhat slow at execution compared to getting data from an axes object.
(2) Write your own code to draw a rectangle with curved edges. While recreating precisely what matlab draws may not be so simple, you may be satisfied with your own version.
Whether you choose one of these approaches boils down to (a) what speed of execution you consider acceptable (b) how closely you need to replicate what rectangle draws on screen (c) whether you have image processing routines, say for reading an image file.
Edit
If you have the image processing toolbox you can arrive at a set of points representing the rectangle as follows:
h=rectangle('Position',[0,-1.37/2,3.75,1.37],...
'Curvature',[1],...
'LineWidth',1,'LineStyle','-')
daspect([1,1,1])
axis off
saveas(gca,'test.png');
im = imread('test.png');
im = rgb2gray(im);
figure, imshow(im)
Note that you will still need to apply a threshold to pick the relevant points from the image and then transform the coordinate system and rearrange the points in order to display properly as a connected set. You'll probably also want to tinker with resolution of the initial image file or apply image processing functions to get a smooth curve.

Matlab: find major axis of binary area

the output of some processing consists of a binary map with several connected areas.
The objective is, for each area, to compute and draw on the image a line crossing the area on its longest axis, but not extending further. It is very important that the line lies just inside the area, therefore ellipse fitting is not very good.
Any hint on how to do achieve this result in an efficient way?
If you have the image processing toolbox you can use regionprops which will give you several standard measures of any binary connected region. This includes
You can also get the tightest rectangular bounding box, centroid, perimeter, orientation. These will all help you in ellipse fitting.
Depending on how you would like to draw your lines, the regionprops function also returns the length for major and minor axes in 2-D connected regions and does it on a per-connected-region basis, giving you a vector of axis lengths. If you specify 4 neighbor connected you are fairly sure that the length will be exclusively within the connected region. But this is not guaranteed since `regionprops' calculates major axis length of an ellipse that has the same normalized second central moment as the connected region.
My first inclination would be to treat the pixels as 2D points and use principal components analysis. PCA will give you the major axis of each region (princomp if you have the stat toolbox).
Regarding making line segments and not lines, not knowing anything about the shape of these regions, an efficient method doesn't occur to me. Assuming the region could have any arbitrary shape, you could just trace along each line until you reach the edge of the region. Then repeat in the other direction.
I assumed you already have the binary image divided into regions. If this isn't true you could use bwlabel (if the regions aren't touching) or k-means (if they are) first.