/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import javax.microedition.media.Manager;
import javax.microedition.media.MediaException;
import javax.microedition.media.Player;
/**
*
* @author Administrator
*/
public class UTioPatinhas {
static int BORDA_CLARO_ESCURO = 0, BORDA_ESCURO_CLARO = 1;
static int TAM_VETOR_LIMITES_VERTICAIS_GRUPOS = 300;
static int PIXEL_ACEITO = 1;
static int PIXEL_NAO_ACEITO = 2;
static int DELTA_Y_HISTOGRAM = 5, DELTA_X_HISTOGRAM = 5;
UTioPatinhas() {
}
static void ReconheceCedula(TParamsRC ParamsRC) {
//CDesktopFuncs.WriteOutput("Processamento iniciado.");
ParamsRC.LumMedianaImagem = Histograma(ParamsRC.ParamsMLT.TCImgSrc);
ParamsRC.ConverteParametrosDependentesLumMediana();
MostraLimiteTarja(ParamsRC.ParamsMLT);
ParamsRC.ParamsABT.BImgDest = ParamsRC.ParamsMLT.BImgDest;
ParamsRC.ParamsABT.BordasColunas = ParamsRC.ParamsMLT.BordasColunas;
AnalizaBordasTarja(ParamsRC.ParamsABT);
ParamsRC.ConverteParametrosDependentesAlturaFaixa();
if (ParamsRC.ParamsABT.AchouTarja) {
ParamsRC.ParamsAI.RefTarja = ParamsRC.ParamsABT.RefTarja;
ParamsRC.ParamsAI.BImgDest = ParamsRC.ParamsABT.BImgDest;
ParamsRC.ParamsAI.TCImgSrc = ParamsRC.ParamsMLT.TCImgSrc;
AnalizaIdentificador(ParamsRC.ParamsAI);
}
//CDesktopFuncs.WriteOutput("Processamento concluido!");
//EscreveParametros(ParamsRC);
}
/**
* Diz o valor da nota
*/
void say(int value){
String valueSoundFile = null;
switch (value){
case 1:
valueSoundFile = "01.wav";
break;
case 2:
valueSoundFile = "02.wav";
break;
case 5:
valueSoundFile = "05.wav";
break;
case 10:
valueSoundFile = "10.wav";
break;
case 20:
valueSoundFile = "20.wav";
break;
case 50:
valueSoundFile = "50.wav";
break;
case 100:
valueSoundFile = "100.wav";
break;
default:
valueSoundFile = "unknown.wav";
break;
}
try {
InputStream is = getClass().getResourceAsStream(valueSoundFile);
Player audioPlayer = Manager.createPlayer(is, "audio/X-wav");
audioPlayer.start();
} catch (IOException ioe) {
} catch (MediaException me) { }
}
/**
* Calcula o histograma da imagem toda, retornando a mediana de tons de cinza.
*/
static int Histograma(CTonsCinza TCImgSrc) {
int[] vetor = new int[256];
int[] vetorCumulativa = new int[256];
int n, x, y;
int MetadeTotal;
int Mediana;
int[][] ImgSrc = TCImgSrc.TonsCinza;
for (y = 0; y < TCImgSrc.Alt; y+=DELTA_Y_HISTOGRAM) {
for (x = 0; x < TCImgSrc.Larg; x+=DELTA_X_HISTOGRAM) {
vetor[ImgSrc[y][x]]++;
}
}
vetorCumulativa[0] = vetor[0];
for (n = 1; n < 256; n++) {
vetorCumulativa[n] = vetorCumulativa[n - 1] + vetor[n];
}
Mediana = 0;
MetadeTotal = vetorCumulativa[255] / 2;
for (n = 1; n < 256; n++) {
if (vetorCumulativa[n] >= MetadeTotal) {
Mediana = n;
break;
}
}
return Mediana;
}
/**
* Varre a imagem verticalmente detectando grande variação de contraste entre
* os pixels. Estas variações são marcadas superiormente com uma faixa vermelha
* e inferiormente com uma faixa verde.
*/
static void MostraLimiteTarja(TParamsMLT ParamsMLT) {
int ALT_COLUNA = 3, DY = 2, DIF_MIN_LUM = 15;
int x, y, j;
int yBorda;
int DifLum;
int UltYBordaCE, UltYBordaEC;
int MaisEscuroAtual, MaisClaroAtual, MaisClaroAnterior, MaisEscuroAnterior;
int lum;
int[][] ImgSrc = ParamsMLT.TCImgSrc.TonsCinza;
Cor[][] ImgDest = ParamsMLT.BImgDest.PMCor;
int YIni = (int) (ParamsMLT.TCImgSrc.Alt * ParamsMLT.PropYIni);
int XFim = (int) (ParamsMLT.TCImgSrc.Larg * ParamsMLT.PropXFim);
TBorda BordaTemp;
TMaiorBorda MaiorBorda = new TMaiorBorda();
ParamsMLT.BordasColunas = new TBordasColunas(XFim);
for (x = 0; x < XFim; x++) {
UltYBordaCE = UltYBordaEC = -1;
MaiorBorda.DifLum = 0;
for (y = YIni + ALT_COLUNA; y < (ParamsMLT.TCImgSrc.Alt - ALT_COLUNA); y++) {
MaisEscuroAtual = 255;
MaisEscuroAnterior = 255;
MaisClaroAtual = 0;
MaisClaroAnterior = 0;
//define os mais claros e mais escuros atuais
for (j = y; j < (y + ALT_COLUNA); j++) {
lum = ImgSrc[j][x];
if (lum > MaisClaroAtual) {
MaisClaroAtual = lum;
}
if (lum < MaisEscuroAtual) {
MaisEscuroAtual = lum;
}
}
//define os mais claros e os mais escuros anteriores
for (j = y - (ALT_COLUNA + DY); j < (y - DY); j++) {
lum = ImgSrc[j][x];
if (lum > MaisClaroAnterior) {
MaisClaroAnterior = lum;
}
if (lum < MaisEscuroAnterior) {
MaisEscuroAnterior = lum;
}
}
// if (x==25 && y==170)
// int w=5;
//borda claro encima, escuro embaixo
DifLum = MaisEscuroAnterior - MaisClaroAtual;
if (DifLum > DIF_MIN_LUM) {
if (DifLum > MaiorBorda.DifLum) {
MaiorBorda.DifLum = DifLum;
MaiorBorda.y = y;
}
UltYBordaCE = y;
} else {
if (y == (UltYBordaCE + 1)) {
yBorda = MaiorBorda.y - ALT_COLUNA;
ImgDest[yBorda][x].SetVermelho();
BordaTemp = new TBorda();
BordaTemp.Y = yBorda;
BordaTemp.TipoBorda = BORDA_CLARO_ESCURO;
ParamsMLT.BordasColunas.Bordas[x].addElement(BordaTemp);
MaiorBorda.DifLum = 0;
}
}
//borda escuro encima, claro embaixo
DifLum = MaisEscuroAtual - MaisClaroAnterior;
if (DifLum > DIF_MIN_LUM) {
if (DifLum > MaiorBorda.DifLum) {
MaiorBorda.DifLum = DifLum;
MaiorBorda.y = y;
}
UltYBordaEC = y;
} else {
if (y == (UltYBordaEC + 1)) {
yBorda = MaiorBorda.y - ALT_COLUNA;
ImgDest[yBorda][x].SetVerde();
BordaTemp = new TBorda();
BordaTemp.Y = yBorda;
BordaTemp.TipoBorda = BORDA_ESCURO_CLARO;
ParamsMLT.BordasColunas.Bordas[x].addElement(BordaTemp);
MaiorBorda.DifLum = 0;
}
}
}
}
}
/**
* Analiza os limites vermelhos e verdes de cada uma das tarjas, marcando
* a faixa amarela na distancia média entre as mesmas.
*/
static void AnalizaBordasTarja(TParamsABT ParamsABT) {
int x,
n;
int NumColunas = ParamsABT.BordasColunas.NumColunas;
ParamsABT.ConjuntoMeioBordas = new TConjuntoMeioBordas(NumColunas);
int dif;
TVectorBorda BordasTemp;
TBorda BordaEnc, BordaEmb;
TMeioBordas MeioBordasTemp;//= new TMeioBordas();
Cor[][] ImgDest = ParamsABT.BImgDest.PMCor;
for (x = 0; x < NumColunas; x++) {
BordasTemp = ParamsABT.BordasColunas.Bordas[x];
//percorre todas as bordas da coluna
for (n = 1; n < BordasTemp.size(); n++) {
BordaEnc = BordasTemp.retornaTBorda(n - 1);
BordaEmb = BordasTemp.retornaTBorda(n);
dif = BordaEmb.Y - BordaEnc.Y;
if ((BordaEmb.TipoBorda == BORDA_ESCURO_CLARO) &&
(BordaEnc.TipoBorda == BORDA_CLARO_ESCURO) &&
(dif >= ParamsABT.AltMinTarja) && (dif <= ParamsABT.AltMaxTarja)) {
MeioBordasTemp = new TMeioBordas(BordaEnc.Y, BordaEmb.Y);
ParamsABT.ConjuntoMeioBordas.VectorMeioBordas[x].addElement(MeioBordasTemp);
ImgDest[MeioBordasTemp.yMeio][x].SetAmarelo();
}
}
}
SelecionaTarja(ParamsABT);
if (ParamsABT.AchouTarja) {
ImgDest[ParamsABT.RefTarja.y][ParamsABT.RefTarja.x].SetMagenta();
ImgDest[ParamsABT.RefTarja.y + 1][ParamsABT.RefTarja.x].SetMagenta();
ImgDest[ParamsABT.RefTarja.y][ParamsABT.RefTarja.x + 1].SetMagenta();
ImgDest[ParamsABT.RefTarja.y + 1][ParamsABT.RefTarja.x + 1].SetMagenta();
}
}
/**
* Descarta as tarjas que estao fora dos limites de largura e com a altura
* variando muito (analizando os desvios padrão calculados em preparaSelecionaTarja)
*/
static void SelecionaTarja(TParamsABT ParamsABT) {
int n, nMenorX, m, LargTarjaCandidata;
TTarja TarjaCandidata;
int MenorX, AlturaTarjaMColunaN;
double soma, desvio, media, MediaTarjaSelecionada = 0;
PreparaSelecionaTarja(ParamsABT);
MenorX = 0xFFFFFF;
nMenorX = -1;
ParamsABT.AchouTarja = false;
//percorre vector com todas as tarjas
for (n = 0; n < ParamsABT.VectorTarja.size(); n++) {
TarjaCandidata = ParamsABT.VectorTarja.retornaTTarja(n);
LargTarjaCandidata = TarjaCandidata.VetorAlturas.size();
//ifdef DEBUG
//CDesktopFuncs.WriteOutput("Tarja candidata " + String.valueOf(n) + ".\tLargura:\t" + String.valueOf(LargTarjaCandidata) +
// "\tX:\t" + String.valueOf(TarjaCandidata.X) +
// "\tY:\t" + String.valueOf(TarjaCandidata.PriYEnc));
//endif
if ((LargTarjaCandidata <= ParamsABT.LargMaxTarja) &&
(LargTarjaCandidata >= ParamsABT.LargMinTarja)) {
soma = 0;
//calcula a média da altura de cada coluna da possível tarja
for (m = 0; m < ParamsABT.VectorTarja.retornaTTarja(n).VetorAlturas.size(); m++) {
soma += ParamsABT.VectorTarja.retornaTTarja(n).VetorAlturas.retornaInteiro(m).intValue();
}
media = soma / ParamsABT.VectorTarja.retornaTTarja(n).VetorAlturas.size();
//calcula o desvio padrão
soma = 0;
for (m = 0; m < ParamsABT.VectorTarja.retornaTTarja(n).VetorAlturas.size(); m++) {
AlturaTarjaMColunaN = ParamsABT.VectorTarja.retornaTTarja(n).VetorAlturas.retornaInteiro(m).intValue();
soma = Math.abs(media - AlturaTarjaMColunaN);
}
desvio = soma / ParamsABT.VectorTarja.retornaTTarja(n).VetorAlturas.size();
// ifdef DEBUG
//CDesktopFuncs.WriteOutput("desvio padrão alturas: " + String.valueOf(desvio));
//endif
if (desvio < ParamsABT.DesvioMax) {
//ifdef DEBUG
//CDesktopFuncs.WriteOutput("menor do que o limite de : " + String.valueOf(ParamsABT.DesvioMax));
//endif
//pode ser substituído por um código que pega o primeiro. mantido para debug
if (ParamsABT.VectorTarja.retornaTTarja(n).X < MenorX) {
MenorX = ParamsABT.VectorTarja.retornaTTarja(n).X;
nMenorX = n;
MediaTarjaSelecionada = media;
}
}
}
}
if (nMenorX != -1) {
ParamsABT.RefTarja.x = ParamsABT.VectorTarja.retornaTTarja(nMenorX).X;
ParamsABT.RefTarja.y = ParamsABT.VectorTarja.retornaTTarja(nMenorX).PriYEnc;
ParamsABT.MediaAlturaTarja = MediaTarjaSelecionada;
ParamsABT.AchouTarja = true;
}
}
/**
* Calcula os desvios padrões das alturas de cada coluna das tarjas detectadas.
*/
static void PreparaSelecionaTarja(TParamsABT ParamsABT) {
int x;
int n, m;
boolean Adicionou;
TMeioBordas MeioBordasTemp;
for (x = 0; x < ParamsABT.ConjuntoMeioBordas.NumColunas; x++) {
//percorre todos os meio de bordas da coluna (pixels amarelos)
for (m = 0; m < ParamsABT.ConjuntoMeioBordas.VectorMeioBordas[x].size(); m++) {
Adicionou = false;
MeioBordasTemp = ParamsABT.ConjuntoMeioBordas.VectorMeioBordas[x].retornaTMeioBordas(m);
//percorre todas as tarjas que estão ativas na coluna corrente
for (n = 0; n < ParamsABT.VectorTarja.size(); n++) {
if (ParamsABT.VectorTarja.retornaTTarja(n).Ativa(x)) {
if (Math.abs(ParamsABT.VectorTarja.retornaTTarja(n).UltYMeio - MeioBordasTemp.yMeio) <= ParamsABT.DistMaxTarjas) {
ParamsABT.VectorTarja.retornaTTarja(n).VetorAlturas.adicionaInteiro(new Integer(MeioBordasTemp.Altura));
ParamsABT.VectorTarja.retornaTTarja(n).UltYMeio = MeioBordasTemp.yMeio;
Adicionou = true;
}
}
}
if (!Adicionou) {
TTarja TarjaTemp = new TTarja();
TarjaTemp.X = x;
TarjaTemp.UltYMeio = MeioBordasTemp.yMeio;
TarjaTemp.PriYEnc = MeioBordasTemp.Y1;
TarjaTemp.VetorAlturas.adicionaInteiro(new Integer(MeioBordasTemp.Altura));
ParamsABT.VectorTarja.adicionaTTarja(TarjaTemp);
}
}
}
}
//Mostra a linha cyan (azul claro) que representa o ponto de referência da tarja para a localização
//do identificador, e retorna a luminosidade média dos pixels da faixa
static int MediaFaixa(TParamsAI ParamsAI) {
int x, y, xIni, xFim, soma;
int[][] ImgSrc = ParamsAI.TCImgSrc.TonsCinza;
Cor[][] ImgDest = ParamsAI.BImgDest.PMCor;
xIni = ParamsAI.RefTarja.x;
xFim = xIni + ParamsAI.LargFaixaRef;
y = ParamsAI.RefTarja.y - ParamsAI.DistFaixaRef;
soma = 0;
for (x = xIni; x < xFim; x++) {
soma += ImgSrc[y][x];
ImgDest[y][x].SetCyan();
}
double retorno1 = (soma * 1.0 / ParamsAI.LargFaixaRef);
int retorno = (int) MathUtils.round(retorno1);
return retorno;
}
//---------------------------------------------------------------------------
/**
* Processa a imagem na região marcada pelo ARect agrupando os grupos conexos de pixels escuros.
* O ARect guarda a regiao detectada como o identificador na cedula.
*
* entradas de dados: CTonsCinza tcImgSrc, TRect ARect, int limiar
* saidas de dados: int[][] MatrizGrupos, TLimitesVerticaisGrupo[] VetorLimitesVerticaisGrupo, int[] PonteiroGrupos
*/
static void MatrizGruposConexos(CTonsCinza tcImgSrc, TRect ARect, int[][] MatrizGrupos, int limiar,
TLimitesVerticaisGrupo[] VetorLimitesVerticaisGrupo, int[] PonteiroGrupos) {
int x, y, i, j, n;
boolean AnteriorDentroGrupo;//informa se o pixel anteriormente processado na linha possuía um grupo
boolean AchouGrupoEncima;
boolean EmGrupoNovo = false;
int ContadorGrupos, GrupoAtual, GrupoEncima;
int[][] ImgSrc = tcImgSrc.TonsCinza;
//inicialmente cada grupo aponta para ele mesmo
for (n = 0; n < TAM_VETOR_LIMITES_VERTICAIS_GRUPOS; n++) {
PonteiroGrupos[n] = n;
}
ContadorGrupos = 1;
GrupoAtual = 0;
for (y = ARect.top + 1; y < ARect.bottom; y++) {
AnteriorDentroGrupo = false;
for (x = ARect.left + 1; x < ARect.right - 1; x++) {
if (ImgSrc[y][x] < limiar) {
if (!AnteriorDentroGrupo)//se pixel anterior (da esquerda) não possuia grupo, prossegue
{
EmGrupoNovo = true;
AchouGrupoEncima = false;
j = y - ARect.top;
//procura encima por pixels com grupo
for (n = -1; n <= 1; n++) {
i = x - ARect.left;
GrupoAtual = PonteiroGrupos[MatrizGrupos[j - 1][i + n]];
if (GrupoAtual > 0) {
AchouGrupoEncima = true;
EmGrupoNovo = false;
break;
}
}
//se não achou pixels encima então cria um novo grupo
if (!AchouGrupoEncima) {
GrupoAtual = ContadorGrupos;
VetorLimitesVerticaisGrupo[GrupoAtual].yEmb = 0;
VetorLimitesVerticaisGrupo[GrupoAtual].yEnc = 0xFFFF;
ContadorGrupos++;
}
} else //já estamos dentro de um grupo
{
//devemos sempre ver se encima existe algum grupo antigo
j = y - ARect.top - 1;
i = x - ARect.left + 1;
GrupoEncima = PonteiroGrupos[MatrizGrupos[j][i]];
if ((MatrizGrupos[j][i] > 0) && (GrupoEncima != GrupoAtual))//tem grupo antigo encima
{
if (EmGrupoNovo) {
PonteiroGrupos[GrupoAtual] = GrupoEncima;
GrupoAtual = GrupoEncima;//o grupo atual agora é o de cima
EmGrupoNovo = false;
} else {
PonteiroGrupos[GrupoEncima] = GrupoAtual;
}
}
}
j = y - ARect.top;
i = x - ARect.left;
MatrizGrupos[j][i] = GrupoAtual;
AnteriorDentroGrupo = true;
//atualiza limites verticais do grupo caso necessário
if (j > VetorLimitesVerticaisGrupo[GrupoAtual].yEmb) {
VetorLimitesVerticaisGrupo[GrupoAtual].yEmb = j;
}
if (j < VetorLimitesVerticaisGrupo[GrupoAtual].yEnc) {
VetorLimitesVerticaisGrupo[GrupoAtual].yEnc = j;
}
} else //se pixel é mais claro que o limiar
{
AnteriorDentroGrupo = false;
}
}
}
}
//---------------------------------------------------------------------------
/**
* Corta fora dos grupos conexos os grupos cujas alturas sejam muito pequenas
* em comparação com a altura da faixa preta de referencia detectada.
*/
static void SelecionaGruposIdentificador(TLimitesVerticaisGrupo[] VetorLimitesVerticaisGrupo,
char[] VetGruposValidos, int AltMin, int[] PonteiroGrupos, int yFim, int DifMinEmb) {
int altura, DifEmb;
int GrupoReal;
for (int n = 1; n < TAM_VETOR_LIMITES_VERTICAIS_GRUPOS; n++) {
GrupoReal = PonteiroGrupos[n];
altura = VetorLimitesVerticaisGrupo[GrupoReal].yEmb - VetorLimitesVerticaisGrupo[GrupoReal].yEnc;
DifEmb = yFim - VetorLimitesVerticaisGrupo[GrupoReal].yEmb;
//ifdef DEBUG
// if (altura)
if (altura>0)
//CDesktopFuncs.WriteOutput("Região candidata altura: " + String.valueOf(altura) + " DifEmb: " + String.valueOf(DifEmb));
//endif
if (altura >= AltMin && DifEmb < DifMinEmb) {
VetGruposValidos[n] = (char) PIXEL_ACEITO;
} else {
VetGruposValidos[n] = (char) PIXEL_NAO_ACEITO;
}
}
}
//---------------------------------------------------------------------------
//MatrizGrupos é variável de entrada e de saída
static void CopiaGruposValidos(int[][] MatrizGrupos, TRect ARect, char[] VetGruposValidos) {
int x, y;
int larg, alt;
larg = ARect.Width();
alt = ARect.Height();
for (y = 0; y < alt; y++) {
for (x = 0; x < larg; x++) {
MatrizGrupos[y][x] = VetGruposValidos[MatrizGrupos[y][x]];
}
}
}
//---------------------------------------------------------------------------
static void PintaIdentificador(CBitmap BImgDest, TRect ARect, int[][] MatrizGrupos) {
int x, y;
int larg, alt;
Cor[][] ImgDest = BImgDest.PMCor;
larg = ARect.Width();
alt = ARect.Height();
for (y = 0; y < alt; y++) {
for (x = 0; x < larg; x++) {
if (MatrizGrupos[y][x] == PIXEL_ACEITO) {
ImgDest[y + ARect.top][x + ARect.left].SetCyan();
} else if (MatrizGrupos[y][x] == PIXEL_NAO_ACEITO) {
ImgDest[y + ARect.top][x + ARect.left].SetAzul();
}
}
}
}
//---------------------------------------------------------------------------
static float RetornaRelacaoMedianasLargurasEncEmb(int[] VetorLarguras, int comeco, int fim,
int[] MediaLarguras) {
int alt = fim - comeco;
int[] vetor = new int[alt + 1];
int MetadeAltura = alt / 2;
int QuartoAltura = (int) MathUtils.round(alt * 1.0 / 4);
int[] Larguras = new int[2];
for (int n = 0; n < 2; n++) {
System.arraycopy(VetorLarguras, comeco + n * MetadeAltura, vetor, 0, MetadeAltura);
COrdenacao.OrdenaInt(vetor, MetadeAltura);
Larguras[n]=vetor[QuartoAltura];
//Vector a=new Vector();
//for (int u=0; u<MetadeAltura; u++)
// a.addElement(new Integer(vetor[u]));
//java.util.Collections.sort(a);
//memcpy(vetor, VetorLarguras + comeco + n * MetadeAltura, MetadeAltura * sizeof(int));
// qsort(vetor, MetadeAltura, sizeof(int), ComparaInteiro);
//Larguras[n] = ((Integer)a.elementAt(QuartoAltura)).intValue();
}
//delete [] vetor;
//ifdef DEBUG
//CDesktopFuncs.WriteOutput("Largura encima: " + String.valueOf(Larguras[0]));
//CDesktopFuncs.WriteOutput("Largura embaixo: " + String.valueOf(Larguras[1]));
//endif
MediaLarguras[0] = (Larguras[0] + Larguras[1]) / 2;
if (Larguras[1] > 0) {
return (float) (Larguras[0] * 1.0 / Larguras[1]);
} else {
return -100;
}
}
//---------------------------------------------------------------------------
/**
* Pega as informacoes estraidas da imagem pelas outras funcoes e faz a decisao
* sobre qual identificador foi detectado.
*/
static void Identifica(TParamsAI ParamsAI)
{
//ifdef DEBUG
//CDesktopFuncs.WriteOutput("Inclinação identificador: "+String.valueOf(ParamsAI.Inclinacao));
//CDesktopFuncs.WriteOutput("Altura identificador: "+String.valueOf(ParamsAI.Alt));
//CDesktopFuncs.WriteOutput("Relação larguras identificador: "+String.valueOf(ParamsAI.RelacaoMedianasLargurasEncEmb));
if (ParamsAI.RelacaoMedianasLargurasEncEmb > 0) {
//CDesktopFuncs.WriteOutput("Relação inversa larguras identificador: "+String.valueOf(1.0/ParamsAI.RelacaoMedianasLargurasEncEmb));
}
//CDesktopFuncs.WriteOutput("Relação Altura/Largura: "+String.valueOf(ParamsAI.RelacaoLargAlt));
//CDesktopFuncs.WriteOutput("Número médio de colunas: "+String.valueOf(ParamsAI.NumMedColunas));
//endif
if (ParamsAI.Inclinacao>ParamsAI.LimiarInclinacaoidentificador)
{
//ifdef DEBUG
//CDesktopFuncs.WriteOutput("Inclinação maior que o limite, pode ser \tR$2\tR$20");
///endif
if (ParamsAI.RelacaoLargAlt>ParamsAI.LimiarRelacaoLargAlt)
{
//ifdef DEBUG
//CDesktopFuncs.WriteOutput("Relação Altura/Largura maior que o limite, é R$2");
//endif
ParamsAI.ValorCedula=2;
}
else
{
//ifdef DEBUG
//CDesktopFuncs.WriteOutput("Relação Altura/Largura menor que o limite, é R$20");
//endif
ParamsAI.ValorCedula=20;
}
}
else
{
//ifdef DEBUG
//CDesktopFuncs.WriteOutput("Inclinação menor que o limite, pode ser \tR$1\tR$5\tR$10\tR$50\tR$100");
//endif
if (ParamsAI.Alt>ParamsAI.LimiarAlturaIdentificador)
{
//ifdef DEBUG
//CDesktopFuncs.WriteOutput("Altura maior que o limite, pode ser \tR$1\tR$5\tR$50\tR$100");
//endif
if (ParamsAI.RelacaoMedianasLargurasEncEmb>ParamsAI.LimiarLargLinhasIdentificador)
{
//ifdef DEBUG
//CDesktopFuncs.WriteOutput("Relação medianas larguras maior que o limite, é R$50");
//endif
ParamsAI.ValorCedula=50;
}
else if (1.0/ParamsAI.RelacaoMedianasLargurasEncEmb>ParamsAI.LimiarLargLinhasIdentificador)
{
//ifdef DEBUG
//CDesktopFuncs.WriteOutput("Relação inversa medianas larguras maior que o limite, é R$100");
//endif
ParamsAI.ValorCedula=100;
}
else
{
//ifdef DEBUG
//CDesktopFuncs.WriteOutput("Relação medianas larguras menor que o limite, pode ser \tR$1\tR$5");
//endif
if (ParamsAI.NumMedColunas<ParamsAI.LimiarNumMedColunas)
{
//ifdef DEBUG
//CDesktopFuncs.WriteOutput("Número médio de colunas menor que o limite, é R$1");
//endif
ParamsAI.ValorCedula=1;
}
else
{
//ifdef DEBUG
//CDesktopFuncs.WriteOutput("Número médio de colunas maior que o limite, é R$5");
//endif
ParamsAI.ValorCedula=5;
}
}
}
else
{
//ifdef DEBUG
//CDesktopFuncs.WriteOutput("Altura menor que o limite, é R$10");
//endif
ParamsAI.ValorCedula=10;
}
}
}
//---------------------------------------------------------------------------
/**
* Analiza o identificador para detectar o valor das notas.
*/
static void AnalizaIdentificador(TParamsAI ParamsAI) {
int NADA = 0, IDENTIFICADOR = 1, FUNDO = 2;
int TAM_HIST = 200;
int EstadoUltPixel;
int x, y;
int xIni, xFim, yIni, yFim;
int YEnc, YEmb, LargLinha, MaiorLargLinha, NumBordasPixelLinha;
int XEsq, XDir, UltXEnc = 0, UltXEmb = 0, MaiorUltXEnc;
int NumLinha, UltYComLinha, NumPixelsIdentificador;
int[] VetorLarguras;
char[] VetGruposValidos = new char[TAM_VETOR_LIMITES_VERTICAIS_GRUPOS];
//usado para indicar grupos conexos que fazem parte de outros grupos
int[] PonteiroGrupos = new int[TAM_VETOR_LIMITES_VERTICAIS_GRUPOS];
boolean AchouLinha;
int[] HistogramaNumBordasPixelLinha = new int[TAM_HIST];
TRect ARect;
xIni = ParamsAI.RefTarja.x - ParamsAI.XIniParaRefTarja;
xFim = xIni + ParamsAI.LargIdentificador;
yFim = ParamsAI.RefTarja.y - ParamsAI.YIniParaRefTarja;
yIni = yFim - ParamsAI.AltIdentificador;
int TamVetLarguras = yFim - yIni + 1;
VetorLarguras = new int[TamVetLarguras];
//memset(VetorLarguras, 0, TamVetLarguras*sizeof(int));
int Media = MediaFaixa(ParamsAI);
//ifdef DEBUG
//CDesktopFuncs.WriteOutput("Luminosidade média faixa: " + String.valueOf(Media));
//endif
int Limiar = Media - ParamsAI.DifMinMediaFaixaRef;
CMatrizInteiro MatrizGrupos = new CMatrizInteiro(xFim - xIni + 1, yFim - yIni + 1);
TLimitesVerticaisGrupo[] VetorLimitesVerticaisGrupo =
new TLimitesVerticaisGrupo[TAM_VETOR_LIMITES_VERTICAIS_GRUPOS];
for (int s = 0; s < TAM_VETOR_LIMITES_VERTICAIS_GRUPOS; s++) {
VetorLimitesVerticaisGrupo[s] = new TLimitesVerticaisGrupo();
}
ARect = new TRect(xIni, yIni, xFim, yFim);
COutros.LimitaTRect(ARect);
MatrizGruposConexos(ParamsAI.TCImgSrc, ARect,
MatrizGrupos.Matriz, Limiar, VetorLimitesVerticaisGrupo, PonteiroGrupos);
SelecionaGruposIdentificador(VetorLimitesVerticaisGrupo, VetGruposValidos,
ParamsAI.AltMinGrupoConexoIdentificador, PonteiroGrupos, ARect.Height(),
ParamsAI.DifMinEmbGrupoEmbRegiaoIdentificador);
CopiaGruposValidos(MatrizGrupos.Matriz, ARect, VetGruposValidos);
PintaIdentificador(ParamsAI.BImgDest, ARect, MatrizGrupos.Matriz);
YEnc = 0;
YEmb = -1;
MaiorLargLinha = 0;
NumLinha = 0;
MaiorUltXEnc = 0;
NumPixelsIdentificador = 0;
UltYComLinha = -1;
//ifdef DEBUG
//CDesktopFuncs.WriteOutput("Área do identificador: X: (" + String.valueOf(xIni) + ", " +
// String.valueOf(xFim) + " Y: (" + String.valueOf(yIni) + ", " + String.valueOf(yFim) + ")");
//endif
for (y = ARect.Height(); y > 0; y--) {
XEsq = -1;
XDir = 0;
AchouLinha = false;
NumBordasPixelLinha = 0;
EstadoUltPixel = NADA;
for (x = 0; x < ARect.Width(); x++) {
if (MatrizGrupos.Matriz[y][x] == PIXEL_ACEITO) {
if (YEmb == -1) {
YEmb = y;
}
YEnc = y;
if (XEsq == -1) {
XEsq = x;
}
XDir = x;
//se for a primeira linha
if (NumLinha == 0) {
UltXEmb = x;
}
UltXEnc = x;
AchouLinha = true;
NumPixelsIdentificador++;
if (EstadoUltPixel != IDENTIFICADOR) {
NumBordasPixelLinha++;
}
EstadoUltPixel = IDENTIFICADOR;
} else {
EstadoUltPixel = FUNDO;
}
}
LargLinha = XDir - XEsq;
VetorLarguras[y] = LargLinha;
if (LargLinha > MaiorLargLinha) {
MaiorLargLinha = LargLinha;
}
if (AchouLinha) {
if (UltXEnc > MaiorUltXEnc) {
MaiorUltXEnc = UltXEnc;
}
NumLinha++;
UltYComLinha = y;
HistogramaNumBordasPixelLinha[NumBordasPixelLinha]++;
} else {
if ((UltYComLinha != -1) &&
((UltYComLinha - y) >= ParamsAI.MaiorDistSemPixelsIdentificador) &&
(NumPixelsIdentificador > ParamsAI.NumMinPixelsIdentificador)) {
break;
}
}
}
int soma = 0;
for (int w = 0; w < TAM_HIST; w++) {
soma += HistogramaNumBordasPixelLinha[w] * w;
}
if (NumLinha > 0) {
ParamsAI.NumMedColunas = (float) (soma * 1.0 / NumLinha);
} else {
ParamsAI.NumMedColunas = -100;
}
int[] MediaLarguras = new int[1];
ParamsAI.RelacaoMedianasLargurasEncEmb =
RetornaRelacaoMedianasLargurasEncEmb(VetorLarguras, YEnc, YEmb, MediaLarguras);
ParamsAI.Alt = YEmb - YEnc;
if (MediaLarguras[0] > 0) {
ParamsAI.RelacaoLargAlt = (float) (ParamsAI.Alt * 1.0 / MediaLarguras[0]);
} else {
ParamsAI.RelacaoLargAlt = 0;
//ifdef DEBUG
//CDesktopFuncs.WriteOutput("UltXEnc: " + String.valueOf(MaiorUltXEnc) + "\tUltXEmb: " + String.valueOf(UltXEmb));
//CDesktopFuncs.WriteOutput("YEmb: " + String.valueOf(YEmb) + "\t\tYEnc: " + String.valueOf(YEnc));
//endif
}
if (ParamsAI.Alt > 0) {
ParamsAI.Inclinacao = (float) ((MaiorUltXEnc - UltXEmb) * 1.0 / ParamsAI.Alt);
} else {
ParamsAI.Inclinacao = -100;
}
ParamsAI.MaiorLargLinha = MaiorLargLinha;
Identifica(ParamsAI);
//delete [] VetorLarguras;
//delete ARect;
//delete MatrizGrupos;
}
//---------------------------------------------------------------------------
}