Matlab: Image Processing: + and - identification on dices
(German) This post describes the segmentation of images of dice with plus, minus and nothing on it
Here one can see that the + is in green and the - in red.
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!
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
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: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
Kommentar veröffentlichen