Automatische Folienextraktion

Aus II-Wiki
Zur Navigation springen Zur Suche springen
Das originale Foto wie es von der Kamera aufgenommen wurde
Das Script hat die Folie gefunden und markiert
Das Ergebnis er automatischen Korrektur

Entstehung

Die Vorlesungsfolien für die Vorlesung Grundlagen der Bildverarbeitung und Mustererkennung wahren nur im Copy Shop in schlechter Qualität und zu überteuerten Preise erhältlich. Das führte dazu das wir uns entschieden die Folien während der Vorlesung mit Hilfe eine Digital Kamera mitzuschneiden. Schnell stellte sich dann aber heraus das die Korrektur der Folien (ausschneiden und perspektivisch Korrigieren) eine mühsame und eintönige Arbeit ist. Schnell kam der Gedanke das sich das auch irgendwie automatisieren lassen müsste. Es dauerte dann aber noch eine ganze Weile bis dann das Matlab-Skript welches unten zu finden ist fertig war.

Benutzung des Scriptes

Das Matlabscript ist einfach in die Datei correct_image.m zu kopieren und im Verzeichnis mit den zu korrigierenden Folien abzulegen. Anschließend muss man Matlab starten und in das entsprechende Verzeichnis wechseln. Ist dies geschehen wird das Script einfach mit "correct_image" aufgerufen. Daraufhin ließt das Script die Fotos von der Festplatte ein und versucht die Folien zu extrahieren. Während der automatischen Verarbeitung wird zu erst das Bild angezeigt welches gerade verarbeitet wird. Anschließend blendet Matlab die gefundene Folie ein mit dem ermittelten Folieneckpunkten. Sollte das Script eine ungereimtheit bei den Eckpunkten entdecken so wird der Benutzer aufgefordert die Eckpunkte mit Hand zu setzen. (Das Fenster hat keinen OK Button ... einfach die Eckpunkte hinziehen und dann aufs Kreuz oben rechts klicken). Zum Schluss blendet Matlab die extrahierte Folie ein. Alle korrigierten Folien werden mit einem "p" vor dem Dateinamen abgespeichert. Auf diese weiße wird verhindert das die Originalfolien überschrieben werden.

Sollte das Ergebnis nicht "zufriedenstellend" sein so kann ein automatischer Histogrammausgleich, vor der Bearbeitung mit dem Script, das Ergebnis deutlich verbessern.

Das Script


close all;
clear all;
img=regexp((ls('*.jpg')), '[\s]+', 'split');
images=size(img);
for image=1:images(2)-1
    
I=imread(char(img(:,image)));
imshow(I);
drawnow;
hold on;

I2=rgb2gray(I);
I2=im2bw(I2); %Create Black White Image from grayscale
I2=imfill(I2,'holes'); %Fill all holes in the image
boundaries = bwboundaries(I2); %find all bundarys
tmp = size(boundaries);
bound=[0 0];
for i=1:tmp(1,1)
    tmp2=size(boundaries{i});
    if(tmp2(1,1)>bound(1,1))
        bound(1,1)=tmp2(1,1);
        bound(1,2)=i;
    end
end

b = boundaries{bound(1,2)}; %take the largest boundary (thats the foile)

plot(b(:,2),b(:,1),'g','LineWidth',3);

s=size(b); %Caluculate the center of the folie
mx = sum(b(:,1))/s(1);
my = sum(b(:,2))/s(1);

plot(my,mx,'+r','LineWidth',3);

edges = zeros(4,3); % 1 = x, 2= y, 3 = dist

for i = 1:s(1)
   if b(i,1)>=mx && b(i,2)>=my
       quad=1;
   elseif b(i,1)>=mx && b(i,2)<my 
       quad=2;
   elseif b(i,1)<mx && b(i,2)>=my
       quad=3;
   elseif b(i,1)<mx && b(i,2)<my 
       quad=4;
   end
   dist =(b(i,1)-mx)^2 + (b(i,2)-my)^2; 
   if dist>edges(quad,3)
      edges(quad,3) = dist;
      edges(quad,1) = b(i,1);
      edges(quad,2) = b(i,2);    
   end
end

plot(edges(1,2),edges(1,1),'+b','LineWidth',3);
plot(edges(2,2),edges(2,1),'+b','LineWidth',3);
plot(edges(3,2),edges(3,1),'+b','LineWidth',3);
plot(edges(4,2),edges(4,1),'+b','LineWidth',3);
drawnow;
for i = 1:4
    input_points(i,2) = edges(i,1);
    input_points(i,1) = edges(i,2);
end

%input_points(5,2) = mx;
%input_points(5,1) = my;
imsize = size(I);

base_points(1,1) = imsize(2);
base_points(1,2) = imsize(1);
base_points(2,1) = 1;
base_points(2,2) = imsize(1);
base_points(3,1) = imsize(2);
base_points(3,2) = 1;
base_points(4,1) = 1;
base_points(4,2) = 1;
%base_points(5,1) = imsize(2)/2;
%base_points(5,2) = imsize(1)/2;
%[input_points, base_points]=cpselect(I, I, input_points, base_points,'wait',true);

if(((edges(1,2)-edges(2,2))^2+(edges(1,1)-edges(2,1))^2)<500^2 ||((edges(1,2)-edges(3,2))^2+(edges(1,1)-edges(3,1))^2)<500^2 || ((edges(1,2)-edges(4,2))^2+(edges(1,1)-edges(4,1))^2)<500^2 )
  [input_points, base_points]=cpselect(I, I, input_points, base_points,'wait',true);
end


TFORM = cp2tform( input_points,base_points, 'projective');
B = imtransform(I,TFORM,'XData',[1 imsize(2)],'YData',[1 imsize(1)]);
hold off;
%figure;
imshow(B);
drawnow;

imwrite(B,char(strcat('p',img(:,image))),'jpg','Quality',50);
end