Verfasst am: 01.05.2022, 13:47
Titel: Probleme bei Implementierung einer Binarisierung
Hi @all,
ich versuche einen Algorithmus zu einer Binarisierung zu implementieren.
Der besagte Bin.Algo. wird in dem angehängten PDF beschrieben und habe noch das Bsp.Bild von Seite 3 mit angehängt.
Als erstes Lese ich das Bild ein und erzeuge gleich ein Kanten Bild.
Der empfohlene Schwellwert liegt im Paper für den Canny Algo. bei 0.001, jedoch sahen damit meine Ergebnisse nicht aus wie auf S.3 Fig.2 (b) , daher habe ich den Schwellwert auf 3/128 angepasst und habe damit vorerst "ähnliches" Ergebnis erzielt
% Image varFilt function o_img = im_varFilt(i_img, window_size)
I = double(i_img);
%Define the window size
sz = window_size;
mn=floor(sz/2);
%Preallocate the matrix
o_img = zeros(size(I));
%Pad the matrix with zeros
I = padarray(I,[mn mn]);
for i=1:size(I,1)-mn*2 for j=1:size(I,2)-mn*2
tmp = I(i:i+(sz-1),j:j+(sz-1));
mu = mean(tmp(:));
tmp2 = mean(tmp(:).^2);
o_img(i,j)=tmp2 - mu.^2;
end end
Soweit so gut..
Nun sollen aber die nicht geschlossenen Konturen der Schriftzüge geschlossen werden was in Step 4 auf S.2 beschrieben wird.
Jedoch bin ich ratlos wie ich das genau implementieren soll und zwar wird in Step 4.2 ein OR verknüpfung des Grauwert-Kanten-Bilds und des Varianz-Kanten-Bilds erzeugt.
In dem Ergebnisbild sollen nun alle connected Components, die im Varianz-Kanten-Bild eine Kontur berühren, sozusagen in eine Matrix extrahiert werden.
Dazu habe ich mir die Befehlde bwconncomp, bwtraceboundary und bwboundaries angeschaut und damit etwas rumgespielt.
Aber habe keine Ahnung wie ich weiter verfahren soll. In den images der Conected Components sind zwar zusammenhängende Gebiete aber diese haben im geringsten etwas mit dem Schriftzug zu tun. Wie ich diese dann letztlich noch in eine neue Matrix extrahieren soll weiß ich garnicht.
Über Tipps und Tricks würde ich mich sehr freuen.
Danke im Voraus und euch einen schönen Sonntag.
Bis dahin.
EG2_map = zeros(size(test_img));
for i = 1:length(OR_conn_comps) for j = 1:length(OR_conn_comps{i})
EG2_map ( OR_conn_comps{i}(j), OR_conn_comps{i}(j + length(OR_conn_comps{i}))) = uint8(255);
end end
EG1_map = zeros(size(test_img));
for i = 1:length(EG1_conn_comps) for j = 1:length(EG1_conn_comps{i})
EG1_map ( EG1_conn_comps{i}(j), EG1_conn_comps{i}(j + length(EG1_conn_comps{i}))) = uint8(255);
end end
% Setze alle PixelKoordinaten von conn_comps in F1 = 255
F1 = zeros(size(test_img));
for i = 1:length(conn_comps) for j = 1:length(conn_comps{i})
F1(conn_comps{i}(j), conn_comps{i}(j + length(conn_comps{i}))) = 255;
end end
for i=1:size(I,1)-mn*2 for j=1:size(I,2)-mn*2 % initialisiere Tmp mit allen Elementen die unter aktuellen % Maskenpositionen sind !
tmp = I(i:i+(window_size-1),j:j+(window_size-1));
% berechne Mittelwert d. Elemente und Mittelwert d. Quadrate d. Elemente unter d. Maske
mu = mean(tmp(:));
tmp2 = mean(tmp(:).^2);
Je nachdem wieviel zusammenhängende Gebiete in den Teilbildern gefunden werden, brauch die Funktion compCC ihre Zeit. Bei mir manchmal mehr als 30 Minuten.
calc_directional_thresholds.m
Code:
function done_img = calc_directional_thresholds(org_gray_img, boundary_map, window_size)
for i = 1:size(org_gray_img, 2)% i = laufvariable f. Spalten for j = 1:size(org_gray_img, 1)% j = laufvariable f. Zeilen % Spaltenweise über Bild und Grenzen in Zeilen suchen.
cur_pix_val = boundary_map(j, i);
% Wenn: controllVar_copyBound == 1 % d.H.: übernehme alte untere Grenze als neue obere if controllVar_copyBound == 1
pix_koord_hi_bound = last_pix_koord_lo_bound;
controllVar_copyBound = 0;
strike_hi_bound = 1;
end
% Wenn: Pixel == true und strike_le_bound == 0 % d.H.: Zeile N Spalte M -> Grenze gefunden if cur_pix_val == true && strike_hi_bound == 0
pix_koord_hi_bound = [j+1 i+1];
strike_hi_bound = 1;
% Wenn: Pixel == false und strike_le_bound == 1 und % strike_no_bound == 0 % d.H.: Zeile N Spalte M linke Grenze gefunden (mit evtl. % vertikaler Richtung). Ende gefunden elseif cur_pix_val == false && strike_hi_bound == 1 && strike_no_bound == 0
strike_no_bound = 1;
% Wenn: Pixel == true und strike_le_bound == 1 und % strike_no_bound == 1 % d.H.: Zeile N Spalte M rechte Grenze gefunden elseif cur_pix_val == true && strike_hi_bound == 1 && strike_no_bound == 1
pix_koord_lo_bound = [j+1 i+1];
strike_lo_bound = 1;
strike_no_bound = 0;
for j = 1:size(org_gray_img, 1)% j = laufvariable f. Zeilen for i = 1:size(org_gray_img, 2)% i = laufvariable f. Spalten % Zeilenweise über Bild und Grenzen in Zeilen suchen.
cur_pix_val = boundary_map(j, i);
% Wenn: controllVar_copyBound == 1 % d.H.: übernehme alte rechte Grenze als neue linke if controllVar_copyBound == 1
pix_koord_le_bound = last_pix_koord_ri_bound;
controllVar_copyBound = 0;
strike_le_bound = 1;
end
% Wenn: Pixel == true und strike_le_bound == 0 % d.H.: Zeile N Spalte M -> Grenze gefunden if cur_pix_val == true && strike_le_bound == 0
pix_koord_le_bound = [j+1 i+1];
strike_le_bound = 1;
% Wenn: Pixel == false und strike_le_bound == 1 und % strike_no_bound == 0 % d.H.: Zeile N Spalte M linke Grenze gefunden (mit evtl. horizontaler % Richtung). Ende gefunden elseif cur_pix_val == false && strike_le_bound == 1 && strike_no_bound == 0
strike_no_bound = 1;
% Wenn: Pixel == true und strike_le_bound == 1 und % strike_no_bound == 1 % d.H.: Zeile N Spalte M rechte Grenze gefunden elseif cur_pix_val == true && strike_le_bound == 1 && strike_no_bound == 1
pix_koord_ri_bound = [j+1 i+1];
strike_ri_bound = 1;
strike_no_bound = 0;
elseif i == size(org_gray_img, 2) && strike_le_bound == 1
pix_koord_ri_bound = [j+1 i+1];
strike_ri_bound = 1;
strike_no_bound = 0;
end
% Wenn: strike_le_bound == 1 und strike_ri_bound == 1 % d.H.: linke und rechte GrenzKoordinaten gefunden -> starte % Berechnungen und binarisiere Bild Zeilen und zusätzlich Teilweise if strike_le_bound == 1 && strike_ri_bound == 1
Mein Output (F1) habe ich angehängt, schaut aber leider noch nicht ganz wie im PDF aus. Die zwischenergebnisse sehen leider aber auch schon nicht aus wie im PDF.
Bspw. der Output in Zeile 16 / 17 ( Canny-Kanten-Grauwert Bild mit Schwellwert 0.001 )... Im Code ist der Schwellwert zwar auf 0.1, aber das liegt einzig allein daran das ich so bessere Ergebnisse heraus bekomme. Wenn ich den Schwellwert wie im PDF beschrieben auf 0.001 setze, erhalte ich zwar nicht viel mehr Kanten als im PDF, aber das fertig binarisierte Bild F1 wird meines empfindens nach nicht besser.
Einzig allein das Varianzbild sieht ungefähr so aus wie es soll. Aber das Kantenbild des Varianzbildes (boundary map / EG1) entspricht leider nicht ganz dem was ich im PDF sehe.
Ich habe versucht die Input Bilder mit einem 5x5 Gauß-Filter zu glätten und so das Rauschen zu minimieren, aber das hat nicht wirklich was gebracht. Auch andere Masken habe ich versucht oder die Prinzipien der Canny-Kanten-Filterung mehr oder weniger selbst auf die Bilder anzuwenden ohne die edge() - Funktion zu benutzten, was abeer auch kein Mhergewinn war.
Ein weiterer Punkt ist die Funktion compCC. Diese vergleicht zusammenhängende Pixel-Gebiete die von der bwboundaries() Funktion aus den Zeilen 44 und 55 zurückgegeben werden. Allerdings ist es ja so, dass Pixel-Gebiete zusammenhängend sind wenn die Pixel angrenzen und nicht wie in der Funktion compCC, sobald ein Pixel aus beiden Mengen übereinstimmt.
Hat jemand einen Tipp wie ich das prüfen kann ohne in der Funktion compCC weitere for loops zu öfnnen um an die Inhalte der einzelnen Matrizen der Cell-Arrays zugelangen?
Je nach Bild und verwendeten Schwellwerten für die Kanten-Filter sind hier bis zu 10k Komponenten pro Zelle vorhanden, mit Pixel-Gebieten die zwischen bspw. 4 bis 50 Pixel groß sein können. Dadurch wird die compCC Funktion meiner erachtens nach sehr rechenintensiv.
Ich bedanke mich schonmal für alle Anregungen, Hilfestellungen, Tipps und Verbesserungsvorschläge.
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.