Verfasst am: 18.12.2012, 09:55
Titel: Flächenberechnung eines Polygons mit polyarea()
Hallo Forum,
ich möchte die Fläche eines Polygons mit polyarea() berechnen. Das Polygon bekommt in einer While Schleife pro Durchlauf zwei Koordinatenpaare dazu. Nach jedem Durchlauf soll die Fläche neu berechnet und geschaut werden ob die Fläche bereits größer ist als ein eingestellter Schwellwert. (Ich möchte das benutzen, um die Fläche zwischen zwei kurvigen Konturlinien in möglichst gleich große Flächenteile aufzuteilen.)
Die Teilflächen sind nicht wirklich gleich groß
Hier mal ein Ausschnitt bei Schleifendurchlauf 60. Jede blaue Linie meint eine Traverse. Die rote Fläche ist ein patch(). Im nächsten Durchlauf werden die X,Y Koordinaten von Start und Endpunkt der nächsten Traverse zu dem Patch hinzugefügt. Und immer so weiter bis der Schwellwert überschritten wird.
Ich habe den Quellcode mal auskommentiert und auch eine lauffähige Version als zip angehängt. Das Programm läuft auch, nur verstehe ich das Verhalten von polyarea (Zeile:5 ab dem Schleifendurchlauf 64 nicht.(conditional breakpoint zeile 72 (i==60), und dann folgende Durchläufe betrachten)
Die Darstellung des Polygons mit patch() zeigt, dass das Polygon wie gewünscht größer wird nur steigt die Fläche des Polygons nicht mehr an. Das Polygon wird um eine senkrechte Linie nach untern verlängert, kann es sein, dass dies zu einem Problem bei der Flächenberechnung führt?
Das ganze Programm ist bis jetzt nur für mich zum testen und in keinem Punkt optimiert oder besonders gut strukturiert. Bitte versteht es als einen Test!
if ~exist('img','var')
%img=imread('B05_1621.tif');
img=ones(5000,6976);
end % Darstellen des (leeren) Bildes imshow(img);
x_all=[];
y_all=[];
% Darstellen aller Traversen die aus der Datei traversen.mat eingelesen % wurden (Traverse meint hier immer eine der mit line(x,y) dargestellten % Linien. Die Linien wurden zwischen zwei (hier nicht mehr sichtbaren) % Konturlinien erzeugt. Die Konturlinien umschließen eine Biologische % Struktur die später Bildanalytisch untersucht werden soll for i=1:size(prof,2)
x=[prof(1,i).startx,prof(1,i).endx];
y=[prof(1,i).starty,prof(1,i).endy];
line(x,y);
x_all=[x_all,x];
y_all=[y_all,y];
end pause % gesamt fläche
hin=[prof(1,:).startx;prof(1,:).starty];
zurueck=[prof(1,:).endx;prof(1,:).endy];
zurueck=fliplr(zurueck);
hin_zurueck=[hin zurueck];
%patch(test(1,:),test(2,:),'r');
%sum_area = gesamtfläche zwischen den Konturlinien
sum_area= polyarea(hin_zurueck(1,:),hin_zurueck(2,:));
% gesamtfläche soll in zB 30 gleichgroße Teile unterteilt werden % part_area= zB 1/30 der Gesamtfläche. Dient als Schwellwert, wenn dieser % Wert überschritten wurde soll ein neuer Patch eröffnet werden
part_area=sum_area/30;
% quick and dirty initialisierung einiger Variablen step=1; % nur für die abwechselnde Färbung der Patches
start_temp=[]; % Vektoren mit den X und Y Koordinaten der Startpunkte der Traversen
end_temp=[]; % Vektoren mit den X und Y Koordinaten der Endpunkte der Traversen
i=1;
% Hauptschleife über alle Traversen die aus der Datei traversen.mat % eingelesen wurden while i<size(prof,2) % das Patch wird in jedem Durchlauf vergrößert (bzw. ein neues um eine % Traverse größers Patch wird erzeugt). Altes kleineres wird deswegen % gelöscht
h = findobj(gca,'Type','patch','Tag','tmp');
delete(h);
% Zusammenbau des Vektors für die Patch Generierung
start_temp=[start_temp;prof(1,i).startx,prof(1,i).starty];
end_temp=[end_temp;prof(1,i).endx,prof(1,i).endy];
end_flip=flipud(end_temp); % einmal flippen, da Patch sonst verdreht
sum_temp=[start_temp;end_flip]; % Vektor mit X,Y von Start und Endpunkten der Traversen % Berechnen der Fläche des aktuell erzeugten Patches
temp_area=polyarea(sum_temp(:,1),sum_temp(:,2));
% Darstellung des Patches
h_patch=patch(sum_temp(:,1),sum_temp(:,2),'r','Marker','o','MarkerFaceColor','y');
% Tag setzen um temp. Patches später wieder löschen zu können set(h_patch,'Tag','tmp');
i=i+1;
%disp(['Summe:' num2str(sum_area)]);
%disp(['Thres:' num2str(part_area)]);
disp(['Loop Ind:' num2str(i)]);
disp(['TempA:' num2str(temp_area)]);
disp('------------------');
% Abfragen ob die Fläche des aktuellen Patches schon größer als der % geplante Schwellwert ist und falls ja Farbe ändern und anderen Tag % setzen if temp_area>part_area
ifmod(step,2)==0 set(h_patch,'FaceColor','b');
else set(h_patch,'FaceColor','g');
end set(h_patch,'Tag','final');
i=i-1;
start_temp=[];
end_temp=[];
step=step+1;
end
Ist hier sichergestellt, dass die Sortierung der Punkte stimmt? Du solltest zunächst eine Seite des Gebildes aufzählen, dann die andere Seite, also beispielsweise "hin rechts" und dann "zurück links". Zum Abschluss des Polygons noch den Anfangsknoten am Ende aufführen.
ja, das sollte so sein, deswegen lasse ich mir das Polygon auch immer wieder ausgeben in der Figure, da ich genau in dem Punkt viele Fehler hatte und das Polygon immer wieder verdreht war.
Aber momentan wird es mir richtig angezeigt, auch alle Eckpunkte werden richtig angezeigt.
Ich baue den gesamten Vektor extra deswegen in den Zeilen davor zusammen.
Code:
% gesamt fläche
hin=[prof(1,:).startx;prof(1,:).starty]; % xy Koordinaten der Hinpunkte
zurueck=[prof(1,:).endx;prof(1,:).endy]; % xy Koordinaten der Zurück Punkte
zurueck=fliplr(zurueck); % dann einmal flippen, damit die Reihenfolge stimmt
hin_zurueck=[hin zurueck]; % und wieder zusammen bauen
%patch(hin_zurueck(1,:),hin_zurueck(2,:),'r'); % zeigt den richtigen Patch, der durch alle hin und zurück Punkte geht
Ich würde in der Schleife das gleiche machen wie hier
Code:
hin=[prof(1,:).startx;prof(1,:).starty]; % xy Koordinaten der Hinpunkte
zurueck=[prof(1,:).endx;prof(1,:).endy]; % xy Koordinaten der Zurück Punkte
zurueck=fliplr(zurueck); % dann einmal flippen, damit die Reihenfolge stimmt
hin_zurueck=[hin zurueck]; % und wieder zusammen bauen
Hi und danke das du schon mal drüber geschaut hast.
Ich habe deine Änderung eingebaut. Es ändert aber leider nichts an der Tatsache, dass die polyarea() Fläche ab einem Loopindex von 64 nicht mehr steigt obwohl das paralell dazu abgebildete patch deutlich größer wird.
Ich spare mir durch deine Idee zwei Variablen, was natürlich schon mal gut ist, aber das Problem besteht leider immer noch.
Da wäre ich jetzt nicht drauf gekommen, obwohl ich kürzlich ein ähnliches Problem hatte. Die internen Operationen in polyarea, wozu auch die Division gehört, führen zu Stellenfehlern. Teilt man zwei uint-Datentypen, fallen die Nachkommastellen weg. Mit einer Konvertierung in double wird das Problem natürlich behoben.
Du kannst Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen. Du kannst Dateien in diesem Forum posten Du kannst Dateien in diesem Forum herunterladen
MATLAB, Simulink, Stateflow, Handle Graphics, Real-Time Workshop, SimBiology, SimHydraulics, SimEvents, and xPC TargetBox are registered trademarks and The MathWorks, the L-shaped membrane logo, and Embedded MATLAB are trademarks of The MathWorks, Inc.