Beliebte Posts:

Donnerstag, 5. Januar 2017

Matlab: Einfaches neuronales Netz

Einfache Methode für ein neuronales Netz

(English) Nowadays neuronal nets are very often used. One don't have to write an algorithm to detect things like crosses and lines but you have to give your neuronal net many images which are wrong and right, let the net learn a while and it have learned how to differ between a cross and a lines. In this post I very easyly implemented a neuronal net and an optimizer in Matlab to detect in a 7x7 field crosses like this (the generate this go to the source code below or to look at the whole program):

With 100 of this images I learned my neuronal net within 1 second to differ it to 100% right.

Neuronal Net

First a short introduction how this neuronal net is working. My net needs 3 layers with neurons on it. For a 7x7 image the first layer is a nx49 (n = 25, first column then row) layer. If one multipies the vector on the layer one get again a vector of the size nx1. With the second layer mxn and the same multiplication one gets mx1 vector. Last but not least multiply it with the last layer, a 1xm, to get an output value. This output value has to be a number between 0 and 1.
T´hat's why I set t he value of the vectors in between the steps to 1 if it is greater or to 0 if it is smaller. In the following code you see this implementation. n_layer_1,n_layer_2 and len are just the size for which I took 25.
First define these 3 random layers. The  function neuronal net needs the input_img and the 3 layers. As described above I calculated the vectors in between and last but not least one gets the output value. In the matrix multiplications are factors of 2/sz(2) and so on that the values are around 0.5, so not too small and not too big.

neuronal_layer_1 = rand(n_layer_1,len);
neuronal_layer_2 = rand(n_layer_2,n_layer_1);
neuronal_layer_3 = rand(1,n_layer_2);


%function neuronal net
function [output_value] = neuronal_net_2(input_img, neuronal_layer_1, neuronal_layer_2, neuronal_layer_3)

sz = size(neuronal_layer_1);
sz_2 = length(neuronal_layer_3);

neuronal_layer_gen_1 = 2/sz(2).*neuronal_layer_1*input_img(:);
neuronal_layer_gen_1(neuronal_layer_gen_1<0) = 0;
neuronal_layer_gen_1(neuronal_layer_gen_1>1) = 1;

neuronal_layer_gen_2 = 2/sz(1).*neuronal_layer_2*neuronal_layer_gen_1(:);
neuronal_layer_gen_2(neuronal_layer_gen_1<0) = 0;
neuronal_layer_gen_2(neuronal_layer_gen_1>1) = 1;

neuronal_layer_gen_3 = 2/sz_2.*neuronal_layer_3*neuronal_layer_gen_2;
neuronal_layer_gen_3(neuronal_layer_gen_3<0) = 0;
neuronal_layer_gen_3(neuronal_layer_gen_3>1) = 1;

output_value = neuronal_layer_gen_3;
end


 Optimization

 The point is now to optimize the the neurons in the layers to get a neuronal net that can differ the signs.
There are 2 methodes. The one is to calculate the mean output value of every image and change 1 neuron to optimize it (which I won't show you here) and the second is to optimize for an amount of neurons the output value for one image after another. That's why it's good to randomly mix the the images.
The function optimizer is based on the gradient methode. The value of 1 neuron is changed a bit and the derivative is calculated. Then this derivative is added to the value of the neuron with a weighting factor.
The optimizer function needs the 3 neuron layers as an input then the images with a value which say that it is wrong or right (true). Optional parameters are the number of edit neurons per image (edit_neuron) and the max value of a neuron (max_value).

function [final_layer_1, final_layer_2, final_layer_3] = optimizer_neuronal_grad(neuronal_layer_1,neuronal_layer_2, neuronal_layer_3,image,true,edit_neuron,max_value)

That is how the function is defined.
The function consists of a for loop over all images. Then a random neuron of one of the layers is taken and the output value is calculated. Now there is a while loop with the conditions that the amount of runs are less than 10 (to prevent a to slow convergence), output value must be lower than 0.8 or the maximal value of a neuron is smaller than the input parameter max_value. In this loop all the time a random neuron of the 3 layers is taken and the output value calculated. Then the gradient is calculated and the new neuron value estimated. This, untill the conditions are not any longer fulfilled.

This was the whole magic of the neuronal net. It is very simple and I show you a few dependcies of the input parameters. For higher edit_neuron value the net has a higher accuracy. If it is more than 10 it's totally fine. If the number of taken neurons per image is more than 100 it achieves nearly 100% accuracy. You can see it in this plots where the accuracy over the edit_neuron is depict and the needed time of the edit_neuron is represented:

For the first values (edit_neuron<100) I average over 100 neuronal net learnings with different layers and images and then with 20 and for the high values just 5.



Source Code:

% ______________________ produce images ________________________ %
 clear;
clc;

for test=1:1:1
%generate images (+ and -)
pixel = 7;
image_number = 100;
for i=1:1:image_number
    tf = round(rand);
    image(:,:,i) = zeros(pixel);
    if tf == 1
        xi = round(rand*(pixel-3)) + 2;
        yi = round(rand*(pixel-3)) + 2;
        image(xi,yi,i) = 1;
        image(xi-1,yi,i) = 1;
        image(xi+1,yi,i) = 1;
        image(xi,yi-1,i) = 1;
        image(xi,yi+1,i) = 1;
        image_true(i) = 1;
    else
        xi = round(rand*(pixel-1)) + 1;
        yi = round(rand*(pixel-3)) + 2;
        image(xi,yi,i) = 1;
        image(xi,yi-1,i) = 1;
        image(xi,yi+1,i) = 1;  
        image_true(i) = 0;
    end
end


% plot images
fig(1) = figure(1);
clf(1);

for i=1:1:12
    subplot(4,3,i);hold on;imshow(image(:,:,i));
    if image_true(i) == 1
        title('true'); else
        title('false'); end
end  


tic;

% ______________________ learning process ________________________ %
  

%neuronal learning
sz = size(image(:,:,:));

len = sz(1)*sz(2);
n_layer_1 = 25;
n_layer_2 = 25;


  
neuronal_layer_1 = rand(n_layer_1,len);
neuronal_layer_2 = rand(n_layer_2,n_layer_1);
neuronal_layer_3 = rand(1,n_layer_2);


%[neuronal_layer_1, neuronal_layer_2, neuronal_layer_3] = optimizer_neuronal_2(neuronal_layer_1,neuronal_layer_2,neuronal_layer_3,image,image_true);
[neuronal_layer_1, neuronal_layer_2, neuronal_layer_3] = optimizer_neuronal_grad(...
    neuronal_layer_1,neuronal_layer_2,neuronal_layer_3,...
    image,image_true,200,10);

%calculate output of all images
jv = 0;kv = 0;
a = [];
a2 = [];
for i=1:1:sz(3)
    if image_true(i) == 1
        jv = jv + 1;
        a(jv) = neuronal_net_2(image(:,:,i), neuronal_layer_1, neuronal_layer_2, neuronal_layer_3);
    else
        kv = kv + 1;
        a2(kv) = neuronal_net_2(image(:,:,i), neuronal_layer_1, neuronal_layer_2, neuronal_layer_3);
    end
end

%calculate accuracy
dev=(abs((1.-sum(a))/(image_number))+abs(sum(a2)/image_number))/2;

bounder = (mean(a(:))+mean(a2(:))/image_number
sum_right_1 = numel(a(a>=bounder));
sum_right_2 = numel(a2(a2<bounder));
right(test) = sum_right_1+sum_right_2;

needed_time(test) = toc;
time_duration = toc

end
procent = sum(right)/numel(right)
time_mean = sum(needed_time)/numel(needed_time)

%___________________________ functions ______________________ %


%function neuronal net
function [output_value] = neuronal_net_2(input_img, neuronal_layer_1, neuronal_layer_2, neuronal_layer_3)

sz = size(neuronal_layer_1);
sz_2 = length(neuronal_layer_3);

neuronal_layer_gen_1 = 2/sz(2).*neuronal_layer_1*input_img(:);
neuronal_layer_gen_1(neuronal_layer_gen_1<0) = 0;
neuronal_layer_gen_1(neuronal_layer_gen_1>1) = 1;

neuronal_layer_gen_2 = 2/sz(1).*neuronal_layer_2*neuronal_layer_gen_1(:);
neuronal_layer_gen_2(neuronal_layer_gen_1<0) = 0;
neuronal_layer_gen_2(neuronal_layer_gen_1>1) = 1;

neuronal_layer_gen_3 = 2/sz_2.*neuronal_layer_3*neuronal_layer_gen_2;
neuronal_layer_gen_3(neuronal_layer_gen_3<0) = 0;
neuronal_layer_gen_3(neuronal_layer_gen_3>1) = 1;

output_value = neuronal_layer_gen_3;
end

%_____________________________________________________________%


function [final_layer_1, final_layer_2, final_layer_3] = optimizer_neuronal_grad(neuronal_layer_1,neuronal_layer_2,neuronal_layer_3,image,true,edit_neuron,max_value)
if nargin < 6
    edit_neuron = 100;
    if nargin <7
        max_value = 10;
    end
end

weigth = 1;
image_number = size(image);

for i=1:1:image_number(3)
    counter = 0;
    sz_ly_1 = size(neuronal_layer_1);
    sz_ly_2 = size(neuronal_layer_2);
    sz_ly_3 = size(neuronal_layer_3);
    while counter < edit_neuron
        take_layer = round(rand*2+1);
        output_new = 0;
        output_value = abs(neuronal_net_2(image(:,:,i),neuronal_layer_1,neuronal_layer_2,neuronal_layer_3)+(true(i)-1));
        time = 0;
        grad = 1;
     
        while time < 10 && output_new<0.8  && abs(grad)<max_value
      
        switch take_layer
            case 1
                take_neuron = [ round(rand*(sz_ly_1(1)-1)+1) round(rand*(sz_ly_1(2)-1)+1)];
                old_v = neuronal_layer_1(take_neuron(1), take_neuron(2));
                neuronal_layer_1(take_neuron(1), take_neuron(2)) = grad;
            case 2
                take_neuron = [ round(rand*(sz_ly_2(1)-1)+1) round(rand*(sz_ly_2(2)-1)+1)];
                old_v = neuronal_layer_2(take_neuron(1), take_neuron(2));
                neuronal_layer_2(take_neuron(1), take_neuron(2)) = grad;
            case 3
                take_neuron = [ round(rand*(sz_ly_3(1)-1)+1) round(rand*(sz_ly_3(2)-1)+1)];
                old_v = neuronal_layer_3(take_neuron(1), take_neuron(2));
                neuronal_layer_3(take_neuron(1), take_neuron(2)) = grad;
        end

        output_new = abs(neuronal_net_2(image(:,:,i),neuronal_layer_1,neuronal_layer_2,neuronal_layer_3)+(true(i)-1));  
        grad = grad +(output_new-output_value)/(grad-old_v)*weigth;
        output_value = output_new;

        time = time +1;
        end
        counter = counter + 1;
    end
end
final_layer_1 = neuronal_layer_1;
final_layer_2 = neuronal_layer_2;
final_layer_3 = neuronal_layer_3;
end

Dienstag, 13. Dezember 2016

Matlab: Segmentierung Wachstum (Segmentation Growing)

Segmentierung Wachstum (Segmentation Growing)

(English) Diese Post ist über ein Verfahren um Objekte aus BIldern zu segmentieren. Dafür wird eine Region gewählt (seed) und mit einem Gewichtungsfaktor, der von der Standartabweichung und der Durchschnittswert der Region und dem Faktor f abhängt, gewählt. Wenn Pixel, die unmittelbar um das seed liegen innerhalb der Grenzen sind, wird dieser dem seed hinzugefügt. Dies wird so lange fortgezetzt, bis kein Wert mehr dem seed hinzugefügt wird. Dann ist das Objekt somit segmentiert.

function [region, area, seed, sx1, sx2, sy1, sy2] = Segmentation_Growing(img,sx1,sx2,sy1,sy2,f):

Diese Funktion benötigt ein Bild als input. Wird sonst nichts als input angegeben kann mit 2 Markern der Bereich festgelegt werden, in dem der seed ist. Andernfalls wird mit sx1, sy1 die obere linke Ecke und mit sx2, sy2 die untere rechte Ecke definiert. Wird mit den Markern gearbeitet, kann als zweiter input f angegeben werden. Diese Variable beschreibt die Gewichtung und kann Werte größer gleich Null annehmen.
Dies ist in der unteren Abbildung für f=1 (blau), f=1.5 (gelb) und f=2 (grün) gezeigt. Das rote Rechteck beschreibt den seed.
Die Augabe der Funktion ist region, welches das segmentierte Objekt ausgibt. Die Variable area gibt für den segmentierten Bereich eine 1 und für den Rest eine 0 zurück zur leichteren Darstellung. Mit seed wird der seed zurückgegeben, der mit den Markern ausgewählt wurde.

In unterer Abbildung sind für 3 verschiedene Regionen die Ergebnisse für 3 verschiedene Werte von f dargestellt. Das Bild unten rechts zeigt das Auswahlfenster zur Definition des seeds mit dem Marker.


Hier kann die Funktion auf Matlab heruntergeladen werden, bzw. weiter unten ebenfalls angeschaut werden:

Quellcode:

function [region, area, seed, sx1, sx2, sy1, sy2] = Segmentation_Growing(img,sx1,sx2,sy1,sy2,f)
%img is the image which is segmentated
%sx1 and sy1 are the values of the upper left corner and
%sx2 and sy2 are the values of the lower right corner
%f can vary between 1 and 2 and is the weigthing factor
%region is the output of the segmentated region
%if area is in region it's one otherwise it's 0
%seed is the start area

%definition of f if not already defined
if nargin < 6
    f = 1.5;
end
if nargin == 2
    f = sx1;
end

% initialize the the region of interest by to cursors
if nargin < 3
    fig(1) = figure(1);
    clf(1);
    imshow(img);
    dcm_obj = datacursormode(fig(1));
    set(dcm_obj,'DisplayStyle','datatip','SnapToDataVertex','off','Enable','on')
    disp('Click for left upper corner of region of interest')
    pause
    pos1 = getCursorInfo(dcm_obj);
    pos = pos1.Position;
    sx1 = pos(2);
    sy1 = pos(1);
    disp('Click for right lower corner of region of interest')
    pause
    pos2 = getCursorInfo(dcm_obj);
    pos = pos2.Position;
    sx2 = pos(2);
    sy2 = pos(1);
    close(fig(1));
end

%generate the seed;
seed = img(sx1:sx2, sy1:sy2);
n = size(img);
% all non segmented regions are infinity
region = ones(n)*inf;
region(sx1:sx2, sy1:sy2) = img(sx1:sx2, sy1:sy2);

region2 = ones(n);
% end condition if region in 2 following steps are equal
tf = isequal(region2,region);
q = double(tf);
while q < 1
    %calculate the mean and standard deviation of all non-inf elements
    rv = region(:);
    vec = rv(rv~=inf);
    m = mean(vec);
    s = std(vec);
    %find all elements in region and sum over them
    [i1,j1,v1] = find(region~=inf);
    for r=1:1:numel(i1)
        i = i1(r);
        j = j1(r);
        %sum over all neighboors
        for k=-1:1:1
            for l=-1:1:1
                if i+k >= n(1) || j+l >= n(2) || i+k <= 0 || j+l <= 0
                    continue
                end
                %include all outside particles which fullfill condition
                if region(i+k,j+l) ~= inf
             
                else
                    if img(i+k,j+l) > m-f*s && img(i+k,j+l) <m+f*s
                        region(i+k,j+l) = img(i+k,j+l);
                    end
                end
            end
        end
    end
    % ending condition
    tf = isequal(region2,region);
    q = double(tf);
    region2 = region;
end
% define the area which is segmented as 1, otherwise 0
area = region;
area(region~=inf) = 1;
area(area~=1) = 0;


end


Quellcode Benutzung:

 clear;
clc;

img = imread('onion.png');
img = im2double(img);
img = rgb2gray(img);
%a)

[region,area,seed,sx1,sx2,sy1,sy2] = Segmentation_Growing(img,1);
[region2,area2] = Segmentation_Growing(img,sx1,sx2,sy1,sy2,1.5);
[region3,area3] = Segmentation_Growing(img,sx1,sx2,sy1,sy2,2);

n = size(region);
% use my function and plot everything
fig(1) = figure(1);
clf(1);
subplot(2,2,1);hold on;imshow(img);title('original');
subplot(2,2,2);hold on;imshow(region3);title('f = 2.0');
subplot(2,2,3);hold on;imshow(seed);title('seed');
subplot(2,2,4);hold on;title('All together');
imshow(img);
green = cat(3, zeros(n), ones(n), zeros(n));
h = imshow(green);set(h, 'AlphaData', area3);
yellow = cat(3, 0.8*ones(n), 0.8*ones(n), zeros(n));
h2 = imshow(yellow);set(h2, 'AlphaData', area2);
blue = cat(3, zeros(n), zeros(n), ones(n));
h3 = imshow(blue);set(h3, 'AlphaData', area);
plot([sy1 sy2 sy2 sy1 sy1],[sx1 sx1 sx2 sx2 sx1],'r');

Matlab: Dijkstra Methode - große Nachbarschaft

Die Dijkstra Methode

(English) In diesem Post wird die Dijkstra Methode aus dem vorherigen Post nochmal aufgearbeitet, sodass diese eine größere Nachbarschaft nach Wegen durchsucht und somit bei mehreren möglichen Pfäden eine präziesere Lösung findet.
Die wird in folgendem Bild zu dme vorherigen Post verglichen:

Hier kann der Code bei MathWorks heruntergeladen werden.

Quellcode Dijkstra:

function [path, prev, unvis, distance, start, target] = Dijkstra_Methode(Matrix, start, target)
%Matrix is the incoming image
%start is the start point in a vector [a,b] where a is the column and b the
%row
%target is the end point similare to start
%path is the matrix with ones excepted at the position of the path where it is 0
%prev are also the previous visited pixels where the algorithm took the
%wrong way
%unvis are all unvisited pixels
%distance is the distance or weight of the pixels


%open the image and you can choose with the cursor the start
%and end point if you don't give the function these values
if nargin == 1
    fig(1) = figure(1);
    clf(1);
    imshow(Matrix);
    dcm_obj = datacursormode(fig(1));
    set(dcm_obj,'DisplayStyle','datatip','SnapToDataVertex','off','Enable','on')
    disp('Click for start point')
    pause
    pos1 = getCursorInfo(dcm_obj);
    pos = pos1.Position;
    sx1 = pos(2);
    sy1 = pos(1);
    start = [sx1 sy1];
    disp('Click for end point')
    pause
    pos2 = getCursorInfo(dcm_obj);
    pos = pos2.Position;
    sx2 = pos(2);
    sy2 = pos(1);
    target = [sx2 sy2];
end

%calculate amount of nodes
n = size(Matrix);

vis = zeros(n);
unvis = ones(n); %set all unvisited to 1
distance = ones(n).*inf; %set all distances to inf
prev = zeros(n);%previous node
prev1 = zeros(n);%previous node
prev2 = zeros(n);%previous node
Q = zeros(n);
for i=1:1:n(1)
    for j=1:1:n(2)
        Q(i,j) = (j-1)*n(1)+i;
    end
end
%strt = (start(1)-1)*n(1)+start(2);
%trgt = (target(1)-1)*n(1)+target(2);
u = start;

distance(u(1),u(2)) = 0;%startdistance is 0

while max(Q) ~= 0
    test = inf;
    for i = 1:1:n(1)
        for j = 1:1:n(2)
            if Q(i,j)~=0 && distance(i,j)<test
                test = distance(i,j);
                u = [i j];
            end
        end
    end
    %if i is in Q
        Q(u(1),u(2)) = 0;
    %end
    vis(u) = 1;
    %if etime(clock,starttime) > inf %safety time stop
        %break
    %end
    for i=1:1:3
        for j=1:1:3
            if(i==2 && j ==2)
                continue
            end
            %v=u-2+i+sz*(j-2);
            vx = u(1)-2+i;
            vy = u(2)-2+j;
            v = [vx vy];
            if vx <= 0 || vy <= 0 || vx >= n(1) || vy >= n(2)
                continue
            end
            if Q(vx,vy) == 0
                continue
            end
            cost = distance(u(1),u(2))+localedgewidth(Matrix,u,v);
            if (cost<distance(vx,vy))
                distance(vx,vy)=cost;
                prev(vx,vy)=(u(1)-1)*n(2)+u(2);
                prev1(vx,vy) = u(1);
                prev2(vx,vy) = u(2);
            end
        end
    end
    unvis(u(1),u(2))=0;
    if (u(1) == target(1) && u(2) == target(2))
        break
    end
end
distance(distance==inf) = 0;
distance = distance./255;
path=zeros(n);
path(u) = 1;
%u = target;
%backtrack from end to start to find best sequence
while u ~= start
    v = u;
    u(1) = prev1(v(1),v(2));
    u(2) = prev2(v(1),v(2));
    path(u(1),u(2)) = 1;
end

end

function [weight] = localedgewidth(G,p,q)
    maxG=max(G(:));
    minG=min(G(:));
    %d=sqrt(sum((p-q).^2));
    d = [sqrt(2) 1 sqrt(2); 1 0 1; sqrt(2) 1 sqrt(2)];
    i = 2+(q(1)-p(1));
    j = 2+(q(2)-p(2));
    weight=(maxG-G(q(1),q(2)))/(maxG-minG) *d(i,j)/sqrt(2);
end

Mittwoch, 7. Dezember 2016

Matlab: Dijkstra Methode - kürzestes Weg entlang des Gradienten (kleine Nachbarschaft)

Die Dijkstra Methode

(English) In diesem Post zeige ich wie mit Matlab am Rand von Objekten oder Bildern der Pfad gefunden werden kann. Hierfür benutzt ich die Dijkstra Methode. Ich nehme als Input ein BIld von Matlab, führe es in ein Gradientenbild über mit [G,Gdir] = imgradient(img,'sobel'); und benutze meine Funktion Dijkstra(G,p,q):
Diese ist benötigt ein Bild in double Format G, einen Startpunkt p bei dem der erste Wert der Zeilenwert und der zweite der Spaltenwert ist und das vorgegebene Ziel q dem entsprechend.
Die Methode funktioniert so, dass sie alle Distanzen auf unendlich setzt und nur den Startpunkt auf 0. Alle unbesichteten Pixel haben den Wert 1. Der Algorithmus geht so lange, bis das Ziel kein unbesichteter Pixel mehr ist. Er summiert über alle Nachbarpixel und berechnet immer das Gewicht bzw. die Distanz mit function [weight] = localedgewidth(G,p,q) wobei der Wert vom Nachbarpixel von dem Maximum der Bilder abgezogen wird, dies durch die Differenz von maximalen und minimalen Wert des Bildes geteilt und mit der Distanz multipliziert. Ist das Gewicht kleiner dem Abstand wird die Distanz überschrieben und der vorherige besuchte Pixel gespeichert. Sobald der aktuelle Wert kleiner dem Wert davor ist, wird beim nächsten Pixel das Selbe wiederholt.
Um den Pfad zu rekonstruieren wird solange der Pfad mit Null gleich gesetzt bis man wieder am Startpunkt ist.
Dann kann die Distanz, der Pfad, die unbesichteten Pixel und die vorher besichteten Pixel ausgegeben werden.
Hier ein kleines Beispiel, welches weiter unten im Quellcode aufgeführt ist.

Hier kann der Code bei MathWorks heruntergeladen werden.

Quellcode Dijkstra:

function [path, prev, unvis, distance] = Dijkstra(Matrix, start, target)
%Matrix is the incoming image
%start is the start point in a vector [a,b] where a is the column and b the
%row
%target is the end point similare to start
%path is the matrix with ones excepted at the position of the path where it is 0
%prev are also the previous visited pixels where the algorithm took the
%wrong way
%unvis are all unvisited pixels
%distance is the distance or weight of the pixels

%calculate amount of nodes

    n = size(Matrix);

    unvis = ones(n); %set all unvisited to 1

    distance = ones(n).*inf; %set all distances to inf
    prev = zeros(n);%previous node

    u = start;

    distance(start) = 0;%start distance is 0

    while (unvis(target(1),target(2))==1)

        test = inf;
        for i=1:1:3%sum over the neighborhood pixels
            for j=1:1:3
                if(i~=2 | j ~=2)%exclude the pixel u in the middle
                    vx = u(1)-2+i;%generate the neighborhood pixels (3x3)
                    vy = u(2)-2+j;
                    v = [vx vy];
                    if (unvis(vx,vy)==1)%if actual neighbor is unvisited
                        cost = localedgewidth(Matrix,u,v);%calculate the weight
                        if (cost<distance(vx,vy))
                            distance(vx,vy)=cost;
                            prev(vx,vy)=u(1)*n(2)+u(2);%set previous node
                            if (cost<test)
                                next=[vx vy]; 
                                test=cost;
                            end
                        end
                    end
                end
            end
        end 
        unvis(u(1),u(2))=0;
        u=next;
    end
    path=ones(n);
    u = target;
    %backtrack from end to start to find best sequence
    while u ~= start
        previous=prev(u(1),u(2));
        k=floor(previous/n(2));
        l=previous-k*n(2);
        path(k,l)=0;%generate path
        u=[k,l];
    end

end


function [weight] = localedgewidth(G,p,q)

% aclculate the local edge width between neighborhood pixels
    maxG=max(G(:));
    minG=min(G(:));
    d=sqrt(sum((p-q).^2));
    weight=(maxG-G(q(1),q(2)))/(maxG-minG)*d/sqrt(2);
end

 

Quellcode Anwendung:

 clear;
clc;

img = imread('pout.tif');
img = im2double(img);
%a)
[G,Gdir] = imgradient(img,'sobel');
n = size(G);
p = [120 165];
q = [274 205];

[path, prev, unvis, distance] = Dijkstra(G, p, q);
% use my function and plot everything
fig(1) = figure(1);
clf(1);
subplot(2,3,1);hold on;imshow(img);title('original');
subplot(2,3,2);hold on;imshow(G);title('gradient');
subplot(2,3,3);hold on;imshow(G);plot(165,120,'r.','markersize',12);
plot(205,274,'b.','markersize',12);title('Start, Target, Path');
for i=1:1:n(1)
    for j=1:1:n(2)
        if path(i,j) == 0
            plot(j,i,'g.','markersize',1);
        end
    end
end
subplot(2,3,4);hold on;imshow(distance);title('distance');
subplot(2,3,5);hold on;imshow(unvis);title('visited pixels');
subplot(2,3,6);hold on;imshow(mat2gray(prev));title('previous point')

Sonntag, 13. November 2016

Matlab: GUI Interface

Erstellen eines GUI interfaces

(English) In diesem Beitrag zeige ich wie man mit Matlab ganz einfach ein GUI Interface mit Buttons etc. erstellt und ein Programm daraus schreibt.
Hierfür muss zuerst in Matlab in die Konsule "guide" eingegeben werden, dass sich ein Fester öffnet. Hier kann man jetzt entweder schon erstellt Interfaces öffnen oder ein neues erstellen.


In einem neu erstellten Interface kann ganz einfach mit den entsprechenden Buttons und anderen Objekten eine Oberfläche erstellt werden. Dies kann man speichern und ausführen woraufhin ein Matlab Code erstellt wird.
Für die Programmierung ist wichtig, dass hierbei jedem Objekt ein "Tag" zugeordnet wird und benannt wird. Dies kann man mit dem "Inspector" bearbeiten, indem einfach auf ein Objekt doppelt geklickt wird. Hier können auch noch weitere Einstellungen wie Design oder "Value" oder "Name" angegeben werden:
Hier kann nun mit dem grünen Pfeil des Editors der Code erstellt werden und die einzelnen Funktionen definiert werden.

Programmieren des GUI interfaces

Der Button kann nun programmiert werden, indem  in dem Quellcode unter "function pushbutton1_Callback(hObject, eventdata, handles)" der Code eingegeben wird. In meinem Fall zeichne ich eine Spirale in "axes1" in Abhängigkeit des Wertes des Textfeldes daneben (zwischen 0 und 3 Pi). Hierfür wird der Wert von "Slider" verwendet um die Reichweite von "x" zu anzugeben. Mit "global" kann man die Variable zu einer globalen Variable machen, wobei darauf zu achten ist, wenn sie in einem anderen Abschnitt benutzt wird muss immer erst "global x" hinu´zugefügt werden.

function pushbutton1_Callback(hObject, eventdata, handles)
global x;
xneu = 1080*get(handles.slider1,'Value')
x = [0:0.1:xneu/180*pi];


Für das Zeichnen wird erst die "axis" des Graph "axes1" ausgewählt:

axis(handles.axes1);

und dann geplottet:

plot(sin(x).*x,cos(x).*x,'parent',handles.axes1);
guidata(hObject,handles);

als nächstes wird der Wert der "Checkbox" eingelesen mit "get(handles...)"

check = get(handles.checkbox1,'Value');if check == 1
    axis(handles.axes2);
    plot(x,cos(x).*x,'parent',handles.axes2);
    guidata(hObject,handles);
end


Falls die Checkbox aktiviert ist, wird in "axes2" ebenfalls eine Funktion geplottet.
Für den "Slider" und die "Editbox" wird jeweils das "hObject", der Wert, mit "set" auf das andere übertragen, damit die beiden immer den gleichen Wert anzeigen.

function slider1_Callback(hObject, eventdata, handles)

slider = num2str( round(get(hObject,'Value')*1080,2) );
set(handles.edit1,'String', slider);


...

function edit1_Callback(hObject, eventdata, handles)

edit = round(str2num( get(hObject,'String') ),2);
set(handles.slider1,'Value',edit/(1080));


Hilfreich ist bei dem "Slider", der "Checkbox" und der "Editbox" jeweils wieder den Button aufzurufen, damit automatisch neu geplottet wird:

pushbutton1_Callback(hObject, eventdata, handles);

All die anderen Objekte der GUI Interface funktionieren änhlich und können immer mit der "Callback" Funktion editiert werden.

Quellcode:

function varargout = GUI(varargin)
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @GUI_OpeningFcn, ...
                   'gui_OutputFcn',  @GUI_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end


function GUI_OpeningFcn(hObject, eventdata, handles, varargin)

handles.output = hObject;

guidata(hObject, handles);


function varargout = GUI_OutputFcn(hObject, eventdata, handles)

varargout{1} = handles.output;


% this is the buttom that shows the figures
function pushbutton1_Callback(hObject, eventdata, handles)
global x;
xneu = 1080*get(handles.slider1,'Value')
x = [0:0.1:xneu/180*pi];

axis(handles.axes1);
plot(sin(x).*x,cos(x).*x,'parent',handles.axes1);
guidata(hObject,handles);

check = get(handles.checkbox1,'Value');
if check == 1
    axis(handles.axes2);
    plot(x,cos(x).*x,'parent',handles.axes2);
    guidata(hObject,handles);
end

% this checkbox is plotting both figures if it is on
function checkbox1_Callback(hObject, eventdata, handles)
pushbutton1_Callback(hObject, eventdata, handles);

% --- Executes on slider movement.
function slider1_Callback(hObject, eventdata, handles)

slider = num2str( round(get(hObject,'Value')*1080,2) );
set(handles.edit1,'String', slider);
pushbutton1_Callback(hObject, eventdata, handles);

function slider1_CreateFcn(hObject, eventdata, handles)

if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor',[.9 .9 .9]);
end



function edit1_Callback(hObject, eventdata, handles)

edit = round(str2num( get(hObject,'String') ),2);
set(handles.slider1,'Value',edit/(1080));
pushbutton1_Callback(hObject, eventdata, handles);

function edit1_CreateFcn(hObject, eventdata, handles)

if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end



Sonntag, 19. Juni 2016

Matlab: alle Dateien aus Ordner darstellen

Öffnen und Darstellen aller Dateien aus einem Ordner

(English) In diesem Post wird beschrieben, wie aus einem Ordner mit Matlab alle Dateien geöffnet und geplottet werden können.
Zuerst werden alle Datein des Formats  *.txt geladen und in files gespeichert.

files = dir('*.csv');

Dann werden alle Dateien in eine Variable gespeichert. Für value = 2 wird beispielsweise nur jede 2. Datei genommen.

for i = 1:1:length(files)/value
    fid3{i}=files(i).name;
end

Diese Dateien sind noch nicht sortiert und können nun sortiert werden. Hierfür muss "natsortfiles" aus Matlab-Exchange heruntergeladen werden:

fid3 = natsortfiles(fid3)
for i = 1:value:length(files) 
    fid = fopen(fid3{i});
    daten = textscan(fid,'%f %f','delimiter',',','headerlines',0');
    q1(:,i/value) = daten(1);
    q2(:,i/value) = daten(2);
end
fclose(fid);

Im "textscan"-Befehl wird mit 'headlines',0 die Anzahl der Zeilen der .txt Datei gelöscht. Die Daten aus Spalte 1 werden in q1 und aus Spalte 2 in q2 gespeichert.

Nun werden die Dateien geöffnet und als Matrix abgespeichert. aus q1 und q2 kann nun noch ein Bereich ausgesucht werden und als x und y gespeichert werden:

%convert cell to matrix
q1=cell2mat(q1);
q2=cell2mat(q2);
%take a defined area
x = q1(650:1150,:);
y = q2(650:1150,:);

Nun können die Daten wie folgt geplottet werden. Dabei wird die Funktion ColSpec genutzt.

fig = figure(1)
hold on;
for i=1:1:length(files)
     h(i)=plot(x(:,i),y(:,i),'Color',ColSpec(length(x),i);
 end

Nun können noh die Daten durchnummeriert werden und dann in der Legende dargestellt werden:

leg = num2str([1:1:length(files)]');
leg = strcat('Datei', leg);
legend(h2,leg,'location','EastOutside');





Matlab: Farbspektrum für Plots

Farbspektren mit Matlab

(English) In diesem Post wird beschrieben, wie mit meiner Funktion für Matlab, ein Farbspektrum erzeugt werden kann, sodass verschiedene Plots alle verschiedene Farben haben.
Hierfür habe ich die Funktion geschrieben (Download):

function [CoolSpec] = ColSpec(a,q,value,start,m,k,inv)

Es kann also mit "a" die Anzahl der verschiedenen Farben im Bereich von rot über gelb zu grün zu blau und zu pink abgegeben werden. Mit dem Wert q wird der q'te Wert des Spektrums zurückgegeben. Mit "value" wird die Weite des Spektrums beschreiben also für Wert größer 1 wird sich die Farbe weniger ändern. "start" gibt den Startwert der Farbe an. Dabei ist rot (start = 0), gelb (start = 0.5), grün(start = 1), hellblau (start = 1.5-2), dunkelblau (start = 2.5) und pink (start = 3) und dann beginnts wieder von vorne. Mit "m" und "k" kann für kleinere Werte als 1 die Helligkeit der Kuven kontinuierlich verringert werden. Mit Werten "inv" kann für ungleich 0 das Spektrum von blau über grün nach rot verwendet werden.

Hier sind vier verschiedene Parameter beispielhaft gezeigt:
ColSpec(21,i,1.2,0,0.8,1,2);



 Mit den Parametern ColSpec(5,:,1,0) bzw. ColSpec(5)


  Mit den Parametern ColSpec(5,:,2,0)
  Mit den Parametern ColSpec(5,:,2,2)

Quellcode:

function [CoolSpec] = ColSpec(a,q,value,start,m,k,inv)
% This Function creates a colorsweep for mulitple plots.
%Therefor "a" defines the amount of different colors
% "q" ist the qth value which is created
% "value" defines how far the sweep should be. So for value = 1
% the sweep goes form red to yellow to green to blue to violett.
%start is the value at which color you want to start.
%start = 0 --> red
%start = 0.5 --> yellow
%start = 1 --> green
%start = 1.5 - 2 --> brigthblue
%start = 2.5 --> darkblue
%start = 3 --> pink
%m and q handels the brigthness of th curve
%inv handels the inverted spectra from blue to red over over

if nargin <7
    inv = 0;
end
if nargin <6
    k=1;
end
if nargin <5
    m=0.9;
end
if nargin <4
    start = 0;
end
if nargin <3
    value=1;
end
alt = a;
a = a*value*1.2;
s = round(start*alt/3);
speed = 6;
for j=s:1:alt+s-1
    i=j;
    if i>a;
        i = round(i-a);
    end
    if i<a/(3)
        r = 2*m-i/a*speed;
        g = i/a*speed;
        b = 0;      
    end
    if i>=a/(3) && i<2*a/(3)
        r = 0;
        g = 2*m-(i-a/(3))/a*speed;
        b = (i-a/(3))/a*speed;      
    end
    if i>=2*a/(3)
        r = (i-2*a/(3))/a*speed;
        g = 0;
        b = 2*m-(i-2*a/(3))/a*speed;      
    end
    %ROT
    if r<0
        r1 = 0;
    elseif r<1
        r1 = r;
    else
        r1=m;
    end
    %GRÜN
    if g<0
        g1 = 0;
    elseif g<1
        g1 = g;
    else
        g1=m;
    end
  
    if b<0
        b1 = 0;
    elseif b<1
        b1 = b;
    else
        b1=m;
    end
  
    if inv == 0
        col = [k*r1 k*g1 k*b1];
    else
        col = [k*b1 k*g1 k*r1];
    end
    CoolSpec{j-s+1,:} = col;
    if i>alt;
        i = 0;
    end
end
if nargin > 1
    CoolSpec = CoolSpec{q,:};
end

Sonntag, 15. Mai 2016

Matlab: optische Aufbauten

Optikenaufbauten mit Matlab

(English) Dieser Post ist dazu da, optische Aufbauten aus Linsen, Spiegeln und anderen Optiken schön mit Matlab darzustellen. Dafür habe ich einige einzelne Funktionen geschrieben mit denen man diese infolgender Form benutzen kann (MATLAB Dateien):
opticlense(x,y,deg,thick,dx,dy,color)
opticbeamsplitter(x,y,deg,thick,dx,dy,color)
opticbikonvex(x,y,deg,thick,dx,dy,color) 
opticdistance(x1,y1,x2,y2,string,len,thick,color)
opticline(x,y,deg,len,thick,color)
opticmirror(x,y,deg,style,thick,color,len)
opticslit(x,y,deg,thick,color,len)

Hierbei gibt x und y die Position des optischen Elements an. So kann nun Maßstabgetreu in Matlab die Linsen positioniert werden. deg gibt den Winkel der Neigung der Optik an und dx, dy bzw. len die Länge in x, y Richtung. color bestimmt die Farbe der Optik und thick die Dicke der Linie. In opticdistance x1,y1 sind die Startwerte und x2,y2 die Endwerte des Abstandes, wobei mit string der Name (z.B. die Entfernung) eingegeben werden kann. In opticmirror stellt style für den Wert 0 einen normalen Spiegel und für 1 einen gestrichelten Spiegel dar. In folgender Abbildung ist der Versuchsaufbau meine Bachelorarbeit zu sehen wie diese mit Matlab in Latex eingebunden wurde:

Quellcode:

clear all;
clc;




fig(1) = figure(1);
clf(1);
hold on;
box off;
axis off;
xLaser = [-11.4 -2.4 -2.4 -11.4 -11.4];
yLaser = [2 2 7.7 7.7 2];
text(-11,6,'Ti:Saphir Laser','interpreter','Latex')
text(-11,4.6,'76 MHz; 800 nm','interpreter','Latex')
text(-11,3.2,'Pulsrate: 150 fs')
plot(xLaser,yLaser,'Color',colors('darkred'),'linewidth',1.15);
xbLaser = [-7 -10.5 -10.5 -7 -7];
ybLaser = [-5.5 -5.5 -2.5 -2.5 -5.5];
text(-10.2,-4,'SHG')
plot(xbLaser,ybLaser,'Color',colors('blue'),'linewidth',1.15);
%xLight = [12.2 9.1 9.1 12.2 12.2];
%yLight = [-12 -12 -10 -10 -12];
opticlense(10,-10,45,1,1.2,1.2,colors('yellow'));
opticlense(10,-10,225,1,1.2,1.2,colors('yellow'));
opticlense(10,-10,135,1,1.2,1.2,colors('yellow'));
opticlense(10,-10,315,1,1.2,1.2,colors('yellow'));
text(8.9,-8.5,'WLC','interpreter','latex')
%plot(xLight,yLight,'Color',colors('yellow'),'linewidth',1.15);

xSpec = [-18 -18 -23 -23 -18 -18];
ySpec = [-19.8 -15 -15 -21 -21 -20.2];
text(-22.7,-15.8,'Monochr.');
plot(xSpec,ySpec,'Color',[0 0 0],'linewidth',1.15);
opticline(-19,-20,45);
xmono = [-20:0.1:-18.5];
xmono2 = [-22.5:0.1:-21];
opticline(-20.5,-20,15,2,1.6);
plot(xmono,-21.5+5*cos((xmono+19.25)*0.35),'Color',[0 0 0]);
plot(xmono2,-21.5+5*cos((xmono2+21.75)*0.35),'Color',[0 0 0]);



xSpecc = [-21.75 -22.25 -22.25 -21.75 -21.75];
ySpecc = [-21 -21 -21.5 -21.5 -21];
plot(xSpecc,ySpecc,'Color',[0 0 0],'linewidth',1.15);

xSpecb = [-23.5 -23 -23 -23.5 -23.5];
ySpecb = [-19.75 -19.75 -20.25 -20.25 -19.75];
plot(xSpecb,ySpecb,'Color',[0 0 0],'linewidth',1.15);

xStreak = [-20 -27 -27 -20 -20];
yStreak = [-24.5 -24.5 -21.5 -21.5 -24.5];
text(-26,-23,'LN$_2$-CCD','interpreter','latex');
plot(xStreak,yStreak,'Color',[0 0 0],'linewidth',1.15);

xspec2 = [-23.5 -28 -28 -23.5 -23.5];
yspec2 = [-19 -19 -21 -21 -19];
text(-27.8,-20,'Streak');
plot(xspec2,yspec2,'Color',[0 0 0],'linewidth',1.15);

xUSB1 = [-12.3 -9.3 -9.3 -12.3 -12.3];
yUSB1 = [-16.5 -16.5 -14.7 -14.7 -16.5];
plot(xUSB1,yUSB1,'Color',[0 0 0],'linewidth',1.15);
plot([-10.6 -11 -11.4 -10.2 -10.6],[-16.5 -16.5 -17 -17 -16.5],'Color',[0 0 0],'linewidth',1.15);
text(-12.4,-15.7,'CCD')

xUSB2 = [7.3 4.3 4.3 7.3 7.3];
yUSB2 = [-17.5 -17.5 -15.7 -15.7 -17.5];
plot([5.6 6 6.4 5.2 5.6],[-17.5 -17.5 -18 -18 -17.5],'Color',[0 0 0],'linewidth',1.15);
plot(xUSB2,yUSB2,'Color',[0 0 0],'linewidth',1.15);
text(4.2,-16.7,'CCD')

%opticdistance(-2.4,3,18.6,3,'105 cm');
%opticdistance(23,-4,23,-6,'10 cm');
%opticdistance(23,-6,23,-19,'115 cm');
%opticdistance(23,-19,23,-20.5,'7.5 cm');
%opticdistance(18.6,-8.5,-5.4,-8.5,'120 cm');
%opticdistance(-12,-22,12,-22,'120 cm');


plot([-2.4 10.6],[3 3],'-','Color',[0.6 0.6 0.6],'linewidth',1.3);
%plot([0 0],[0 -4],'-','Color',[0.6 0.6 0.6],'linewidth',1.3);
%plot([0 10.6],[-4 -4],'-','Color',[0.6 0.6 0.6],'linewidth',1.3);
plot([10.6 10.6],[3 -4],'-','Color',[0.6 0.6 0.6],'linewidth',1.3);
plot([10.6 -5.4],[-4 -4],'-','Color',[0.6 0.6 0.6],'linewidth',1.3);
plot([-5.4 -7],[-4 -4],'-','Color',[0.6 0.6 0.6],'linewidth',1.3);
plot([-10.5 -24],[-4 -4],'-','Color',[0.6 0.6 0.6],'linewidth',1.3);
plot([-24 -24],[-4 -1.2],'-','Color',[0.6 0.6 0.6],'linewidth',1.3);
plot([-24 -5.4],[-1.2 -1.2],'-','Color',[0.6 0.6 0.6],'linewidth',1.3);
plot([-5.4 -5.4],[-1.2 -20],'-','Color',[0.6 0.6 0.6],'linewidth',1.3);

plot([-5.4 9.4],[-10 -10],'-','Color',[0.6 0.6 0.6],'linewidth',1.3);
%plot([-2.4 -2.4],[-9.5 -11],'-','Color',[0.6 0.6 0.6],'linewidth',1.3);
%plot([-2.4 12.2],[-11 -11],'-','Color',[0.6 0.6 0.6],'linewidth',1.3);


plot([-5.4 5],[-20 -20],'-','Color',[0.6 0.6 0.6],'linewidth',1.3);
plot([5 12],[-20 -20],'-','Color',[0.6 0.6 0.6],'linewidth',1.3);
plot([12 12],[-20 -24],'-','Color',[0.6 0.6 0.6],'linewidth',1.3);
plot([12 -12],[-24 -24],'-','Color',[0.6 0.6 0.6],'linewidth',1.3);
plot([-12 -12],[-24 -20],'-','Color',[0.6 0.6 0.6],'linewidth',1.3);
plot([-10.8 -10.8],[-20 -17],'-','Color',[0.6 0.6 0.6],'linewidth',1.3);
plot([-12 -5.4],[-20 -20],'-','Color',[0.6 0.6 0.6],'linewidth',1.3);
plot([-12 -19],[-20 -20],'-','Color',[0.6 0.6 0.6],'linewidth',1.3);
plot([5.8 5.8],[-20 -18],'-','Color',[0.6 0.6 0.6],'linewidth',1.3);
plot([-19 -19.25],[-20 -16.5],'-','Color',[0.6 0.6 0.6],'linewidth',1.3);
plot([-19.25 -20.5],[-16.5 -20],'-','Color',[0.6 0.6 0.6],'linewidth',1.3);
plot([-20.5 -21.75],[-20 -16.5],'-','Color',[0.6 0.6 0.6],'linewidth',1.3);
plot([-21.75 -22],[-16.5 -21],'-','Color',[0.6 0.6 0.6],'linewidth',1.3);

%Bereiche
xba = [-12 -12 -2.1 -2.1 12.7 12.7 -12];
yba = [8.5 1 1 -6.2 -6.2 8.5 8.5];
plot(xba,yba,'--','Color',colors('darkred'),'linewidth',1.15);
text(-14.5,7.5,'\textbf{(a)}','Color',colors('darkred'),'interpreter','latex');

xbb = [-2.8 -2.8 -27.5 -27.5 -2.8];
ybb = [0.2 -6.2 -6.2 0.2 0.2];
plot(xbb,ybb,'--','Color',colors('blue'),'linewidth',1.15);
text(-26.6,1.5,'\textbf{(b)}','Color',colors('blue'),'interpreter','latex');

xbc = [-8 -8 12.7 12.7 -8];
ybc = [-12.1 -7.2 -7.2 -12.1 -12.1];
plot(xbc,ybc,'--','Color',colors('yellow'),'linewidth',1.15);
text(-10.3,-8.5,'\textbf{(c)}','Color',colors('yellow'),'interpreter','latex');

xbd = [-13.3 -13.3 12.7 12.7 -13.3];
ybd = [-12.6 -26 -26 -12.6 -12.6];
plot(xbd,ybd,'--','Color',colors('green'),'linewidth',1.15);
text(-13,-11.5,'\textbf{(d)}','Color',colors('green'),'interpreter','latex');

xbd = [-13.8 -13.8 -28.5 -28.5 -13.8];
ybd = [-14.5 -26 -26 -14.5 -14.5];
plot(xbd,ybd,'--','Color',colors('orange'),'linewidth',1.15);
text(-29,-13.5,'\textbf{(e)}','Color',colors('orange'),'interpreter','latex');

%
%xp = [-0.6 -0.6 -1.8 -1.8 -0.6];
%yp = [0.3 -0.3 -0.3 0.3 0.3];
%plot(xp,yp,'Color',[0 0 0],'linewidth',1.15);
%text(-2.0,1,'Cw')
%opticmirror(0,0,45,0,1.15,colors('darkred'));
%opticmirror(0,-4,45,0,1.15,colors('darkred'));

opticlense(2.5,3,90);
text(1,4.5,'$\text{CL}_1$','interpreter','latex');
opticlense(7.5,3,-90);
text(5.5,4.5,'$\text{CL}_2$','interpreter','latex');
%opticline(9.4,-4,90);
%text(8,-3,'$\nicefrac{\lambda}{2}$','interpreter','latex');
%opticbeamsplitter(10.6,-4,90);
%text(10.3,-3,'Pbs','interpreter','latex');
%opticline(10.6,-5,-45);
%text(10.7,-5,'Gp','interpreter','latex');
opticmirror(10.6,3,45,0,1.15,colors('darkred'));
text(9.9,4,'$\text{DM}_1$','interpreter','latex');
opticmirror(10.6,-4,-45,0,1.15,colors('darkred'));
text(9.9,-5.2,'$\text{DM}_1$','interpreter','latex');
opticlense(9,-4,-90);
text(8.2,-5.5,'$\text{L}_1$','interpreter','latex');
arrow2D(8,-2.5,180,[0 0 0],6,6,1.15);
arrow2D(9.5,-2.5,0,[0 0 0],6,6',1.15);
plot([8 9.5],[-2.5 -2.5],'k','linewidth',1.15);
%opticslit(16.2,-6,90);

%blue light
opticmirror(-5.4,-4,-45,1,1.15,colors('darkred'));
text(-5.6,-5.1,'RM','interpreter','latex');

opticlense(-12.4,-4,90);
text(-12.8,-5.5,'$\text{L}_2$','interpreter','latex');
text(-15,-5.5,'$\text{PH}_1$','interpreter','latex');
opticslit(-13.4,-4,90);

opticlense(-17.4,-4,90);
text(-17.8,-5.5,'$\text{L}_2$','interpreter','latex');
arrow2D(-18,-2.5,180,[0 0 0],6,6,1.15);
arrow2D(-16.5,-2.5,0,[0 0 0],6,6,1.15);
plot([-18 -16.5],[-2.5 -2.5],'k','linewidth',1.15);
text(-19,-5.5,'$\text{I}_1$','interpreter','latex');
opticslit(-18.4,-4,90);

opticmirror(-24,-4,45,0,1.15,colors('blue'));
text(-27,-0.7,'$\text{DM}_2$','interpreter','latex');

opticmirror(-24,-1.2,-45,0,1.15,colors('blue'));
text(-27,-4.5,'$\text{DM}_2$','interpreter','latex');

opticline(-22.4,-1.2,90);
text(-22.2,-2.2,'$\text{F}_1$','interpreter','latex');
opticmirror(-5.4,-1.2,45,0,1.15,colors('blue'));
text(-5.6,-0.8,'$\text{DM}_2$','interpreter','latex');

%white light
text(-5.3,-8.5,'RM','interpreter','latex');
opticmirror(-5.4,-10,-45,1);

opticbeamsplitter(-1.4,-10,90);
text(-2.2,-8.5,'P','interpreter','latex');
opticlense(0.35,-10,-90);
text(-0.5,-8.5,'$\text{L}_5$','interpreter','latex');
opticlense(2.35,-10,90);
text(1.6,-8.5,'$\text{L}_4$','interpreter','latex');
opticlense(5.8,-10,-90);
text(4.5,-8.5,'$\text{L}_3$','interpreter','latex');
arrow2D(2,-11.5,180,[0 0 0],6,6,1.15);
arrow2D(3.5,-11.5,0,[0 0 0],6,6,1.15);
plot([2 3.5],[-11.5 -11.5],'k','linewidth',1.15);

opticslit(6.9,-10,90);
text(6,-8.5,'$\text{PH}_2''$','interpreter','latex');


%all three
%opticline(-5.4,-9.5,0);
%text(-5,-9.5,'Cw','interpreter','latex')
opticline(-5.4,-13.5,0);
text(-5,-13.75,'FW','interpreter','latex');
opticline(-5.4,-14,0);

opticlense(-5.4,-15.4,180);
text(-5,-15.7,'$\text{L}_6$','interpreter','latex');


opticmirror(-5.4,-20,45);
text(-6.8,-20.9,'BS','interpreter','latex');

opticlense(-4.4,-20,90);
text(-5,-18.5,'$\text{L}_3''$','interpreter','latex');
opticlense(-1.4,-20,-90);
text(-2.6,-18.5,'$\text{L}_4''$','interpreter','latex');

%CRYOSTAT

xcry3 = [0.1 0.1 1.1 1.1 0.1];
ycry3 = [-20 -19 -20 -21 -20];
plot(xcry3,ycry3,'Color',[0.6 0.6 0.6],'linewidth',1.15);

xcry = [-0.2 -0.2 0.4 0.4 -0.2];
ycry = [-20 -19.3 -20 -20.7 -20];
plot(xcry,ycry,'k','linewidth',1.15);

plot([1.1 0.1],[-21 -21],'Color',[0.6 0.6 0.6],'linewidth',1.15);
plot([1.1 0.1],[-20 -20],'Color',[0.6 0.6 0.6],'linewidth',1.15);
plot([0.1 -0.9],[-19 -19],'Color',[0.6 0.6 0.6],'linewidth',1.15);

xcry2 = [-0.9 -0.9 0.1 0.1 -0.9];
ycry2 = [-20 -19 -20 -21 -20];
plot(xcry2,ycry2,'Color',[0.6 0.6 0.6],'linewidth',1.15);

xend = [-0.9 -0.9 0.1 0.1 -0.9];
yend = [-20 -19 -20 -21 -20];
plot(xend,yend,'Color',[0.6 0.6 0.6],'linewidth',1.15);
%doublearrwow
arrow2D(-1,-21.5,0,[0 0 0],6,6,1.15);
arrow2D(-2.5,-21.5,180,[0 0 0],6,6,1.15);
plot([-2.5 -1],[-21.5 -21.5],'k','linewidth',1.15);


arrow2D(1,-21.5,180,[0 0 0],6,6,1.15);
arrow2D(2.5,-21.5,0,[0 0 0],6,6,1.15);
plot([2.5 1],[-21.5 -21.5],'k','linewidth',1.15);


arrow2D(0,-21.3,90,[0 0 0],4,6,1.15);
arrow2D(0,-23.2,-90,[0 0 0],4,6,1.15);
plot([0 0],[-21.3 -23.2],'k','linewidth',1.15);

arrow2D(-0.65,-21.55,135,[0 0 0],5,5,1.15);
arrow2D(0.65,-22.95,-45,[0 0 0],5,5',1.15);
plot([-0.65 +0.65],[-21.55 -22.95],'k','linewidth',1.15);

%opticline(0.1,-19,90);
arrow2D(0.3,-18.5,233,[0 0 0],6,6,1.15);
plot([0.3 0.3+0.5*2.5],[-18.5 -18.5+0.707*2.5],'k','linewidth',1.15);
text(-1,-14.8,'sample in');
text(-1,-16,'cryostate');

opticlense(1.6,-20,90);
text(1.0,-18.5,'$\text{L}_4''$','interpreter','latex');


text(2.8,-18.5,'$\text{L}_6''$','interpreter','latex');
opticlense(4,-20,-90);
text(7.7,-18.5,'$\text{L}_7$','interpreter','latex');
opticlense(8.3,-20,90);
opticmirror(5.8,-20,-45,1);
text(5.2,-21.2,'$\text{RM}''$','interpreter','latex');


opticmirror(-12,-20,45,1);
text(-11.0,-21.2,'$\text{RM}''$','interpreter','latex');

text(-13.2,-19,'$\text{RM}$','interpreter','latex');

text(-8.5,-18.5,'$\text{L}_5''$','interpreter','latex');
opticlense(-7.4,-20,-90);

text(-10.3,-18,'$\text{L}_4''''$','interpreter','latex');
opticlense(-10.8,-18.3,0);
text(-13.5,-25,'MM');
opticmirror(-12,-24,+45);
text(9.9,-25,'MM');
opticmirror(12,-24,-45);
text(9.9,-18.8,'MM');
opticmirror(12,-20,+45);
%text(-10.2,-18,'RM','interpreter','latex');
opticmirror(-10.8,-20,45,1);

opticline(-14.8,-20,90);
text(-16.0,-18.5,'$\text{F}_{\text{1,2}}$','interpreter','latex');

text(-17.4,-18.5,'$\text{L}_7''$','interpreter','latex');
opticlense(-16.5,-20,90);
arrow2D(-15.7,-21.5,0,[0 0 0],6,6,1.15);
arrow2D(-17.2,-21.5,180,[0 0 0],6,6,1.15);
plot([-17.2 -15.7],[-21.5 -21.5],'k','linewidth',1.15);

text(-17.4,-18.5,'$\text{L}_7''$','interpreter','latex');

xl = [-28.5 12.7 12.7 -28.5 -28.5];
yl = [-26.8 -26.8 -38.2 -38.2 -26.8];
plot(xl,yl,'k','linewidth',1.15);

text(-27,-28.5,'CL');
text(-24,-28.5,'zylindrische Linse');
text(-27,-30.5,'L');
text(-24,-30.5,'Linse');
text(-27,-32.5,'PH');
text(-24,-32.5,'Lochblende');
text(-27,-34.5,'BS');
text(-24,-34.5,'Strahlteiler');
text(-27,-36.5,'SHG');
text(-24,-36.5,'Frequenzverdoppelung');

text(-13,-28.5,'RM');
text(-10,-28.5,'beweglicher Spiegel');
text(-13,-30.5,'DM');
text(-10,-30.5,'dielektrischer Spiegel');
text(-13,-32.5,'MM');
text(-10,-32.5,'metalischer Spiegel');
text(3,-34.5,'I');
text(6,-34.5,'Irisblende');

text(3,-28.5,'F');
text(6,-28.5,'Filter');
text(3,-30.5,'FW');
text(6,-30.5,'Filterrad');
text(3,-32.5,'P');
text(6,-32.5,'Polarisator');
text(-13,-34.5,'WLC');
text(-10,-34.5,'Weisslichtlampe');

%set(gca, 'linewidth',1.5);
xlim([-29 13]);
%ylim([-23.5 8]);
%set(findall(gcf,'-property','FontSize'),'FontSize',10)
%set(findobj(gcf,'-property','FontSize'),'FontSize',10)

matlab2tikz('compositionneu.tikz', 'height', '\figureheight', 'width', '\figurewidth', 'figurehandle', fig(1));

Montag, 18. April 2016

Theremin: Das elektrische Musikinstrument

Allgemein:

(English) Ein Theremin ist ein elektrisches Musikinstrument, welches durch zwei Schwingkreise geregelt wird, indem an einem Schwingkreis eine Antenne angeschlossen ist. Durch Annäherung der Hand wird die Kapazität geändert und somit auch die Frequenz des Schwingkreises. Schlussendlich hört man die Differenz zwischen den beiden Schwingkreisen.

Aufbau:

Hierfür habe ich folgende Schaltung genommen.

Die Stückliste ist wie folgt:
  • OPV TL071 x2
  • LM386 x1

    Kondensator:
  • 100 nF x2
  • 220 nF x2
  • 47 pF x2
  • 47 nF x1
  • 100 pF x1
  • 10 nF x1
  • Elko 220 u x3

    Widerstand:
  • 100 k  x4
  • 22 k x4
  • 47 k x2
  • 10 x1

    Potentiometer:
  • 100k x1
  • 10k x2

    Sonstiges:
  • Diode 1N4007 1
  • BAT42 2
  • Antenne
  • Lautsprecher
Um das Theremin mit Strom zu versorgen werden entweder 2 9V-Akkus benötigt die in Reihe geschaltet sind oder sonstige 18V Spannungsdifferenz. Mit Netzteilen ist es kritisch, da diese eine richtige Erdung brauchen. Eignen könnten sich dafür diese Stecker, falls man so wie ich zwei 9V-Netzteile hat. Alles aufgebaut sieht dies dann auf dem Steckbrett in etwas so aus (Mit zusätzlichem Lautsprecheranschluss und On-Off Schalter): Wichtig ist, dass kurze Kabel verwendet werden und knapp über dem Steckbrett, da das Theremin sehr stark dadurch beeinflusst wird und sich deswegen die Tonhöhe ändert.
Steckerkonstruktion als +-9V Quelle
Wie zu sehen, habe ich mir eine Antennenhalterung aus dem 3D Drucker gedruckt (STL-Datei). 
Als Antenne eignet sich so ziemlich jeder elektrisch leitender Stoff der fest ist. 
Wird nun noch alles in ein Gehäuse aus dem 3D-Drucker von meinem Bruder eingebracht sieht dies wie folgt aus: 





Hier kann jedes Einzelteil für das Gehäuse gedruckt werden bzw. noch nachgearbeitet werden.

 Anwendung:

Die Anwendung ist einfach: Je näher man mit der Hand zur Antenne geht, desto tiefer wird der Ton (Ausnahmen siehe in "Analyse"). Bewegt man die zweite Hand über das Theremin merkt man, dass sich ebenfalls der Ton ändert, da dieser sehr empfindlich ist. Dies kann zum Beispiel ausgenutzt werden, um die Reichweite der Töne ("Range") zu verändern. Normalerweise kann das Theremin eine Oktave aber wird mit der anderen Hand ebenfalls der Schwingkreis verändert gehen sogar 2-3 Oktaven.
Praktisch ist auch, um die Range zu erhöhen muss man sehr nah an die Antenne ran. Wird diese allerdings berührt wird das Signal unterbrochen. Da der Ton reziprok tiefer wird, sind kleinste Änderungen der Entferung im Nahfeld schon ausschlaggebend. Deswegen kann ein Handschuh genutzt werden, damit die Antenne nie "wirklich" berührt wird. Hier ein kleines Video von "Over the rainbow":
video

 Analyse:

Da ich Physiker bin, hat mich eben interessiert wie die Frequenz mit dem einstellbaren Widerstand zusammenhängt. Dabei ist interessant, dass im Bereich R = 0-10 kOhm der Ton höher wird (Frequenz höher) je höher der Widerstand ist. Ebenfalls gilt hier je weiter man sich von der Antenne wegbewegt, wird der Ton höher (bis zu einem Grenzwert). Dies ist auch in Abbildung 1 zu sehen.
Wird jedoch der einstallbare Widerstand in den Bereich 100 kOhm gestellt, so dreht sich alles um:
Bei steigendem Widerstand sinkt die Tonhöhe und bei Vergrößerung des Abstands zur Antenne wird der Ton tiefer.
Abb:1 Abhängigkeit der Tonhöhe vom einstellbaren WIderstand für verschiedene Töne

In diesem Abbild sind für verschiedene Töne (mit dem Stimmgerät gemessen) die jeweiligen Werte des Widerstands aufgetragen für den Bereich 0-10 kOhm und 90-100 kOhm. Die Fitparameter sind wie folgt:
  • R(f) = 0.002605[Ohm*s]*f+0.02711[Ohm]
  • R(f) = -0.001624[Ohm*s]*f+100.3[Ohm]
 Theoretisch einmal eine Ursprungsgerade mit Steigung 0.002605[Ohm*s] ca. 1/400. Dies zeigt auch, dass bei Verdoppelung des Widerstands sich auch die Frequenz in etwa Verdoppelt.
Dies ist allerdings nicht mehr der Fall für die Messung bei ca. 100 kOhm.



Sonntag, 10. April 2016

Matlab: Matlabskript

Matlabskript

Da ich sehr viel mit Matlab mache, habe ich auch immer nebenher mir alles dokumentiert und die wichtigsten Befehle in eine Latexdatei zusammengefasst. Dieses Skript ist für Anfänger als auch für Fortgeschrittene. Es beginnt mit einfachen Plot- und Fit-Funktionen über 3D-Plots und Fehlergeraden.

Matlabskript

Vorschau:


Matheabitur Skript

Matheabitur-Skript

Da ich dieses Jahr ziemlich viel Mathenachhilfe gegeben habe, habe ich nebenher ein Matheskript geschrieben für das Abitur mit allen relevanten Themen.

Bei irgendwelchen Fehlern oder Unklarheiten im Skript würde ich mich gerne über Komentare und Bemerkungen freuen, da ich doch nicht die Zeit hatte öfters über das Skript zu schauen und es zu perfektionieren.

Ich hoffes es hilft euch beim Lernen und Verstehen!
 
Matheabitur-Skript

Vorschau:


Mittwoch, 30. März 2016

Arduino: Geräuschsensor LM393

Motivation

Da ich mir ein Theremin gebaut habe, wollte ich mir mit dem Arduino-Geräuschsensor LM393 eine Art Mikrofon bauen, bzw. einen Lautstärke regeler.

Anwendung:

Die Anwendung des Sensors ist ziemlich einfach. Man nimmt ein beliebiges Arduino-Board und verbindet vom Sensor VCC mit +5V, GND mit GND und OUT mit A0.


Nun wird einfach der analog Pin A0 mit analogRead(A0) ausgelesen. Der Arduino gibt abhängig von der Lautstärke entweder 26 oder 1023 als Wert an. Es kommt selten vor, dass sich ein Wert dazwischen befindet. Deswegen habe ich immer über einige Werte (500) gemittelt und dann den Durchschnitt bestimmt. Wird nun 10 Sekunden lang immer der Wert ermittelt, kann der Lautstärkeverlauf ziemlich grob bestimmt werden. Dieser ist umso genauer, über je mehr Werte gemittelt wird. Allerdings ist die Zahl der gemittelten Werte und die Werte die man pro Sekunde aufnehmen will, abhängig von der Geschwindigkeit des Computers. 
In folgenden Bildern ist der Lautstärkeverlauf für den Ton c eines Klaviers in Abhängigkeit der Zeit für verschiedene Anzahlen gemittelter Werte geplottet. Dabei ist zu erkennen, dass bei 10 Werten ein willkürlicher Verlauf ensteht, bei 5000 Werten jedoch eine stetige Kurve:


Wie zu sehen ist gibt es erst ab ca 500 Werten pro Mittelung einen Verlauf, der nicht zu große Abweichungen hat. 

Hier der Quellcode:

int audioPin = A0;
int j=1;
int seconds = 0;
int mills = millis();


void setup() {
  Serial.begin(115200);
}

void loop() {
  int soundWave;
  long Sound = 0;
  int range = 1000;
  soundWave = analogRead(audioPin);
  for (int i = 1;i<range;i++){
    soundWave = analogRead(audioPin);
    Sound = Sound + soundWave;
  }
  Serial.print(double(mills-seconds)/1000);
  Serial.print(" ");
  Serial.println(Sound/(range));
  j=j+1;
  mills = millis();
  if ((mills-seconds)>10000){
    while(1==1);
  }
}

Sonntag, 10. Januar 2016

Matlab: Kegel/Pfeil in 3D

Kegel/Pfeil in 3D

(English) Um einen Kegel bzw. ein Pfeil im 3D darzustellen kann die Funktion:

function arrow3D(x,y,z,x2,y2,z2,length,thick,color)

 verwendet werden. Dabei ist "x2,y2,z2" der Endwert der Pfeiles, also die Spitze und "x,y,z" der Anfang des Vektors bzw. des Pfeiles. "length" gibt die Länge des Pfeils an und "thick" die Dicke. Mit "color" kann der Pfeil gefärbt werden. Wie die Funktion angewendet wird, kann im vorherigen Post nachgelesen werden.


Hier der Quellcode:


function arrow3D(x,y,z,x2,y2,z2,length,thick,color)

if nargin<5
    scale = 1;
end
x=-x;
y=-y;
x2=-x2;
y2=-y2;

vector2=[x2;y2;z2];
vector1=[x;y;z];
vector21=[x2-x;y2-y;z2-z];

u1=[x2-x;y2-y;z2-z];
u1=1/norm(u1)*u1;
u2=[1;0;0];
val=u1(1,1);
abstand=u1-val*u2;
if abstand==zeros(3,1)
    u2=[0;1;0];
end;
%Kreuzprodukt
u3(1,1)=u1(2,1)*u2(3,1)-u1(3,1)*u2(2,1);
u3(2,1)=u1(3,1)*u2(1,1)-u1(1,1)*u2(3,1);
u3(3,1)=u1(1,1)*u2(2,1)-u1(2,1)*u2(1,1);
u3=1/norm(u3)*u3;
%
u2(1,1)=u1(2,1)*u3(3,1)-u1(3,1)*u3(2,1);
u2(2,1)=u1(3,1)*u3(1,1)-u1(1,1)*u3(3,1);
u2(3,1)=u1(1,1)*u3(2,1)-u1(2,1)*u3(1,1);
u2=1/norm(u2)*u2;
%orthnormale vektoren
v1=u2;
v2=u3;
step=pi/50;
a = [step:step:2*pi];
er=vector2;
Er=repmat(er,1,numel(a));
zerx=(Er(1,:))';
zery=(Er(2,:))';
zerz=(Er(3,:))';

vectorscale=(1-length)*vector21;
grund=(v1*sin(a)+v2*cos(a))*norm(vector2'-vector1')/3*thick;
VS=repmat(vectorscale+vector1,1,numel(a));
grund=grund+VS;

xspitz=[zerx';grund(1,:)];
yspitz=[zery';grund(2,:)];
zspitz=[zerz';grund(3,:)];

xrep=reshape(xspitz,1,2*numel(a))';
yrep=reshape(yspitz,1,2*numel(a))';
zrep=reshape(zspitz,1,2*numel(a))';

%hold on;
%view(3);
plot3(xrep,yrep,zrep,'Color',color);




Matlab: Punkte und Vektoren in 3D-Plots

Punkte und Vektoren in 3D-Plots

(English) Diese Matlabfunktion ist für das im vorherigen Post dargestellte 3D-Gitter. Dabei kann mit folgender Funktion ein Vektor bzw. ein Punkt im 3D-Plot erstellt werden.

function punkt3D(x1,y1,z1,x2,y2,z2,sign,name,color,dx,dy,dz,true)

Dabei gibt "x1,y1,z1" dem Startpunkt des Vektors und "x2,y2,z2" dem Endpunkt. Dabei kann mit "sign" das Zeichen am Endpunkt bestimmt werden. Mit "name" wird des Punkt benannt und "color färbt die Vektor.
Ist der Name nicht an der richtigen Stelle, kann dieser mit "dx,dy,dz" entsprechend verschoben werden. Für die Variable "true = 1" wird die Projektion des Vektors auf die 3 Ebenen angeschaltet.
Als Beispiel erhält man folgendes Bild mit diesem Quellcode:

grid3D(0,2,0,2,-2,2,4,4,4);
punkt3D(0,0,0,2,2,2,'.','P(2|2|2)',colors('orange'));
punkt3D(0,0,0,1,0.5,1,'arrow','Q(1|0.5|1)',colors('brightblue'),0,0,0.4);
arrow3D(1.5,1.5,0,1.5,1,0,0.4,0.2,'k');
punkt3D(0,0,0,0,1,1,'arrow','R(0|1|1)',colors('darkgreen'),0,0,0.4);

 Hierfür wird jedoch die Funktion arrow3D(...) gebraucht, da für "sign = 'arrow' " wie in dem Schaubild ein Pfeil ans Ende des Vektors gezeichnet wird. Dies kann optional auch einfach im folgenden Quellcode gelöscht werden.

Hier der Quellcode:
function punkt3D(x1,y1,z1,x2,y2,z2,sign,name,color,dx,dy,dz,true)

if nargin<10
    dx=0;
    dy=0;
    dz=0;
end
if nargin<9
    color='black';
end
if nargin>12
    plot3([0 -x2],[-y2 -y2],[z2 z2],'--','Color','[0.8 0.8 0.8');
    plot3([-x2 -x2],[0 -y2],[z2 z2],'--','Color','[0.8 0.8 0.8');
    plot3([-x2 -x2],[-y2 -y2],[0 z2],'--','Color','[0.8 0.8 0.8');
end

if strcmp(sign,'arrow') == 1
    xrange = x2-x1;
    yrange = y2-y1;
    zrange = z2-z1;
    arrow3D(x2-xrange/7,y2-yrange/7,z2-zrange/7,x2,y2,z2,1,1,color);
end
if strcmp(sign,'arrow') == 0
    p2 = plot3(-x2, -y2, z2,sign,'Color',color,'Markersize',7);
end
p1 = plot3([-x1 -x2],[-y1 -y2],[z1 z2]);
p3 = text(-x2-x2/10-dx, -y2-y2/7-dy, z2+z2/10+dz,name);
set([p1 p3],'Color',color);

Matlab: 3D Plot in kartesischem Koordinatensystem

3D Grid/Gitter

(English) In diesem Post stell ich mein 3D-Gitter für Matlab vor. Dieses erzeugt in Abhängigkeit verschiedener Parameter ein Gitter in Matlab. Dieses kann einfach genutzt werden, um Vektoren, Ebenen und Geraden im dreidimensionalen Darzustellen.

function grid3D(x2,x,y2,y,z2,z,amountx,amounty,amountz,arrowtrue);

dabei gibt x2,y2,z2 die Startwerte der Achse und x,y,z die Endwerte der Achse an. Die anderen Variablen sind optional. Dabei gibt amountx, amounty, amountz die Anzahl der Achsenunterteilungen an. Wenn "arrowtrue = 1" ist, dann werden Pfeile an die Achsen gezeichnet. Diese sind jedoch nur für symmetrische Gitter gut zu gebrauchen.

Hier der Quellcode:
 function grid3D(x2,x,y2,y,z2,z,amountx,amounty,amountz,arrowtrue);

if nargin<7
    amountx = 4;
    amounty = 4;
    amountz = 4;
end
if nargin<10
    arrowtrue = 0;
end

xrange = x2-x;
yrange = y2-y;
zrange = z-z2;

zq = 0:1:amountz;
yq = 0:1:amounty;
xq = 0:1:amountx;

hold on;
set(gca,'visible','off')

xv1=x*ones(amountx+1,1)+(xq*xrange/amountx)';
yv1=y*ones(amounty+1,1)+(yq*yrange/amounty)';
zv1=z*ones(amountz+1,1)-(zq*zrange/amountz)';
if (nargin>6)
    view(3);
    %x1x2 Ebene.  
    plot3([-x2 -x],[0 0],[zv1 zv1],'Color',[0.8 0.8 0.8]);
    plot3([0 0],[-y2 -y],[zv1 zv1],'Color',[0.8 0.8 0.8]);
    %x1x3 Ebene.  
    plot3([-xv1 -xv1],[0 0],[z2 z],'Color',[0.8 0.8 0.8]);
    plot3([-xv1 -xv1],[-y2 -y],[0 0],'Color',[0.8 0.8 0.8]);
    %x2x3 Ebene.  
    plot3([0 0],[-yv1 -yv1],[z2 z],'Color',[0.8 0.8 0.8]);
    plot3([-x2 -x],[-yv1 -yv1],[0 0],'Color',[0.8 0.8 0.8]);
end;

%texte
text(-x,-y/10,-z/20,'x_1')
text(-x/20,-y,-z/10,'x_2')
text(-x/10,y/20,z,'x_3')

xv1(sum((xv1==0),2)>0,:)=[];
yv1(sum((yv1==0),2)>0,:)=[];
zv1(sum((zv1==0),2)>0,:)=[];
%Values
text(-xv1,  zeros(numel(xv1),1),  z/12*ones(numel(xv1),1),num2cell(round(xv1*100)/100));
text(zeros(numel(yv1),1),  -yv1, z/15*ones(numel(yv1),1),  num2cell(round(yv1*100)/100));
text(x/15*ones(numel(zv1),1),  y/15*ones(numel(zv1),1),  zv1,num2cell(round(zv1*100)/100));

xrange=-xrange
yrange=-yrange
dx = xrange/15;
dy = yrange/15;
dz = zrange/15;

%arrows
if arrowtrue == 1
    thickx=(yrange+zrange)/(2*xrange);
    thicky=(xrange+zrange)/(2*yrange);
    thickz=(yrange+xrange)/(2*zrange);
    arrow3D(x,0,0,x+dx,0,0,1,1*thickx,'k')
    arrow3D(0,y,0,0,y+dy,0,1,1*thicky,'k')
    arrow3D(0,0,z,0,0,z+dz,1,1*thickz,'k')
end
%axis
view(3);
plot3([-x2 -x],[0 0],[0 0],'k');
plot3([0 0],[-y2 -y],[0 0],'k');
plot3([0 0],[0 0],[z2 z],'k');


xlim([-(x+dx) -x2]);
ylim([-(y+dy) -y2]);
zlim([z2 z+dz]);