WICHTIG: Der Betrieb von goMatlab.de wird privat finanziert fortgesetzt. - Mehr Infos...

Mein MATLAB Forum - goMatlab.de

Mein MATLAB Forum

 
Gast > Registrieren       Autologin?   

Partner:




Forum
      Option
[Erweitert]
  • Diese Seite per Mail weiterempfehlen
     


Gehe zu:  
Neues Thema eröffnen Neue Antwort erstellen

AVI einlesen, bearbeiten, speichern

 

GtrAngus
Forum-Anfänger

Forum-Anfänger


Beiträge: 19
Anmeldedatum: 11.06.13
Wohnort: Bayreuth
Version: ---
     Beitrag Verfasst am: 11.06.2013, 22:29     Titel: AVI einlesen, bearbeiten, speichern
  Antworten mit Zitat      
Hallo Leute,

ich würde gerne ein Video bearbeiten und anschließend speichern. Am besten wäre es, wenn ich ein neues *.avi File bekommen würde.

Ich hab schon verschiedene Sachen ausprobiert, aber nichts hat funktioniert. Hat mir ein paar Codes aus der documentary "writeVideo" kopiert, aber es geht trotzdem nicht Sad

Zum einen weiß ich nicht was in meinem Fall imageObj ist, bzw. ob ich die Sache überhaupt richtig angehe. Wenn ich für imageObj = 'img1' verwende, kommt die Fehlermeldung:

Undefined function 'writeVideo' for input arguments of type 'double'.

Error in Bildmittelung (line 31)
a = writeVideo(img1,res); % Neues Video



Hier mein bisheriger Code:

Code:
clear all;
close all;

% File-Name
file = 'Series001.avi';

% Eigenschaften des Anfangs-Videos
obj = VideoReader(file);
nFrames = obj.NumberOfFrames;
vidHeight = obj.Height;
vidWidth = obj.Width;
 
mov(1:nFrames) = ...;
struct('cdata', zeros(vidHeight, vidWidth,3,'uint8'),'colormap', []);

% Bildmittelung über alle Frames
for i = 1 : nFrames
    mov(i).cdata = read(obj,i);
    img1 =double(mov(i).cdata);
end
immean = mean(img1,3);

% Neues Video erstellen oder Image-Serie

open('img1');

for i = 1 : nFrames
    mov(i).cdata = read(obj,i); % Altes Video einlesen
    img =double(mov(i).cdata);
    res = img(:,:,1) - immean; % Altes Video minus Mittelwert
    a = writeVideo(img1,res); % Neues Video
end

close(img1);


Wäre cool wenn mir jemand meinen Denkfehler erklären könnte! Smile

Gruß GtrAngus
Private Nachricht senden Benutzer-Profile anzeigen


Harald
Forum-Meister

Forum-Meister


Beiträge: 24.499
Anmeldedatum: 26.03.09
Wohnort: Nähe München
Version: ab 2017b
     Beitrag Verfasst am: 11.06.2013, 22:46     Titel:
  Antworten mit Zitat      
Hallo,

du musst zunächst ein VideoWriter-Objekt erstellen. 'img1' ist ja nur ein String.

Code:
writerObj = VideoWriter('result.avi');
open(writerObj);


Siehe z.B. auch
Code:


Grüße,
Harald
Private Nachricht senden Benutzer-Profile anzeigen
 
GtrAngus
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 19
Anmeldedatum: 11.06.13
Wohnort: Bayreuth
Version: ---
     Beitrag Verfasst am: 11.06.2013, 23:00     Titel:
  Antworten mit Zitat      
Danke für die schnelle Antwort! Smile Das hat mich schon ein Stück weiter gebracht, hier der neue Code-Abschnitt:

Code:
% Neues Video erstellen oder Image-Serie

writerObj = VideoWriter('result.avi');
open(writerObj);

for i = 1 : nFrames
    mov(i).cdata = read(obj,i); % Altes Video einlesen
    img =double(mov(i).cdata);
    res = img(:,:,1) - immean; % Altes Video minus Mittelwert
    writeVideo(writerObj,res); % Neues Video
end

close(writerObj);


Neuer Fehler:
Warning: No video frames were written to this file. The file may be invalid.
> In VideoWriter.VideoWriter>VideoWriter.close at 271
In VideoWriter.VideoWriter>VideoWriter.delete at 220
In Bildmittelung at 1
Error using VideoWriter/writeVideo (line 336)
Frames of type double must be in the range 0 to 1.

Error in Bildmittelung (line 32)
writeVideo(writerObj,img); % Neues Video


Muss ich hier noch zu uint8 konvertieren?? Werde mal ein paar Sachen ausprobieren.
Private Nachricht senden Benutzer-Profile anzeigen
 
Harald
Forum-Meister

Forum-Meister


Beiträge: 24.499
Anmeldedatum: 26.03.09
Wohnort: Nähe München
Version: ab 2017b
     Beitrag Verfasst am: 11.06.2013, 23:27     Titel:
  Antworten mit Zitat      
Hallo,

die Fehlermeldung sagt doch, was das Problem ist:
Zitat:
Frames of type double must be in the range 0 to 1.


Vermutung: wenn du von allem den Mittelwert subtrahierst, werden einige Bildwerte negativ, und das ist ja nicht sehr sinnvoll?

Grüße,
Harald
Private Nachricht senden Benutzer-Profile anzeigen
 
Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 12.06.2013, 15:43     Titel: Re: AVI einlesen, bearbeiten, speichern
  Antworten mit Zitat      
Hallo GtrAngus,

Matlab's Debugger könnte Dir helfen das Problem zu verstehen: Setze einfach einen Breakpoint in oder vor die entsprechende Zeile, dann könntest Du die Werte der fraglichen Variablen direkt untersuchen.

Ich schreibe das aber mit Bedacht im Konjunktiv. Denn "clear all" löscht vorhandene Breakpoints. Leider ist es trotz dieser eigentlich vernichtenden Eigenschaft so häufig im Code, der im Forum gepostet wird, zu finden, dass es mich gruselt. Wer empfiehlt Programmieranfängern Methoden, die das Debuggen systematisch verhindern??

Viele Grüße, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
GtrAngus
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 19
Anmeldedatum: 11.06.13
Wohnort: Bayreuth
Version: ---
     Beitrag Verfasst am: 13.06.2013, 21:10     Titel:
  Antworten mit Zitat      
Das mit dem Video schreiben hab ich jetzt so gelöst:

Code:
% Schreibe Video
writerObj = VideoWriter('result.avi');
open(writerObj);

for i = 1 : nFrames
    writeVideo(writerObj,bck_img); % Neues Video
end

close(writerObj);
 


Die Bearbeitung der Bilder findet weiter oben, seperat statt. Großes Problem waren auch die beiden Zeilen:

Code:
   mov(i).cdata = read(obj,i); % Altes Video einlesen
    img =double(mov(i).cdata);


Da hier das Video immer neu eingelesen wurde, was sehr viel Speicher und somit Zeit verbraucht hat. Die Bilder werden jetzt nur einmal eingelesen und dann im Workspace gespeichert Smile

@ Jan S
Das clear all alle Breakpoints löscht, war mir bislang gar nicht klar. Liegt aber auch daran das ich das sehr selten verwende. Trotzdem Danke für den Hinweis! Smile Ich benutze den Befehl um sicher zu gehen, dass keine Variablen im Speicher hängen wie z.B. alte Bilder als Matrix o.ä. Kann man bestimmt eleganter lösen, aber dafür fehlt mir bislang einfach noch die Erfahrung.
Private Nachricht senden Benutzer-Profile anzeigen
 
GtrAngus
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 19
Anmeldedatum: 11.06.13
Wohnort: Bayreuth
Version: ---
     Beitrag Verfasst am: 13.06.2013, 21:44     Titel:
  Antworten mit Zitat      
Jetzt hab ich allerdings eine neue Frage. Ist eigentlich simple, aber ich versteh es einfach nicht....

Hier ist ein Ausschnitt aus meinem Code:

Code:
if thresh == 1
    % Originalbild
    image(I), title('Originalbild'), colormap('gray');
   
    % Histogramm des Originalbildes    
    [m,y] = hist(I,127);
    a = mean(m,2);
    figure, plot(y,a), title('Mean Histogramm Original');
   
    % Mittelwert, Standardabweichung des Bildes berechnen
    b = mean(I(:))
    c = std(I(:))
   
    % Oberer und unterer Datenbereich der bestehen soll
    Io = I > b+c; % oberer Datenbereich
    Iu = I < b-c; % unterer Datenbereich
    logbin = Io + Iu; % Ist logical binary file
   
    % Erzeugt neues Bild in Abhängigkeit ob logbin 1 oder 0
    for i = 1 : vidHeight
        for j = 1 : vidWidth
            if logbin(i,j) == 1
                imgst(i,j) = I(i,j);
            else
                imgcrap(i,j) = I(i,j);
            end
        end
    end
   
    % Bild nach Bearbeitung
    image(imgst), title('Bearbeitet'),colormap('gray');
   
    % Histogramm des bearbeiteten Bildes    imgst
    [n,x] = hist(imgst,127);
    a = mean(n,2);
    figure, plot(x,a), title('Mean Histogramm Bearbeitet');
   
    % Histogramm des bearbeiteten Bildes   crap
    [n,x] = hist(imgcrap,127);
    a = mean(n,2);
    figure, plot(x,a), title('Mean Histogramm Crap');    
   
    % Oberfläche des Originalbildes
    figure, surf(double(I( 1 : 8 : end, 1 : 8 : end))), zlim([0 255]);
    set( gca, 'ydir', 'reverse' ),title('Background Original');      

    % Oberfläche des bearbeiteten Bildes
    figure, surf(double(imgst( 1 : 8 : end, 1 : 8 : end))),zlim([0 255]);
    set( gca, 'ydir', 'reverse' ),title('Background Beschnitten');
end


Hab einige Stellen kommentiert, aber hier nochmal was ich mache:

Video einlesen, das 1. Bild speichern (später werden alle Bilder bearbeitet) und ein Histogramm erstellen.

Dann wird das Bild bearbeitet und ausgegeben. Es wird ein neues Histogramm erstellt. Ganz am Ende erstelle ich noch einen Oberflächen-Plot, um zu schauen ob das Bild z.B. ungleichmäßig belichtet wurde.

crap ist das Negativ zu imgst.

Jetzt das Problem
Obwohl der Code für alle Histogramme gleich ist, wird mir kein Histogramm für das Original angezeigt. Bei den Oberflächen-Plots und den anderen beiden Histogrammen jedoch klappt es... Woran genau liegt das??? Hab das Problem schon öfters gehabt. Oftmals reicht es schon wenn ich ein anderes Bild einlesen lasse, dass doch etwas angezeigt wird.
Private Nachricht senden Benutzer-Profile anzeigen
 
Harald
Forum-Meister

Forum-Meister


Beiträge: 24.499
Anmeldedatum: 26.03.09
Wohnort: Nähe München
Version: ab 2017b
     Beitrag Verfasst am: 13.06.2013, 22:21     Titel:
  Antworten mit Zitat      
Hallo,

ich kann das so nur schwer nachvollziehen.
Hast du das mal im Debugging-Modus Zeile für Zeile versucht? Gibt es Warnungen im Command Window?

Vor allem: wenn es nicht für alle Bilder passiert, wäre ein Bild hilfreich, bei dem es passiert, damit man das reproduzieren kann.

Grüße,
Harald
Private Nachricht senden Benutzer-Profile anzeigen
 
GtrAngus
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 19
Anmeldedatum: 11.06.13
Wohnort: Bayreuth
Version: ---
     Beitrag Verfasst am: 13.06.2013, 22:54     Titel:
  Antworten mit Zitat      
Hier nochmal der gesamte Code, soweit meiner Meinung nach notwendig:

Code:
clear all;
close all;

thresh = 1;
weiter = 0;

% File-Name
file = 'Series005.avi';

% Eigenschaften des Videos
obj = VideoReader(file);
nFrames = obj.NumberOfFrames;
vidHeight = obj.Height;
vidWidth = obj.Width;
mov(1:nFrames) = ...;
struct('cdata', zeros(vidHeight, vidWidth,3,'uint8'),'colormap', []);

imgst = zeros(1040,1392);
imgcrap = zeros(1040,1392);

% Video Frame für Frame in Variable I speichern
for i=1:1
    mov(i).cdata = read(obj,i);
    res = double(mov(i).cdata);
    I(:,:,i) = res(:,:,1);
end

if thresh == 1
    % Originalbild
    image(I), title('Originalbild'), colormap('gray');
   
    % Histogramm des Originalbildes    
    [m,y] = hist(I,127);
    a = mean(m,2);
    figure, plot(y,a), title('Mean Histogramm Original');
   
    % Mittelwert, Standardabweichung des Bildes berechnen
    b = mean(I(:))
    c = std(I(:))

   
    % Oberer und unterer Datenbereich der bestehen soll
    Io = I > b; % oberer Datenbereich
    Iu = I < (b-c); % unterer Datenbereich
    logbin = Io + Iu; % Ist logical binary file
   
    % überschreibt Originalbild, falls
    for i = 1 : vidHeight
        for j = 1 : vidWidth
            if logbin(i,j) == 1
                imgst(i,j) = I(i,j);
            else
                imgcrap(i,j) = I(i,j);
            end
        end
    end
   
    % Bild nach Bearbeitung
    image(imgst), title('Bearbeitet'),colormap('gray');
   
    % Histogramm des bearbeiteten Bildes    imgst
    [n,x] = hist(I,127);
    a = mean(n,2);
    figure, plot(x,a), title('Mean Histogramm Bearbeitet');
   
    % Histogramm des bearbeiteten Bildes   crap
    [n,x] = hist(imgcrap,127);
    a = mean(n,2);
    figure, plot(x,a), title('Mean Histogramm Crap');    
   
    % Oberfläche des Originalbildes
    figure, surf(double(I( 1 : 8 : end, 1 : 8 : end))), zlim([0 255]);
    set( gca, 'ydir', 'reverse' ),title('Background Original');      

    % Oberfläche des bearbeiteten Bildes
    figure, surf(double(imgst( 1 : 8 : end, 1 : 8 : end))),zlim([0 255]);
    set( gca, 'ydir', 'reverse' ),title('Background Beschnitten');
end
 



Hier das 1. Bild aus dem Video:

Bitte den Code selber anpassen. Ist bestimmt nicht schwer, aber jeder hat da so seine eigenen Vorlieben. Ist jetzt jedoch ein JPG !!! Normaler Weise jedoch ein *.tif :



Ich würde den Code-Abschnitt:

Code:
% Eigenschaften des Videos


löschen und dafür schreiben:

Code:
I = imread('filename');


Habs nicht ausprobiert, aber sollte eigentlich funktionieren!
Private Nachricht senden Benutzer-Profile anzeigen
 
Harald
Forum-Meister

Forum-Meister


Beiträge: 24.499
Anmeldedatum: 26.03.09
Wohnort: Nähe München
Version: ab 2017b
     Beitrag Verfasst am: 13.06.2013, 23:13     Titel:
  Antworten mit Zitat      
Hallo,

ich habe
Code:
I = imread('test.jpg');

ausprobiert
--> Fehlermeldung
Zitat:
Error using .*
Integers can only be combined with integers of the same class, or scalar doubles.

Error in hist (line 78)
xx = miny + binwidth*(0:x);

Error in improc (line 34)
[m,y] = hist(I,127);


Dann habe ich auch
Code:
I = double(imread('test.jpg'));

getestet
--> Fehlermeldung
Zitat:
Error using image
TrueColor CData contains element out of range 0.0 <= value <= 1.0

Error in improc (line 31)
image(I), title('Originalbild'), colormap('gray');


Grüße,
Harald
Private Nachricht senden Benutzer-Profile anzeigen
 
GtrAngus
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 19
Anmeldedatum: 11.06.13
Wohnort: Bayreuth
Version: ---
     Beitrag Verfasst am: 13.06.2013, 23:22     Titel:
  Antworten mit Zitat      
Könnte das daran liegen das es sich hierbei um ein Bild mit nur 256 Farben handelt? Also anstelle von "double" "uint8" verwenden?

Also bei mir geht es mit:

Code:
I = double(imread(file));
vidHeight = 1040;
vidWidth = 1392;


Aber ich verwende wie gesagt ein Tiff-File. Deshalb hier nochmal das Bild als TIFF:

Private Nachricht senden Benutzer-Profile anzeigen
 
GtrAngus
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 19
Anmeldedatum: 11.06.13
Wohnort: Bayreuth
Version: ---
     Beitrag Verfasst am: 14.06.2013, 00:17     Titel:
  Antworten mit Zitat      
Ok, hab jetzt mal einen Breakpoint gesetzt Wink

So wie es aussieht, überschreibt mir

Code:
   % Bild nach Bearbeitung
    image(imgst), title('Bearbeitet'),colormap('gray');


einfach das Histogramm. Was kann ich daran ändern??
Private Nachricht senden Benutzer-Profile anzeigen
 
Harald
Forum-Meister

Forum-Meister


Beiträge: 24.499
Anmeldedatum: 26.03.09
Wohnort: Nähe München
Version: ab 2017b
     Beitrag Verfasst am: 14.06.2013, 08:46     Titel:
  Antworten mit Zitat      
Hallo,

Zitat:
Was kann ich daran ändern??

Die Frage ist, wie du das haben willst. Du könntest z.B. einen figure-Befehl davorsetzen, wie du es ja auch bei diversen anderen Grafik-Befehlen gemacht hast.

Mich verwundert allerdings, dass dieses Verhalten nur bei bestimmten Bildern auftritt.

Grüße,
Harald
Private Nachricht senden Benutzer-Profile anzeigen
 
Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 17.06.2013, 00:13     Titel:
  Antworten mit Zitat      
Hallo GtrAngus,

Nur eine Seiten-Bemerkung:
Zitat:
Ich benutze den Befehl um sicher zu gehen, dass keine Variablen im Speicher hängen

Dann ist ein "clear" oder "clear variables" freundlicher und resourcen-schonender.

Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
GtrAngus
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 19
Anmeldedatum: 11.06.13
Wohnort: Bayreuth
Version: ---
     Beitrag Verfasst am: 17.06.2013, 20:01     Titel:
  Antworten mit Zitat      
@ Harald
Danke! Daran lag der Fehler! Hätte womöglich nie in dieser Zeile nach dem Verursacher gesucht! Smile

@ Jan S
Und wieder was neues gelernt Smile Werd ich gleich mal einbauen.
Private Nachricht senden Benutzer-Profile anzeigen
 
Neues Thema eröffnen Neue Antwort erstellen



Einstellungen und Berechtigungen
Beiträge der letzten Zeit anzeigen:

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
.





 Impressum  | Nutzungsbedingungen  | Datenschutz | FAQ | goMatlab RSS Button RSS

Hosted by:


Copyright © 2007 - 2025 goMatlab.de | Dies ist keine offizielle Website der Firma The Mathworks

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.