%% Reconhecimento de Placa
% Trabalho 02 de Processamento Digital de Sinais 2 
% Gisele Tam GRR20102167
% 
% O código contém 5 etapas:
% * pré-processamento
% * reconhecimento de bordas
% * localização da placa
% * segmentação dos caracteres
% * reconhecimento dos caracteres
% 
%% 1) Pré-processamento
clear all
clc
% Carregamento da imagem
arq = 'placa7.jpg';
im_orig = imread(arq);
figure, imshow(im_orig), title('Imagem Original')

% Imagem em escala cinza
im_gray = rgb2gray(im_orig);
% figure, imshow(im_gray),title('Imagem em escala cinza')


%% 2) Reconhecimento de bordas
%%
% Filtro Sobel
aux = im_gray;
[~,thres] = edge(aux,'sobel');
fator = 0.8;
im_sobel2 = edge(aux,'sobel',thres*fator);
% figure
% subplot(3,2,1)
% imshow(im_sobel2), title('Filtro Sobel')

%% 
% Dilatar a imagem
se = strel('rectangle',[50 20]); 
im_dil = imdilate(im_sobel2,se);
% subplot(3,2,2), 
% imshow(im_dil), title('Bordas Dilatadas')

%%
% Erosão da imagem
se = strel('rectangle',[100 75]);
im_er = imerode(im_dil,se);
% subplot(3,2,3), 
% imshow(im_er), title('Erosão da Imagem')

%%
% Limpar as bordas
im_l = imclearborder(im_er,4);
% subplot(3,2,4), 
% imshow(im_l), title('Bordas retiradas')

%%
% Preencher buracos
im_preenc = imfill(im_l,'holes');
% subplot(3,2,5), 
% imshow(im_preenc), title('Imagem Preenchida')

%%
%Remover objetos pequenos
remover = 30000;
im_rem = bwareaopen(im_preenc, remover);
% subplot(3,2,6), 
% imshow(im_rem), title('Remoção de objetos pequenos')
%

%% 3) Localização da placa

stats = regionprops('table',im_rem,'BoundingBox');
% Cada linha do BoundingBox está no formato:
% [ul_x ul_y length_x length_y]; ul = upper left
%  As placas tem tamanho 40x13 cm; 13/70 = 0,325

regiao = 1; % se houver somente uma area

if height(stats)>1 % caso haja mais de uma área
    possivel_regiao = []; % armazenar as possíveis regiões 
    criterio_alt = []; % critério de desempate: altura na imagem (não da região)
    for i = 1:height(stats)
        if stats(i,1).BoundingBox(3) > 1.5*(stats(i,1).BoundingBox(4))
            % verificar a proporção entre os lados => não adianta com
            % placas inclinadas; fazer com comprimento > altura
%             prop = stats(i,1).BoundingBox(4)/stats(i,1).BoundingBox(3); 
            possivel_regiao = [possivel_regiao i];
            criterio_alt = [criterio_alt stats(i,1).BoundingBox(2)];
        end
    end 
    if length(possivel_regiao)==1
        regiao = possivel_regiao(1);
    else % existe mais de uma região que respeita a relação
        [i,ind_y] = max(criterio_alt); % recuperar o indice com maior altura
        regiao = possivel_regiao(ind_y);
    end
else
    regiao = 1;
end

placa = imcrop(im_gray, stats(regiao,:).BoundingBox);
figure, imshow(placa), title('Placa do carro')


%%
% Imagem em binário
thresh = graythresh(placa);
placa_bw = im2bw(placa,thresh);
placa_bw = ~placa_bw;


%%
% Remover ruídos (imagens menor que o parâmetro)
area = 30;
pl_rem = bwareaopen(placa_bw, area);

% 2ª Erosão
seD = strel('diamond',2);
pl_erd = imerode(pl_rem,seD);

% figure, imshow(pl_erd), title('Placa em binário')


%% 4) Segmentação dos caracteres

% Label(): conecta componentes em imagens binárias 2D
[label, nElem] = bwlabel(pl_erd);
% Propriedades da Imagem
statsPlaca = regionprops(label,'BoundingBox');


%% 
coord = [] ;
c = 1;
for ind=1:nElem
    aux = statsPlaca(ind,1).BoundingBox;
    prop = aux(3)/aux(4);  % base/altura; I = 10/63 e A = 54/63
    if (prop >= 0.08) & (prop <= 1.0)
        coord(c,:) = aux;
        c = c+1;
    end
end

% ordenar as linhas de acordo com as colunas 
coord2 = sortrows(coord,4);
coordY = coord2(end-6:end,:); % retirar os últimos (mais altos)
coordX = sortrows(coordY,3); % ordenar de acordo com o comprimento
coordX2 = coordX(1:end,:); % retirar os mais largos
caract = sortrows(coordX2,1); % para que fique na ordem

figure
letra = [];
for ind=1:length(caract)
    x = floor(caract(ind,1));
    y = floor(caract(ind,2));
    dx = caract(ind,3);
    dy = caract(ind,4);
    n1 = pl_erd(y+1:y+dy-1,x+1:x+dx-1);
    n1 = imresize(n1, [150 150]);
    letra{ind} = ~n1;
%     imshow(letra{ind});
%     pause(0.5)
end

%% 5) Reconhecimento dos caracteres - Aspectos HOG
% Baseado em "Digit classification using HOG Features", do MathWorks
% http://www.mathworks.com/help/vision/examples/digit-classification-using-hog-features.html

%% 
% Treinamento 

cellSize = [8 8];
load('trainHOG3.mat');

%% 
% Avaliação dos caracteres da placa

% Letras
testFeaturesLetras = [];

for i=1:3
    img = letra{i};
    testFeaturesLetras(i,:) = extractHOGFeatures(img,'CellSize',cellSize);
end

% Números
testFeaturesNum = [];

for i=4:7
    img = letra{i};
    testFeaturesNum(i-3,:) = extractHOGFeatures(img,'CellSize',cellSize);
end

%% 
% Predição dos caracteres

predictedLetras = predict(classLetras, testFeaturesLetras);
predictedNum = predict(classNum, testFeaturesNum);


%% Resultados
fprintf('Identificação da placa: %s%s \n', predictedLetras,predictedNum)

























