Matlab: Image Processing: + and - identification on dices

(German) This post describes the segmentation of images of dice with plus, minus and nothing on it

Dice identification:

My brother has built a dice rolling machine which automatically roll dices with 2/6 +, 1/6 - and 3/6 nothing on it. The images he produces automatically looked like this:


 Here one can see that the + is in green and the - in red.

Image Processing:

First of all I loaded all images into Matlab and have cut them to a 200x200 size (second column). Further on I made a better contrast by multiplying all rgb-values with a factor, because the green plus and red minus had just a value of around 100 of 255 in rgb (third column). Then I splitted the channels in red, green and blue and generated out of this 3 channels on channel only red and only grenn by taken the red channel and subtracting the blue channel and the green channel with the factor 0.5. With a treshold in these images of 50 for green and 20 for red respectively I converted the images to binare images (see forth column in figure).
The next step is to use the morphology first imclose and then imopen to reduce the noise and little white pixels in the image. Then the gradient is used to use the watershed of Matlab. There the binare images is splitted into different areas and every area has a different color (column 5). With this watershed for the red and green image, the biggest area expect the background is taken and then represented in a binare image again. This you can see in column 6. With a constraint that for the green image with more then 100 pixels in white the images counts as green, the red with more than 70 images in red and less than 100 pixels in green is red respectively and the rest is empty.

Then everything can be plotted and saved in different folders seperated in plus, minus and empty.
This methode worked with a precission of 100% for 1000 dices and a needed time of around 460 seconds. If one changes the algorithm that every image is loaded seperately and processed immediately and the matrices has 1 dimension less, the needed time is at 50 seconds.

The result is that the 1000 rolled dices showed:
amount minus: 164; in percent: 16.40; deviation: 1.60
amount plus: 337; in percent: 33.70; deviation: 1.10
amount empty: 499; in percent: 49.90; deviation: 0.20

The dices are relative good!

Source Code:

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: 3D Coordinate System Rotations with Vectors

Matlab: Cone/Arrow in 3D

Matlab: Points and vectors in 3D-plots