![](https://www.mathworks.com/matlabcentral/answers/uploaded_files/1559489/image.png)
Extract shapes from photos as graphs using MATLAB and express them as functions
3 次查看(过去 30 天)
显示 更早的评论
![](https://www.mathworks.com/matlabcentral/answers/uploaded_files/1557824/image.png)
I would like to extract a function by graphing the outline of the Hindenburg airship.
Here, I would like to define a function that matches the actual size of the Hindenburg.
For example, the length of the Hindenburg airship is 245.3 meters. The length of both endpoints of the function will be 245.3
I even put dots on a picture and expressed it as a graph, but I can't define the function according to the actual scale.
I used this code
data=imread('project_final.png');
imshow(data);
b=drawpolygon('Color','red');
bx=b.Position(:,1);
by=b.Position(:,2);
f=fit(bx,by,'poly4')
3 个评论
Walter Roberson
2023-12-4
Those look to me to likely be catenary and so would need to be fit with hyperbolic functions.
Unfortunately it is mathematically impossible to measure a finite number of points to a finite precision and then through mechanical processing determine what the curve definitely "is". You need to fit against mathematical models of what is reasonable given the physics of the situation.
Kilsu Kim
2023-12-4
Additionally, the shape likely took inspiration from an airfoil. Therefore, finding or designing a similar airfoil shape using a tool like XFOILl or Airfoil Tools could be a practical solution(If you're interested!:))
采纳的回答
DGM
2023-12-4
编辑:DGM
2023-12-4
This isn't an answer to the curve fitting problem, but first things first. Fix the image so you're not trying to fit a curve to a distorted image.
% read the image
A = imread('blimp.png');
A = rgb2gray(A);
% these coordinates are a quadrilateral
% defined by the endpoints of the two projections
boxm = [9 119; 16 334; 715 343; 714 120]; % [x y]
% assert that this is where they're supposed to be
boxf = [9 120; 9 334; 714 334; 714 120]; % [x y]
% adjust the image
TF = fitgeotrans(boxm,boxf,'projective');
outview = imref2d(size(A));
B = imwarp(A,TF,'fillvalues',255,'outputview',outview);
imshow(B,'border','tight')
% these are a polyline describing the vertical shear defect
boxm = [9 120; 529 119; 540 120; 713 120]; % [x y]
boxm = [boxm; boxm+[0 100]]; % control points can't be colinear, so make a cage
% assert that this is where they're supposed to be
boxf = [9 120; 529 120; 540 120; 713 120]; % [x y]
boxf = [boxf; boxf+[0 100]];
% adjust the image again
TF = fitgeotrans(boxm,boxf,'pwl');
B = imwarp(B,TF,'fillvalues',255,'outputview',outview);
imshow(B,'border','tight')
% save the image and transcribe it with something else
imwrite(B,'b_corrected.png')
It's not perfect, but it's a lot better than before.
Normally, I do this sort of transcription via Inkscape
This is only slightly different due to the absence of axes.
1 个评论
DGM
2023-12-4
编辑:DGM
2023-12-4
FWIW, this is what I did.
I transcribed two curves, one for the profile view and one for the plan view. Using the attached SVG:
% using the following FEX tools:
% https://www.mathworks.com/matlabcentral/fileexchange/72225-load-svg-into-your-matlab-code
% filename of manually-fit svg file
fname = 'blimp.svg';
% data range from original image axis labels
% this is where the rectangle is drawn in the SVG
xrange = [0 245.3];
yrange = xrange; % the box is square to preserve data aspect ratio
% spline discretization parameter [0 1]
coarseness = 0.01;
% get plot box geometry
str = fileread(fname);
str = regexp(str,'((?<=<rect)(.*?)(?=\/>))','match');
pbx = regexp(str,'((?<=x=")(.*?)(?="))','match');
pby = regexp(str,'((?<=y=")(.*?)(?="))','match');
pbw = regexp(str,'((?<=width=")(.*?)(?="))','match');
pbh = regexp(str,'((?<=height=")(.*?)(?="))','match');
pbrect = [str2double(pbx{1}{1}) str2double(pby{1}{1}) ...
str2double(pbw{1}{1}) str2double(pbh{1}{1})];
% get coordinates representing the curve
S = loadsvg(fname,coarseness,false);
for k = 1:numel(S) % there are multiple curves
x = S{k}(:,1);
y = S{k}(:,2);
% rescale to fit data range
x = xrange(1) + diff(xrange)*(x-pbrect(1))/pbrect(3);
y = yrange(1) + diff(yrange)*(pbrect(4) - (y-pbrect(2)))/pbrect(4);
% correct for offsets
x = rescale(x,xrange(1),xrange(2)); % assume each curve represents the same length
y = y - min(y); % remove y-offset
% get rid of nonunique points
% this may or may not be needed depending on the shape
% of the curves and how they're to be processed
[x,idx,~] = unique(x,'stable');
y = y(idx);
% shove the prepared data back into S for later
S{k} = [x y];
end
% plot the two curves
for k = 1:numel(S)
x = S{k}(:,1);
y = S{k}(:,2);
plot(x,y); hold on
end
grid on;
xlim(xrange)
%axis equal % if you want to display it with 1:1 data aspect
% let's say that taking the average of the curves is appropriate
xf = linspace(0,245.3,100);
y1 = interp1(S{1}(:,1),S{1}(:,2),xf,'linear','extrap');
y2 = interp1(S{2}(:,1),S{2}(:,2),xf,'linear','extrap');
yf = max((y1 + y2)/2,0); % the average curve
plot(xf,yf)
legend({'sample 1','sample 2','average'})
![](https://www.mathworks.com/matlabcentral/answers/uploaded_files/1559689/image.png)
I have no idea whether the two curves are supposed to differ, or whether the sections are exactly circular. Likewise, I have no idea what an appropriate fit model would be.
更多回答(0 个)
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Interpolation 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!