Divide 3d line into segments
3 views (last 30 days)
Show older comments
Hello,
I've got an object in an image which is positioned at an angle. I can draw a line across each side of the object, forming a sheared bounding box for the object.
I need to split the top and bottom lines (the horizontal lines) into a number of parts. For straight lines this would be fairly easy, something like this:
point1 = [664, 10];
point2 = [1556, 10];
length = point2(2) - point1(2);
numberOfSegments = 30;
segmentSize = length / numberOfSegments;
(664 and 1556 are X-axis positions, 10 is the Y-axis position)
This creates 30 segments of 30 pixels wide each. My line represents a 3D-plane in the image though, so the segments should not be the same width as the line planes towards the camera.
Imagine the following points that I've found in my image:
point1 = [644 220];
point2 = [1556 5];
(664 and 1556 are X-axis positions, 220 and 5 are Y-axis positions)
The segments closer to point 1 should be small in width and the width should increase for segments closer to point 2.
How can I calculate the width of each segment on the angled line?
Thanks!
0 Comments
Accepted Answer
DGM
on 12 Oct 2024
Edited: DGM
on 12 Oct 2024
I don't think that what's requested is necessarily the only way to get around the problem, but consider the following image:
%% fit the object to an orthogonal grid
% an object in an image
A = imread('businesscard.jpg');
imshow(A)
You could choose to just correct the image for the perspective distortion. At that point, you don't need to deal with foreshortening anymore. You can easily overlay a regular grid or subdivide the object.
% these are the coordinates of the box corners
% you can get these using getpts() or impixelinfo() or datatips
boxm = [1115 955; 2890 1167; 2898 2221; 821 1918]; % clockwise from NW corner
% assert that this is where they're supposed to be in the output geometry
szo = [384 640]; % business cards are roughly 1:5/3
boxf = [1 1; szo(2) 1; szo(2) szo(1); 1 szo(1)]; % same order as boxm
% transform the image
TF = fitgeotrans(boxm,boxf,'projective');
outview = imref2d(szo);
B = imwarp(A,TF,'fillvalues',255,'outputview',outview);
% now the object can be subdivided easily
imshow(B); hold on
% for example, show a grid on the image
% i'm choosing to scale N to suit the object aspect ratio
% so that the object subdivisions are roughly square
N = [17 10]; % number of points per edge [x y]
x = linspace(1,szo(2),N(1)); % just use output image geometry
y = linspace(1,szo(1),N(2));
[X Y] = meshgrid(x,y);
plot(X,Y,'m.','markersize',20)
Instead, you could try to work in the original image space as requested:
%% fit an orthogonal grid to the object
% an object in an image
A = imread('businesscard.jpg');
% a uniform grid of points
% i'm choosing to scale N to suit the object aspect ratio
% so that the object subdivisions are roughly square
N = [17 10]; % number of points per edge [x y]
x = linspace(0,1,N(1)); % using unit-scale
y = linspace(0,1,N(2));
[X Y] = meshgrid(x,y);
% these are the coordinates of the grid corners
boxm = [0 0; 1 0; 1 1; 0 1]; % same order as boxf
% assert that this is where they're supposed to be in the image geometry
% these are the same points used for boxm in the prior example
boxf = [1115 955; 2890 1167; 2898 2221; 821 1918]; % clockwise from NW corner
% transform the grid
TF = fitgeotrans(boxm,boxf,'projective');
[Xout,Yout] = transformPointsForward(TF,X(:),Y(:));
% show the transformed grid on the image
imshow(A); hold on
plot(Xout,Yout,'m.','markersize',40)
0 Comments
More Answers (0)
See Also
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!