My problem is as follows:
I have the picture of a half cylinder taken from a horizontal perspective and it has square grid lines on it, so I was wondering how can I implement in MATLAB to unwrap this half cylinder so all my grid cells become the same size? I know I will loose lots of resolution in the edge cells and a simple linear interpolation should do the trick, but I do not know how to tell MATLAB to do this. Also I know the geometrical properties of the cylinder, radius and height. Any help is greatly appreciated.
This is the approach I am using, but I am trying to find the transformation that will make the edges be same size as inner cells.
im=imread('Capture.png');
imshow(im);
impixelinfo
r = #(x) sqrt(x(:,1).^2 + x(:,2).^2);
w = #(x) atan2(x(:,2), x(:,1));
f = #(x) [sqrt(r(x)) .* cos(w(x)), sqrt(r(x)) .* sin(w(x))];
g = #(x, unused) f(x);
tform2 = maketform('custom', 2, 2, [], g, []);
im3 = imtransform(im, tform2, 'UData', [-1 1], 'VData', [-1 1], ...
'XData', [-1 1], 'YData', [-1 1]);
figure,
imshow(im3)
I think the transformation is much simpler than what you're trying to do. Take a look at the (forward) transformation to take a flat grid and wrap it around a cylinder. The coordinates along the axis of the cylinder (the y coordinates, in this case) are unchanged. If we take the range of the grid coordinates in the x direction to be [-1,1], the coordinates on the cylinder will be:
sin(x × π/2)
Since this is the forward transformation going from a grid to the cylinder, it is also the inverse transformation going from the cylinder to the grid.
f = #(x, unused) [sin(x (:, 1) * pi / 2), x(:, 2)]
tform2 = maketform('custom', 2, 2, [], f, []);
im3=imtransform(img, tform2, 'UData', [-1 1], 'VData', [-1 1], ...
'XData', [-1 1], 'YData', [-1 1]);
Result:
This still isn't perfect, primarily because the original image has borders around it that we're transforming along with the rest of the image. This could be improved by cropping the image to contain only the cylinder portion.
Related
If I have the coordinates of the points on the outline of an arbitrary 2D shape, how can I find the coordinates of points composing the outline of a stair step curve, which best represents the original outline, but only use a set of known coordinates (xi, i=1,...,n and yi, i=1,...,m). For example the original triangle is represented by the thick solid blue line. it's different from the matlab stairs function, if my understanding is correct.
matlab code will be nice, but in other language is also ok, algorithm is most important.Thanks.
I'll start by defining a set of sample data based on your plot. Assuming that the pixel centers are aligned at integer values (the convention MATLAB follows) and that the lower left corner is at (0.5, 0.5), here's the data we get:
vx = [1.5; 9.7; 3.7; 1.5]; % X values of triangle vertices
vy = [8.3; 6.0; 1.7; 8.3]; % Y values of triangle vertices
x = 1:10; % X pixel center coordinates
y = 1:9; % Y pixel center coordinates
Note that the vertex coordinates are ordered starting at the top left corner of the triangle and proceeding clockwise, repeating the first vertex at the end to close the polygon.
Getting the mask (the easy part):
There is an easy way to compute the dark gray mask if you have the Image Processing Toolbox: use poly2mask:
mask = poly2mask(vx, vy, numel(y), numel(x));
The algorithm this function uses is discussed here. However, if you'd like to use a pure MATLAB approach that requires no special toolboxes, you can use inpolygon instead:
[cx, cy] = meshgrid(x, y); % Generate a grid of x and y values
mask = inpolygon(cx, cy, vx, vy);
In this case, a pixel is included in the mask as long as its center point lies within the polygon. In this particular example these two approaches yield the same resulting mask, but they won't always due to the differences in their criteria for deciding if a pixel is included or not.
Getting the outline coordinates:
It's a little more involved to get the coordinates of the mask outline, ordered appropriately around the perimeter. To accomplish this, we can represent the mask as a series of vertices and triangular facets (using the triangulation function), then compute the free boundary (i.e. edges that are only present on one triangular facet):
% Create raw triangulation data:
[cx, cy] = meshgrid(x, y);
xTri = bsxfun(#plus, [0; 1; 1; 0], cx(mask).');
yTri = bsxfun(#plus, [0; 0; 1; 1], cy(mask).');
V = [xTri(:) yTri(:)];
F = reshape(bsxfun(#plus, [1; 2; 3; 1; 3; 4], 0:4:(4*nnz(mask)-4)), 3, []).';
% Trim triangulation data:
[V, ~, Vindex] = unique(V, 'rows');
V = V-0.5;
F = Vindex(F);
% Create triangulation and find free edge coordinates:
TR = triangulation(F, V);
freeEdges = freeBoundary(TR).';
xOutline = V(freeEdges(1, [1:end 1]), 1); % Ordered edge x coordinates
yOutline = V(freeEdges(1, [1:end 1]), 2); % Ordered edge y coordinates
And we can plot this like so:
imagesc(x, y, mask);
axis equal
set(gca, 'XLim', [min(x)-0.5 max(x)+0.5], ...
'YLim', [min(y)-0.5 max(y)+0.5], ...
'XTick', x, 'YTick', y, 'YDir', 'normal');
colormap([0.9 0.9 0.9; 0.6 0.6 0.6]);
hold on;
plot(xOutline, yOutline, 'b', 'LineWidth', 2);
plot(xOutline(1), yOutline(1), 'go', 'LineWidth', 2);
plot(vx, vy, 'r', 'LineWidth', 2);
The outline coordinates in xOutline and yOutline are ordered starting from the green circle going counter-clockwise around the mask region.
Seems you need any line rasterization algorithm (that gives coordinate of integer grid points approximating line segment).
Consider Bresenham algortihm or DDA one.
If I have the coordinates of the points on the outline of an arbitrary 2D shape, how can I find the coordinates of points composing the outline of a stair step curve, which best represents the original outline, but only use a set of known coordinates (xi, i=1,...,n and yi, i=1,...,m). For example the original triangle is represented by the thick solid blue line. it's different from the matlab stairs function, if my understanding is correct.
matlab code will be nice, but in other language is also ok, algorithm is most important.Thanks.
I'll start by defining a set of sample data based on your plot. Assuming that the pixel centers are aligned at integer values (the convention MATLAB follows) and that the lower left corner is at (0.5, 0.5), here's the data we get:
vx = [1.5; 9.7; 3.7; 1.5]; % X values of triangle vertices
vy = [8.3; 6.0; 1.7; 8.3]; % Y values of triangle vertices
x = 1:10; % X pixel center coordinates
y = 1:9; % Y pixel center coordinates
Note that the vertex coordinates are ordered starting at the top left corner of the triangle and proceeding clockwise, repeating the first vertex at the end to close the polygon.
Getting the mask (the easy part):
There is an easy way to compute the dark gray mask if you have the Image Processing Toolbox: use poly2mask:
mask = poly2mask(vx, vy, numel(y), numel(x));
The algorithm this function uses is discussed here. However, if you'd like to use a pure MATLAB approach that requires no special toolboxes, you can use inpolygon instead:
[cx, cy] = meshgrid(x, y); % Generate a grid of x and y values
mask = inpolygon(cx, cy, vx, vy);
In this case, a pixel is included in the mask as long as its center point lies within the polygon. In this particular example these two approaches yield the same resulting mask, but they won't always due to the differences in their criteria for deciding if a pixel is included or not.
Getting the outline coordinates:
It's a little more involved to get the coordinates of the mask outline, ordered appropriately around the perimeter. To accomplish this, we can represent the mask as a series of vertices and triangular facets (using the triangulation function), then compute the free boundary (i.e. edges that are only present on one triangular facet):
% Create raw triangulation data:
[cx, cy] = meshgrid(x, y);
xTri = bsxfun(#plus, [0; 1; 1; 0], cx(mask).');
yTri = bsxfun(#plus, [0; 0; 1; 1], cy(mask).');
V = [xTri(:) yTri(:)];
F = reshape(bsxfun(#plus, [1; 2; 3; 1; 3; 4], 0:4:(4*nnz(mask)-4)), 3, []).';
% Trim triangulation data:
[V, ~, Vindex] = unique(V, 'rows');
V = V-0.5;
F = Vindex(F);
% Create triangulation and find free edge coordinates:
TR = triangulation(F, V);
freeEdges = freeBoundary(TR).';
xOutline = V(freeEdges(1, [1:end 1]), 1); % Ordered edge x coordinates
yOutline = V(freeEdges(1, [1:end 1]), 2); % Ordered edge y coordinates
And we can plot this like so:
imagesc(x, y, mask);
axis equal
set(gca, 'XLim', [min(x)-0.5 max(x)+0.5], ...
'YLim', [min(y)-0.5 max(y)+0.5], ...
'XTick', x, 'YTick', y, 'YDir', 'normal');
colormap([0.9 0.9 0.9; 0.6 0.6 0.6]);
hold on;
plot(xOutline, yOutline, 'b', 'LineWidth', 2);
plot(xOutline(1), yOutline(1), 'go', 'LineWidth', 2);
plot(vx, vy, 'r', 'LineWidth', 2);
The outline coordinates in xOutline and yOutline are ordered starting from the green circle going counter-clockwise around the mask region.
Seems you need any line rasterization algorithm (that gives coordinate of integer grid points approximating line segment).
Consider Bresenham algortihm or DDA one.
This code takes the coordinates of two rectangles and finds their intersection.
def rec_intersection(rect1, rect2)
x_min = [rect1[0][0], rect2[0][1]].max
x_max = [rect1[1][0], rect2[1][1]].min
y_min = [rect1[0][0], rect2[0][1]].max
y_max = [rect1[1][0], rect2[1][1]].min
return nil if ((x_max < x_min) || (y_max < y_min))
return [[x_min, y_min], [x_max, y_max]]
end
rec_intersection([[1, 1], [2, 2]],[[0, 0], [5, 5]])
I don't really understand it. Specifically I would like to know more about exactly what the coordinates mean (I know they are coordinates for the left-bottom and right-top) but can anybody elaborate more? What are they relative to? The size of the rectangle? Or it's placement? How does a rectangle with a bottom-left coordinate of [1,1] differ from one with a bottom-left of [0,0]?
Also I would like to know why in order to find the x_min, the max method is being used (and vice-versa). Any clarification is appreciated.
This is a comment, which I will delete after the OP has seen it. Here's a graph of the two rectangles, where rect1 is contained within rect2.
Earlier, where I referred to [1,1] and [2,2] as the "top-left" and "bottom-right" corners, respectively, of rect1, that should have been the "bottom-left" and "top-right" corners.
Hi I am trying to draw an image.
I have three matrices:
Matrix A: X coordinates
Matrix B: Y coordinates
Matrix C: Image gray scale
X, Y coordinates can be integer, decimal points, or NaN.
If any of the matrix point is NaN, I will not draw that point.
For example:
A = [1, 1; B = [1, 2; C = [1, 2;
2, 2; 1, 2; 3, 4;
NaN,3 ] 4, 4 ] 5, NaN]
I will plot a point with value of C(1) at X(1), Y(1). Value 1 is drawn at (1,1) Value 2 is drawn at (1,2) Value 3 is drawn at (2,1) Value 4 is drawn at (2,2)
However, B(3,1) and C(3,1) are not used because A(3,1) is NaN. Also, A(3,2) and B(3,2) are not used because C(3,2) is NaN.
Any suggestion or help to implement this function?.. I appreciate any comments or suggestion. Thank you.
% filter out the data with NaN's
idx_filter = ~(isnan(A)|isnan(B)|isnan(C));
% create a color map
cmap = gray(256);
% plot using scatter (36 is default size)
scatter(A(idx_filter),B(idx_filter),36,cmap(C(idx_filter),:))
The colours now still all look kinda just black, because you're using just a small part of the whole 1-256 range.
I have the following image on which i have applied bilateral filtering and subtracted it from my original image
Is it possible to outline the glass defect as shown
After apply Hough i got the following result not perfect :/
My matlab code :
im = imread('C:\Users\SUJIT\Desktop\image003.jpg');
im=rgb2gray(im);
h = fspecial('gaussian', size(im), 1.0);
g = imfilter(im, h);
im=im2double(g);
im=imadjust(im);
imgauss = imfilter(im, fspecial('gaussian',[7 7], 6),'conv');
imbi = bilateralfilter(im, [5 5], 3, 3);
imbi= im - imbi;
imshow(imbi,[]); title('Bilateral Filted Image');
I = imcrop(imbi, [30 30 450 350]);
J = imfilter(I, fspecial('gaussian', [17 17], 5), 'symmetric');
BW = edge(J, 'canny');
%# Hough Transform and show matrix
[H T R] = hough(BW);
imshow(imadjust(mat2gray(H)), [], 'XData',T, 'YData',R, ...
'InitialMagnification','fit')
xlabel('\theta (degrees)'), ylabel('\rho')
axis on, axis normal, hold on
colormap(hot), colorbar
%# detect peaks
P = houghpeaks(H, 10);
plot(T(P(:,2)), R(P(:,1)), 'gs', 'LineWidth',2);
%# detect lines and overlay on top of image
lines = houghlines(BW, T, R, P);
figure, imshow(I), hold on
for k = 1:length(lines)
xy = [lines(k).point1; lines(k).point2];
plot(xy(:,1), xy(:,2), 'g.-', 'LineWidth',2);
end
hold off
Please help am i doing something wrong here?
It is a bit hard to give a general answer based on only one image and no other information, but I can give a specific answer based on your sample image.
Assuming that what you want to find is the vertical blurry line in the middle of the image, this my approach. I won't go into specific implementation details, but only an outline on how I would do it.
Find the windows. There are multiple approaches to this. Some ideas are to either find the corners, or to find the rectangular structure itself. The Hough transform is a possible tool.
For each window, check if there are vertical structures in it.