Matlab: Bilderkennung von + und - Würfeln

(English) Dieser Eintrag beschreibt die Identifikation von Plus und Minus auf Würfeln.

Würfel Identifikation:

Mein Bruder hat eine Würfel Roll Maschine gebaut die automatisch würfelt mit zwei Seiten +, eine Seite - und der rest leer und Bilder aufnimmt. Diese Bilder sehen wie die folgenden aus:


 Das Plus ist dabei grün und das Minus ist rot.

Bildbearbeitung:

Zu erst lade ich alle Bilder mit Matlab und schneide sie in eine 200x200 size größe (zweite Zeile). Weiterhin verbesser ich den Kontrast der Bilder durch Erhöhung der RGB-Werte, da diese nur bei 100 von 255 liegen (dritte Zeile). Die einzelnen RGB-Kanäle werden dann aufgeteilt und dadurch ein grüner Kanal rekonsturiert, indem von dem grünen Kanel die hälfte des blauen und roten Kanals (als einfache Matrixsubtraktion) abgezogen wird und demenstprechend für rot. Mit einer Grenze der Double-Werte bei 50 für das grüne Bild (darüber sind die Werte nun 1 und darunter 0) und 20 für das rote Bild wird also ein binäres Bild erstellt (vierte Zeile).
Im nächsten Schritt wird der morphologische Operator imclose und dann imopen verwendet um das Rauschen zu verringern und kleine fehlerhafte Pixel zu löschen. Der Gradient wird darauf angewendet, damit wateshed genutzt werden kann. Hierbei wird jedem zusammenhängenden Gebiet ein Integer zugewiesen was in RGB-Farben konvertiert wird (fünfte Zeile).
Nun wird von diesem Bild der größtezusammenhängende Bereich (ausschließlich Hintergrund) gewählt und dann wieder als binäres Bild dargstellt (Zeile 6). Sind nun mehr als 100 Pixel im grünen Bild 1 das Bild wird als Plus erkannt, sind weniger als 100 Pixel 1 aber mehr als 70 Pixel im roten Bild 1 dann wird es als Minus erkannt und der rest ist dann Leer.
Alles kann nun geplottet werden und in verschiedene Ordner gespeichert werden. Diese Methode hat eine Präzission 100% bei 1000 getesteten Bilder und die benötigte Zeit is bei 460 Sekunden. Dies kann verbessert werden, indem die letzte Dimension aller Matrizen verworfen wird. Das heißt die Matrix in der For-Schleife nur immer ein Bild enthält. Dadurch wird die Zugreifzeit auf die Matrizen umgangen (die für große Matrizen sehr lang ist), weshalb ab 500 Bilder ein großer Unterschied in der Laufzeit ensteht. Bei 1000 Bildern benötigt der Algorithmus nur noch 50 Sekunden.

Das Ergebniss is dann bei 1000 Würfen:
Anzahl Minus: 164; in Prozent: 16.40; Abweichung: 1.60
Anzahl Plus: 337; in Prozent: 33.70; Abweichung: 1.10
Anzahl Leer: 499; in Prozent: 49.90; Abweichung: 0.20

Das heißt die Würfel sind relativ gut!

Quellcode:

clear;
clc;

showgraph = 0;
saveimg = 0;
fold = 'NeuronBilder_SR_02_Blog_3';
tic;
cd('C:\Users\admin\Dropbox\Sparta Kriegspläne\DieImages\SR_02x1000');

if saveimg == 1
    mkdir(fold);
    cd(fold);
    mkdir('Plus');
    mkdir('Minus');
    mkdir('Leer');
end

files = dir('*.jpg');
len = length(files);
len = 800;
s = 1;

q = zeros(len,1);
qp = zeros(len,1);
qm = zeros(len,1);
  
for i = 1:1:len
    name{i}=files(i).name;
    img(:,:,:) = im2double(imread(name{i}));
    imgarea(:,:,:) = img(1:200,61:260,:);
    imgoli = imgarea;
    imgarea = (imgarea-0.1)*2.5;

    imgred(:,:) = imgarea(:,:,1);
    imggreen(:,:) = imgarea(:,:,2);
    imgblue(:,:) = imgarea(:,:,3);

    justred = 1.6*(imgred-0.5*imggreen-0.5*imgblue);
    justgreen = 1.5*(imggreen-0.5*imgred-0.5*imgblue);
    justred(justred>20/255) = 1;
    justred(justred<=20/255) = 0;

    justgreen(justgreen>45/255) = 1;
    justgreen(justgreen<=45/255) = 0;

    openedp = imopen(justgreen,ones(5));
    openedm = imopen(justred,ones(5));
    openedp = imclose(openedp,ones(5));
    openedm = imclose(openedm,ones(5));
  
%clear justred justgreen imggreen imgred imgblue name;
    sz = size(imgarea);
    waters = zeros(200,200);
    water = zeros(200,200);
    water_p = zeros(200,200);
    clearvars L_sort L_sum L_sum_p index L_unique;
%           
    grad(:,:) = imgradient(openedm(:,:),'sobel');
    L(:,:) = watershed(grad(:,:));
  
    grad_p(:,:) = imgradient(openedp(:,:),'sobel');
    L_p(:,:) = watershed(grad_p(:,:));
  
% for minus
    L(L==0) = 1;
    % find largest areas
    L_unique = unique(L(:));
    for j=1:1:length(L_unique)
        L_sum(j) = length(L(L==j));
    end
    [L_sort, index] = sort(L_sum,'descend');
    %main img
    if length(index)>1  
        water(L(:,:) == index(2)) = 1;
    end
    clearvars L_sort L_sum_p index L_unique;
% for plus
    L_p(L_p==0) = 1;
    % find largest areas
    L_unique = unique(L_p(:));
    for j=1:1:length(L_unique)
        L_sum_p(j) = length(L_p(L_p==j));
    end
    [L_sort, index] = sort(L_sum_p,'descend');
  
    %index
    %main img
    if length(index)>1
        water_p(L_p(:,:) == index(2)) = 1;
    end
    %clear index
  
    pl = water_p(:);
    mi = water(:);
    qp = sum(pl(:));
    qm = sum(mi(:));
    if qp>100
        q(i) = 1;
    else
        if qm>70
            q(i) = -1;
        else
            q(i) = 0;
        end
    end
    waters(:,:) = water(:,:)+water_p(:,:);
    rgb(:,:,:) = label2rgb(L(:,:)+L_p(:,:),'jet',[.5 .5 .5]);
    waters = imdilate(waters,ones(3));
  
    if saveimg == 1
        if q(i)==1
            filename = sprintf('C:\\Users\\admin\\Dropbox\\Sparta Kriegspläne\\DieImages\\SR_02x1000\\%s\\Plus\\img_plus%d.jpg',fold, i);
            imwrite(imgoli(:,:,:),filename);
        elseif q(i)==-1
            filename = sprintf('C:\\Users\\admin\\Dropbox\\Sparta Kriegspläne\\DieImages\\SR_02x1000\\%s\\Minus\\img_minus%d.jpg',fold, i);
            imwrite(imgoli(:,:,:),filename);
        else
            filename = sprintf('C:\\Users\\admin\\Dropbox\\Sparta Kriegspläne\\DieImages\\SR_02x1000\\%s\\Leer\\img_leer%d.jpg',fold, i);
            imwrite(imgoli(:,:,:),filename);
        end
    end
  
  
end


amount_plus = numel(q(q==1));
amount_minus = numel(q(q==-1));
amount_empty = numel(q(q==0));

if saveimg == 1
      
    fid = fopen('Ergebnisse.txt','w');
    fprintf(fid,'Anzahl Minus: %d; %4.2f; %4.2f \r\n',amount_minus,pcminus,devminus);
    fprintf(fid,'Anzahl Plus: %d; %4.2f; %4.2f \r\n',amount_plus,pcplus,devplus);
    fprintf(fid,'Anzahl Leer: %d; %4.2f; %4.2f \r\n',amount_empty,pcempty,devempty);
    fclose(fid);
  
end
% showing __________________________________________________________
if showgraph == 1
%imgarea = imgarea*2;
    d=108;

    fig(1) = figure(1);
    clf(1);

    for i=s:1:s+19
        %subplot(6,10,i);imshow(grade(:,:,i));
        subplot(6,10,i-s+1);imshow(imgarea(:,:,:,i+d));title(q(i+d));
        subplot(6,10,i+20-s+1);imshow(openedm(:,:,i+d));
        subplot(6,10,i+40-s+1);imshow(openedp(:,:,i+d));
    end
  
    fig(1) = figure(1);
    clf(1);

    for i=s:1:s+9
        %subplot(6,10,i);imshow(grade(:,:,i));
        subplot(6,10,i+10-s+1);imshow(imgoli(:,:,:,i+d));title(q(i+d));
        subplot(6,10,i+20-s+1);imshow(imgarea(:,:,:,i+d));
        subplot(6,10,i-s+1);imshow(img(:,:,:,i+d));
        subplot(6,10,i+30-s+1);imshow(justgreen(:,:,i+d)+justred(:,:,i+d));
        subplot(6,10,i+40-s+1);imshow(rgb(:,:,:,i+d));
        subplot(6,10,i+50-s+1);imshow(waters(:,:,i+d),[]);
        %subplot(6,10,i+50-s+1);imshow(openedp(:,:,i+d)+openedm(:,:,i+d));
    end
end

pcminus = round(100*amount_minus/len,1);
pcplus = round(100*amount_plus/len,1);
pcempty = round(100*amount_empty/len,1);

devminus = abs(1-pcminus*6/100)*100;
devplus = abs(1-pcplus*3/100)*100;
devempty = abs(1-pcempty*2/100)*100;

% saving __________________________________________________________

time_duration = toc

Kommentare

Beliebte Posts aus diesem Blog

Matlab: GUI Interface

Matlab: Polarplot Achsenbeschriftungs- und Skalierfunktion

Matlab: Fehlergeraden