How to create gradient between two curves? - cairo

I have two curves, one inside another, for example ellipse inside circle. I need to create gradient between them.
Here is formula for better explanation:
d_e = min_dist(ellipse,pixel)
d_c = min_dist(circle,pixel)
pixel_color = (e_color * d_e + c_color * d_c) / (d_e + d_c)

Cairo only has radial patterns which are defined by two circles, not an ellipse and a circle.
The other alternatives are mesh gradients (new in cairo 1.12), but for this you would need to calculate a piecewise approximation yourself. Sounds hard and would only be a rough approximation.
So I guess the best suggestions that I can make is: Draw that thing yourself by setting the individual pixels yourself and use the result as an image surface.

Related

Calculating area on N points

Im trying to calculate numerically an area of different shapes where the only thing I know about them is the (x,y) of each corner.
For example the shapes are:
P.s. The points inside the shape are for other calculation, I only need the area of the most outer shape.
Thank you.
Create polygon, and use polyarea function.
Given x,y location of corners than:
Area=polyarea(x,y)

Generate tubes with non-circular cross-sections in MuPad

Using plot::tube function in MuPAD, I can generate tubes with varying spine but the cross-section is always a circle, although the radius can vary along the spine. For instance:
plot::Tube([cos(t), sin(t), 0], 0.4 + 0.3*sin(t)*cos(t),t = -0.5*PI..0.5*PI,Mesh=[60,12]):
I want to plot tubes with (non-circular) elliptical cross-sections. Is there a way to achieve this in MuPAD?
P.S. I can generate tubes with arbitrary cross-sections using MATLAV, so please avoid including answers that use pure MATLAB commands.
As for your first question whether this can be done with plot::Tube: I don't think so. Consider the help of this function (emphasis mine):
plot::Tube creates generalized tubular plots, known as "canal
surfaces", with special cases known as "tube surface", "pipe surface"
or "tubular surfaces."
Intuitively, canal surfaces are space curves with thickness. More formally, a canal surface plot::Tube([x(t), y(t), z(t)], r(t), t = t_min..t_max) is the envelope of spheres with center [x(t), y(t), z(t)] and radius r(t), i.e., the thickness of the curve can vary with
the curve parameter t
The fact that a tube is defined as an envelope of a collection of spheres suggests that their cross-section is inherently circular.
I'm not familiar with MuPAD, so I don't know the elegant solution to your problem. For your simple example of a semi-circular base line I could put together this kludgy solution using the low-level plot::Surface, manually constructing the surface:
plot(
plot::Surface(
matrix([cos(t),sin(t),0])
+ numeric::rotationMatrix(t,[0,0,1]) * matrix([(0.2+0.1*sin(2*t))*cos(u),0,(0.2+0.1*cos(2*t))*sin(u)]),
t = -PI/2..PI/2,
u = 0..2*PI,
Mesh = [30,30]),
Scaling=Constrained)
Here t stands for the angular parameter along the semi-circular base line (toroidal direction), and u is the angle along the cross-section (poloidal direction). A given cross-section at angle t looks like this:
[(0.2+0.1*sin(2*t))*cos(u), 0, (0.2+0.1*cos(2*t))*sin(u)]
I.e. the semimajor axes are (0.2+0.1*sin(2*t)) and (0.2+0.1*cos(2*t)) along the cross-section of the tube.
You can see that I used a rotation matrix around the z axis to construct the surface. This made heavy use of the fact that the base line is a semi-circle. However, in general cases it should be possible to compute the derivative of your parameterized base line (with respect to t), and compute the necessary rotation angle (with parameter t) from that.

Matlab image processing - problems with recognizing circles [duplicate]

I have the image includes circular, elipsoidal, square objects and somethings like these. I want to get only circual objects. I applyed a filter by using Solidity and Enccentricity levels of objets but I could not remove square objects. Square objects which have not sharp corners have nearly same Solidity and Enccentricity level with circular objects.
My question is that is there any other parameter or way to detect square objects?
You can compare the area of the mask to its perimeter using the following formula
ratio = 4 * pi * Area / ( Perimeter^2 )
For circles this ration should be very close to one, for other shapes it should be significantly lower.
See this tutorial for an example.
The rationale behind this formula: circles are optimal in their perimeter-area ratio - max area for given perimeter. Given Perimeter, you can estimate radius of equivalent circle by Perimeter = 2*pi*R, using this estimated R you can compute the "equivalent circle area" using eqArea = pi*R^2. Now you only need to check the ratio between the actual area of the shape and the "equivalent area" computed.
Note: since Area and Perimeter of objects in mask are estimated based on the pixel-level discretization these estimates may be quite crude especially for small shapes. Consider working with higher resolution masks if you notice quantization/discretization errors.
There exists a Hough transform (imfindcircles) in order to find circles within an image which is what you needed in the first place.

Matlab Solid Circles

What we want is to draw several solid circles at random locations, with random gray scale colors, on a dark gray background. How can we do this? Also, if the circles overlap, we need them to change color in the overlapping part.
Since this is an assignment for school, we are not looking for ready-made answers, but for a guide which tools to use in MATLAB!
Here's a checklist of things I would investigate if you want to do this properly:
Figure out how to draw circles in MATLAB. Because you don't have the Image Processing Toolbox (see comments), you will probably have to make a function yourself. I'll give you some starter code:
function [xout, yout] = circle(x,y,r,rows,cols)
[X,Y] = meshgrid(x-r:x+r, y-r:y+r);
ind = find(X.^2 + Y.^2 <= r^2 & X >= 1 & X <= cols & Y >= 1 & Y <= rows);
xout = X(ind);
yout = Y(ind);
end
What the above function does is that it takes in an (x,y) co-ordinate as well as the radius of
the circle. You also will need to specify how many rows and how many columns you want in your image. The reason why is because this function will prevent giving you co-ordinates that are out of bounds in the image that you can't draw. The final output of this will give you co-ordinates of all values inside and along the boundary of the circle. These co-ordinates will already be in integer so there's no need for any rounding and such things. In addition, these will perfectly fit when you're assigning these co-ordinates to locations in your image. One caveat to note is that the co-ordinates assume an inverted Cartesian. This means that the top left corner is the origin (0,0). x values increase from left to right, and y values increase from top to bottom. You'll need to keep this convention in mind when drawing circles in your image.
Take a look at the rand class of functions. rand will generate random values for you and so you can use these to generate a random set of co-ordinates - each of these co-ordinates can thus serve as your centre. In addition, you can use this class of functions to help you figure out how big you want your circles and also what shade of gray you want your circles to be.
Take a look at set operations (logical AND, logical OR) etc. You can use a logical AND to find any circles that are intersecting with each other. When you find these areas, you can fill each of these areas with a different shade of gray. Again, the rand functions will also be of use here.
As such, here is a (possible) algorithm to help you do this:
Take a matrix of whatever size you want, and initialize all of the elements to dark gray. Perhaps an intensity of 32 may work.
Generate a random set of (x,y) co-ordinates, a random set of radii and a random set of intensity values for each circle.
For each pair of circles, check to see if there are any co-ordinates that intersect with each other. If there are such co-ordinates, generate a random shade of gray and fill in these co-ordinates with this new shade of gray. A possible way to do this would be to take each set of co-ordinates of the two circles and draw them on separate temporary images. You would then use the logical AND operator to find where the circles intersect.
Now that you have your circles, you can plot them all. Take a look at how plot works with plotting matrices. That way you don't have to loop through all of the circles as it'll be inefficient.
Good luck!
Let's get you home, shall we? Now this stays away from the Image Processing Toolbox functions, so hopefully these must work for you too.
Code
%%// Paramters
numc = 5;
graph_size = [300 300];
max_r = 100;
r_arr = randperm(max_r/2,numc)+max_r/2
cpts = [randperm(graph_size(1)-max_r,numc)' randperm(graph_size(2)-max_r,numc)']
color1 = randperm(155,numc)+100
prev = zeros(graph_size(1),graph_size(2));
for k = 1:numc
r = r_arr(k);
curr = zeros(graph_size(1),graph_size(2));
curr(cpts(k,1):cpts(k,1)+r-1,cpts(k,2):cpts(k,2)+r-1)= color1(k)*imcircle(r);
common_blob = prev & curr;
curr = prev + curr;
curr(common_blob) = min(color1(1),color1(2))-50;
prev = curr;
end
figure,imagesc(curr), colormap gray
%// Please note that the code uses a MATLAB file-exchange tool called
%// imcircle, which is available at -
%// http://www.mathworks.com/matlabcentral/fileexchange/128-imcircle
Screenshot of a sample run
As you said that your problem is an assignment for school I will therefore not tell you exactly how to do it but what you should look at.
you should be familiar how 2d arrays (matrices) work and how to plot them using image/imagesc/imshow ;
you should look at the strel function ;
you should look at the rand/randn function;
such concepts should be enough for the assignment.

Identify Shapes with Matlab

I created some MATLAB code, that find somes shapes in an image
using regionpros and bwbounaries functions.
I have:
STATS = regionprops(L, 'all');
and from STATS I could easily find all my shapes Area and Perimeter.
My problem is the following: I want to find the "square" shapes and I do
in all shapes the following calculation 16 * area / (perimeter * perimeter),
if this value is near one then I "may" have a square. But other shapes too like
circles or rectangles are near one too. (Also some squares could be rotated
in the image).
Is there a better way to distinguish the shapes (like circles, triangles ...)?
Matlab has a function
procrustes(X,Y)
which will compute distance between two shapes based on the types of transformations it would take to move the points defined by X onto the points defined by Y. For many shape classification tasks, minimizing this distance is a useful way of categorizing noisy instances of shapes. If your problem has 'perfect' shapes, this should work extremely well. Just have Y fixed as a perfect square, and any time that the linear transformation from X to Y is a pure scaling, then you know X is also a square. You could do some simple logical checking to select only shapes satisfying this sort of property.