% *****************************************************
% **          Digitalni zpracovani obrazu            **
% **         Rozeznavani dopravnich znacek           **
% ** Leos Marsalek (c) 2003 Leos.marsalek@tiscali.cz **
% **  www.goro.pescz.cz/dzo    www.sendme.cz/sklad   **
% *****************************************************

% Mým úkolem bylo nalezení vystraznych dopravnich znacek
% a jejich rozpoznani.

% Podminky zpravneho rozpoznani:
% 1) znacka nusi byt cela nicim nezakryta.
% 2) znacka musi byt alespon minimalne osvetlena
% 3) u znacek mensich jako 75px x 75px nemusi rozeznavani pracovat korektne
% 4) v oblastich velmi blizkych znacky by nemeli byt jasne body
% 5) pri vyskytu vice vystraznych znacek na jedne fotografii se rozpoznava
%    pouze jedna, ale plati zde pravidlo, ze cim vice znacek tim mensi
%    pravdepodobnost na spravne urceni znacky.

% mazani vesech promenych a zavirani vsech oken co mel matlab otevreny
clear all;
close all;

% nacteni obrazku a jeho vykresleni
obr=imread('Dsc00015.jpg');
figure(
'name','Originalni fotografie');
imshow(obr);
title(
'Vyfocena fotografie');

% uprava jasu
obr_jas=double(obr).*1.85;

%prevod do Ycbcr prostoru kvuli ziskani cerveneho trojuhelniku
obr_ycbcr=rgb2ycbcr(obr_jas);
r_layer=obr_ycbcr(:,:,3);
r_layer=r_layer.^5/256.^2;
r_layer=uint8(r_layer);
figure(
'name','Cervena vrstva vybrana z obrazku');
imshow(r_layer);
title(
'Potlacene vsechny barvy krome cervene');

%prahovani a cisteni obrazku a hledani hran pro detekci hlavnich primek
h=imhist(r_layer);
prah=h(256)/h(1);
r_bw=im2bw(r_layer,1);
r_bw=bwmorph(r_bw,
'clean',20);
r_bw=bwmorph(r_bw,
'majority',5);
r_bw=bwmorph(r_bw,
'dilate');
r_bw=bwmorph(r_bw,
'close',5);
r_edge=edge(r_bw,
'sobel');
figure(
'name','Prahovany obrazek s nalezenyma hranama');
imshow(uint8(r_edge.*255));
title(
'Vyprahovany,vycisteny obrazek + nalezene hrany'); 

% Radon transformation
r_edge=uint8(r_edge.*255);
theta = (0:179)
';
[R,xp] = radon(r_edge,theta);  
figure(
'name','Radon Transformation');
imagesc(theta,xp,R), colorbar;
xlabel (
'theta (deg)'), ylabel ('rho (pixels from center)');title('Line Space');  
i=find(R>250);  
[foo,ind] = sort(-R(i));
k = i(ind(1:100));  
[y,x] = ind2sub(size(R),k);  
t=-theta(x)*pi/180;
r=xp(y);  
lines = [cos(t) sin(t) -r];  
cx = size(r_edge,2)/2-1;
cy = size(r_edge,1)/2-1;
lines(:,3) = lines(:,3) - lines(:,1)*cx - lines(:,2)*cy;  

%Draw lines to image and compare strong lines
vel=size(lines);
linie=zeros(2,3);
uk1=1;uk2=1;
for i=1:vel(1)
    x=lines(i);
    
if ((x(1)>sin(pi/180*(60-1.5))) && (x(1)<sin(pi/180*(60+1.5))))
        
if ((linie(1,1)==0)&&(linie(1,2)==0))
        linie(1,:)=lines(i,:);   
        
end
        
linie(1,:)=lines(i,:)+linie(1,:);
        uk1=uk1+1;    
    
end
    if 
((x(1)<sin(pi/180*(-60+1.5))) && (x(1)>sin(pi/180*(-60-1.5))))
        
if ((linie(2,1)==0)&&(linie(2,2)==0))
        linie(2,:)=lines(i,:);   
        
end
        
linie(2,:)=lines(i,:)+linie(2,:);
       uk2=uk2+1;    
    
end
end

%average from strong lines
linie(1,:)=linie(1,:)./uk1;
linie(2,:)=linie(2,:)./uk2;

% vykresleni hlavnich car
figure('name','Picture with two strong lines');
image(obr); title(
'Image with lines');
[xx,yy]=draw_lines(linie);  

%hledani vrcholove souradnice
posun_60=-floor(tan(pi/180*60)*xx(1,1));
posun_minus_60=-floor(tan(pi/180*-60)*xx(1,2));
vel=size(r_edge);
for i=1:vel(2)
    y1(i)=floor(tan(pi/180*60)*i+posun_60);
    y2(i)=floor(tan(pi/180*-60)*i+posun_minus_60);
end
souradnice_vrcholu=find(abs(y1-y2)<3);
souradnice_vrcholu=souradnice_vrcholu(1);

% hledani Vysky znacky
for i=50:400
    
if r_layer(y1(souradnice_vrcholu)+i,souradnice_vrcholu)==255
        s_y2=y1(souradnice_vrcholu)+i+10;
        break
    
end
end
s_y1=y1(souradnice_vrcholu);

% hledani pruseciku s vyznamnymi carami (urceni souradnic X)
pom=length(y1);
for i=1:pom(1)
    
if (y1(i)>(s_y2-2))&&(y1(i)<(s_y2+2))
        s_x2=i;
    
end
    if 
(y2(i)>(s_y2-2))&&(y2(i)<(s_y2+2))
        s_x1=i;
    
end
end

znacka=obr(s_y1:s_y2,s_x1:s_x2,:);
figure(
'name','vyrez znacky');
imshow(znacka);title(
'Vyrez znacky');

%mazani nepotrebnych informaci
clear R cx cy foo h i ind k lines uk1 uk2 xx yy vel t theta xp obr_jas pom posun_60;
clear posun_minus_60 prah r r_bw y1 y2 x y r_edge r_layer linie;

% upravy vyrezu
znacka_upravena=uprava_znacky_velikost(znacka);
figure(
'name','upravena znacka pro porovnani');
imshow(uint8(znacka_upravena));title(
'upravena znacka pro porovnani');
znacka_upravena_b=uprava_barev_znacky(znacka_upravena);
figure(
'name','vnitrek znacky');
imshow(uint8(znacka_upravena_b));title(
'vnitrek znacky');


% vlastni porovnani stredu znacky se vzory
figure('name','Prohledavany vzor');
for i=1:35
    cesta=[
'vzory\a' int2str(i) '.jpg'];
    vzor=imread(cesta);
    vzor=uprava_vzoru(vzor);
    korelace(i)=corr2(znacka_upravena_b,vzor);
    imshow(vzor)    
    title(
'Porovnavani tohoto vzoru se znackou z fotky');
end

% nalezeni znacky
match=find(max(korelace)==korelace(:));

% vykresleni vzoru
figure('name','nalezena znacka');
match_fig=imread([
'vzory\a' int2str(match) '.jpg']);
imshow(match_fig);

% vymazani pomocnych informaci
clear cesta i obr_ycbcr s_x1 s_x2 s_y1 s_y2 souradnice_vrcholu;
clear znacka_upravena znacka_upravena_b;

% ZAVER
% Pokud jsou dodrzeny podminky spravneho zpracovani tak tento skript
% nalezne temer vsechy znacky.
% Bohuzel diky nepresnostem vzoru, zejmena u znacky pozor krizovatka, klesa
% ucinost korelace, cos se projevi vetsi pravdepodobnosti ze se nalezne chybna znacka.