3.4 «Identitet» og «identitetsforvaltning»
4 Identitet og identifiserbarhet –
4.4 Nærmere om «identifisert eller identifiserbar» person
4.4.1 Identifiserbar person
Bit 2 Bit 1 Bit 0 Bit 7 Bit 6
Bit 1 Bit 0 Bit 7 tmp[1]
Figura 5.2.3.2.9 – Operação 3, Raster Order
Figura 5.2.3.2.10 – Operação 3, Anti-Raster Order
Esta metodologia proposta, que retira partido da simetria das operações de ordenação, permite simplificar e consolidar o processo, e diminuir os recursos necessários à sua implementação. O bloco de decisão presente na Figura 5.2.3.2.11 é considerado, o segundo mais importante do módulo de reconstrução morfológica, apenas superado pelo contador de posição.
Operação de Processamento
m_pos = ?
Operação 1 Operação 2 Operação 3
default
m_pos = reg_size -1
m_pos = 0 Operação
Completa
Figura 5.2.3.2.11 – Fluxograma do estado de Processing Operation
Bit 1 Bit 0 Bit 7 Bit 6 Bit 5
tmp[1] 0 -1
tmp[0] m_pos
Bit 2 Bit 1 Bit 0 Bit 7 Bit 6
m_pos tmp[0]
5.2.3.3. Controlo de Armazenamento
A próxima máquina de estados, do módulo de reconstrução morfológica, é o controlo de armazenamento. O objetivo do módulo é determinar quando o processamento do registo marcador é concluído, determinar a ordenação pela qual a imagem está a ser percorrida, guardar o valor pretendido numa variável temporária, e sinalizar o módulo de controlo da memória RAM, para que o resultado possa ser guardado. Assim, a Figura 5.2.3.3.1 descreve o processo relacionado com o pedido de escrita de um registo em memória.
Início reg_pos = ? Estado 0 Estado de Espera pending_req = 0 fwd_copy pending_req = 1 last_marker[w1] = curr_marker[w1] req_ram_w = curr_marker[w1] pending_req = 1 w1 = width -1 reg_pos = 0 last_marker[r1] = curr_marker[r1] req_ram_w = curr_marker[r1] pending_req = 1 default r1 = reg_pos -1 1 reg_pos = ? last_marker[0] = curr_marker[0] req_ram_w = curr_marker[0] pending_req = 1 reg_pos = width-1 last_marker[r2] = curr_marker[r2] req_ram_w = curr_marker[r2] pending_req = 1 default r2 = reg_pos +1 2 rev_copy pending_req = 0 pend_answ= 1 pend_answ = 0
Figura 5.2.3.3.1 – Fluxograma referente ao controlo de armazenamento
O significado de algumas das variáveis utilizadas não foi explicado anteriormente, pelo que a consulta da Tabela 5.2.3.3.1, em conjunto com as apresentadas anteriormente ajuda na compreensão do algoritmo.
Variável Significado
pending_req (Pending Request) Pedido de escrita na memória RAM
pend_answ (Pending Request Answered) Resposta ao pedido de escrita em memória
req_ram_w (Request RAM Write) Pedido de escrita do registo
Tabela 5.2.3.3.1 – Descrição das variáveis utilizadas no módulo de controlo de armazenamento
O módulo apresenta dois principais estados: o primeiro fica à espera da sinalização do relógio, para efetuar o pedido de cópia da variável para a memória, o segundo fica à espera que o pedido de acesso à memória seja atendido. A sinalização do relógio indica a ordenação, pela qual o sistema está a percorrer a imagem, Raster ou Anti-Raster.
O bloco de decisão, relativamente à posição do registo, determina qual das duas opções executa. O princípio da posição default é que o registo atual, se encontra na mesma linha do anterior (que é guardado em memória), pelo que apenas é necessário decrementar a posição do registo (Raster Order) ou incrementar o Registo (Anti-Raster Order), em relação ao registo atual, para obter a posição do registo a guardar em memória. O valor é então colocado na variável temporária req_ram_w, e a flag pend_req sinaliza o módulo de controlo de memória, que é necessário escrever o valor. As situações especiais situam-se, no primeiro registo de cada linha (Raster Order) ou no último (Anti-Raster Order). Neste caso, é necessário guardar o valor do último e primeiro registo da linha anterior, respetivamente. Como na posição default, o valor do registo a escrever, é guardado no registo temporário e a flag que realiza o pedido de escrita é ativada.
Após um pedido de escrita em memória, a máquina de estados é colocada em modo de espera, enquanto o pedido não é atendido. Quando o módulo de controlo de memória termina o processo de escrita, coloca a flag req_answ com o valor de um, sinalizando que o processo de escrita foi concluído, colocando a flag de pend_req a zero e voltando ao estado zero, até à próxima sinalização do relógio.
5.2.3.4. Controlo da memória RAM
O módulo de controlo da memória RAM é responsável por todas as operações de escrita na memória, por parte do módulo de reconstrução morfológica. Como tal, a atribuição de vários estados é necessário para responder a todas as necessidades do sistema. Na Figura 5.2.3.4.1 é possível analisar os diversos estados, bem como a lógica de funcionamento do módulo. Como o módulo de controlo de armazenamento e de processamento de dados, a sua execução é realizada na transição descendente do relógio.
Início Estado 1 Estado 2 Estado 3 Estado 4 Estado 5 Estado 6 ram_addr = 0 w_ram_val = ~0 Estado = 2 w_ram = 1 ram_addr = ram_addr +1 w_ram_val = ~0 w_ram = 1 ram_addr >= width ? Estado = 3 ram_addr =size - width Sim ram_addr = ram_addr +1 w_ram_val = ~0 w_ram = 1 ram_addr >= size ? Estado = 0 w_ram = 0 ram_addr = width Sim Estado = 5 w_ram = 1 ram_addr = reg_addr + (reverse - forward) Estado = 0 Escrever no marcador w_ram = 0 ram_tmp = w_ram_val reverse ? Estado = 6 ram_addr = ram_addr -1 Estado = 0 Não Sim A Não Não A Estado 0 req_asnw = 1 Estado = 4 w_ram_val = req_ram_w pending_req & ~req_answ
req_answ = 0 pend_req = 0 Reset
Estado = 1 ~rst rst
Os três primeiros estados do sistema (1, 2 e 3) têm como principal objetivo, preencher a primeira e última linha da imagem em memória com o valor de 1 em todos os bits do registo. Assim, o módulo inicia no estado 1, que coloca o endereço da memória RAM no primeiro valor, ativa a escrita, atribuí um registo com todos os bits a 1, e altera o estado do sistema para o segundo. Este estado prepara a posição e escrita na memória, enquanto o segundo continua o processo de escrita, incrementando o endereço de posição, até atingir o último registo da linha (width - 1). Quando o último registo é escrito, o estado é alterado para o terceiro, situando o endereço da memória, na última linha da imagem (size – width). O comportamento é similar ao do segundo estado, onde o objetivo é preencher todos os valores dos registos, da última linha da imagem com o valor de um. Quando o endereço da memória atinge um valor igual ao tamanho da imagem (reg_addr >= size), a escrita em memória é desativada (w_ram = 0) e o endereço é colocado no primeiro registo da segunda linha da imagem.
Após o processo inicial, o sistema fica à espera, no estado 0, de um pedido de escrita por parte do módulo de controlo de armazenamento. Quando um pedido é executado e não existe resposta pendente, o sistema escreve o valor temporário (req_ram_w) na entrada da porta RAM, sinaliza o módulo de controlo que o pedido foi atendido e muda o estado do sistema para o quarto. O quarto estado começa por posicionar o endereço a escrever e habilitar a escrita em memória, avançando em seguida para o estado 5. O objetivo deste estado, que executa um ciclo de relógio após o anterior, é desligar a escrita em memória, uma vez que a operação já foi concluída, e decidir se deve regressar ao estado de espera zero (Raster Order), ou ao sexto estado (Anti-Raster Order) e guardar o valor escrito num registo temporário, de forma a confirmar o sucesso da operação. Se o sistema processar os dados em Anti-Raster Order, o quinto estado decrementa o endereço da memória RAM e passa para o estado 6, que envia o valor do registo lido da memória para o registo de marcador, a processar após a conclusão do atual, permitindo que o sistema tenha sempre o próximo registo a processar disponível. Após o término da operação volta ao estado zero e espera pelo próximo pedido.
Por final o estado de Reset, coloca o sistema de volta no estado um, quando o seu valor voltar a zero, reiniciando assim o processo de escrita em memória (primeira e última linha apenas). Uma vez que a primeira iteração do algoritmo (Raster Order), não necessita de informação armazenada na memória RAM, não é necessário limpar a memória após o estado de reset, uma
vez que esta vai ser reescrita, antes de voltar a ser consultada na operação de reconstrução morfológica.
5.3. Implementação
O processo de implementação do sistema pode ser dividido em duas partes distintas, a primeira, composta pelo sistema representado na Figura 5.2.2.1, onde todos os resultados são confirmados através da ferramenta de simulação do Vivado. O sistema foi implementado sobre a HDL verilog, utilizando 32 bits por registo, onde cada linha é composta por 12 registos. A Imagem utilizada apresenta uma resolução de 384x260 pixéis.
Posteriormente, o sistema é ligado ao ZYNQ7 Processing System através do barramento AXI-4 (em modo simples), de forma a ser possível confirmar os resultados da simulação em hardware. Este tópico é desenvolvido na secção de resultados obtidos. Em ambos os casos foi utilizada a frequência de operação máxima permitida, 250 MHz, pela placa de desenvolvimento Zybo.
5.3.1. Contador de posição
Na Figura 5.3.1.1 é possível analisar o início do processo de contagem, que percorre a imagem de cima para baixo em Raster Order e de baixo para cima em Anti-Raster Order. O registo counter é incrementado, em todas as transições ascendentes do relógio, servindo como o contador do número total de operações realizadas pelo módulo. A variável de posição (pos) começa no segundo bit do registo, apenas os bits 1 a 31 são processados, uma vez que o primeiro pertence às margens da imagem. O endereço do registo e da memória ROM começam na segunda linha (posição 12), pelo mesmo motivo.
Figura 5.3.1.1 – Inicio do sistema de contagem
A primeira transição de registo pode ser observada na Figura 5.3.1.2. Como o registo 13 não pertence às margens da imagem, a variável de posição assume os valores 0 até 31. O registo reg_pos indica a posição na coluna da imagem, de 0 a 11, e o fwd_clk, indica que a operação está a ser realizada em Raster Order.
Figura 5.3.1.2 – Primeira transição de registo
A Figura 5.3.1.3 demonstra a transição de linha, por parte do sistema. O contador de posição salta do bit 30 do registo atual, para o bit 1 do registo seguinte, uma vez que, tanto o bit 31 do registo 11 como o bit 0 do registo 0 pertencem à margem da imagem. O endereço global do registo e da memória ROM é incrementado normalmente, sem nenhuma condição especial.
Figura 5.3.1.3 – Transição de linha
O processo inverso pode ser observado na Figura 5.3.1.4, onde a transição de linha é feita com a ordenação Anti-Raster. O sistema vai do registo 0 e endereço 3120, para o registo 11 do endereço de memória 3119. A variável de posição é decrementada até atingir o penúltimo bit do primeiro registo da linha atual, e salta para o segundo bit do último registo da linha anterior, evitando assim as margens da imagem.
Figura 5.3.1.4 – Transição de linha Anti-Raster Order
5.3.2. Processamento de dados
O módulo de processamento de dados atua na transição descendente do relógio, tal como descrito anteriormente. A Figura 5.3.2.1 demonstra o preenchimento do marcador atual. O bit 31 do registo recebe o valor 1, uma vez que pertence às margens da imagem, assim, o bit 30 é o primeiro a ser processado pelo sistema. Na Figura 5.3.2.2 é possível visualizar o sistema, a preencher os diversos registos de marcador disponíveis, consoante a iteração do algoritmo.
Figura 5.3.2.1 – Preenchimento do valor do marcador atual
Figura 5.3.2.2 – Preenchimento dos diversos registos do marcador atual
A relação entre os valores do marcador atual (curr_marker), e os do marcador anterior (last_marker) pode ser analisada na Figura 5.3.2.3. Os valores do last_marker são utilizados no processamento dos valores do curr_marker. No entanto, quando o processamento do registo atual termina, o seu valor é copiado, para o registo de marcador anterior, para que possa ser utilizado no processamento da linha seguinte.
Figura 5.3.2.3 – Relação entre last_marker e curr_marker
O Marker Canvas, representado na Figura 5.3.2.4, é utilizado durante a primeira iteração do algoritmo em Raster Order. O registo retorna os valores de uma imagem, com todos os bits a zero e as margens brancas, a um, consoante o valor da variável de posição (pos). O valor do registo corresponde a 31 bits com o valor 1 na primeira e última linha da imagem. As restantes linhas apresentam o comportamento demonstrado na Figura 5.3.2.4. Assim, apenas o primeiro bit do primeiro registo tem o valor 1, os registos intermédios têm todos o valor 0 e o último registo da
linha apresenta o valor decimal 1. Este registo torna desnecessária a alocação do valor inicial da imagem marcador em memória, acelerando e otimizando o processo.
Figura 5.3.2.4 – Marker Canvas
5.3.3. Escrita na memória RAM
Após a inicialização da imagem (estados 1, 2 e 3), o módulo que controla o acesso e escrita na memória RAM fica em modo de espera (estado 0), até receber um pedido de escrita. Na Figura 5.3.3.1 é possível analisar um pedido de escrita quando o estado transita do 0 para o 4, o valor a escrever (w_ram_val) é carregado do registo, o endereço de escrita é incrementado e a flag (w_ram) que possibilita a escrita em memória é ativada. O estado 5 desabilita a flag w_ram e guarda o valor escrito num registo temporário (ram_temp). Uma vez que o sistema estava a executar em Raster Order, o módulo de controlo de memória voltou ao estado zero, onde permanece até receber um novo pedido de escrita.
Figura 5.3.3.1 – Escrita na memória RAM
5.3.4. Execução do sistema
O sistema proposto apresenta dois modos de funcionamento distintos, devido à ordenação pela qual a imagem é percorrida. Assim, na primeira iteração a imagem é percorrida, da segunda à penúltima linha em Raster order. Com uma frequência de operação do sistema de 250MHz, uma imagem de 384x260 pixéis, pode ser percorrida em Raster Order em cerca de 405 μ
Figura 5.3.4.1 – Primeira iteração (Raster)
Após a primeira iteração, o sistema deve percorrer a imagem novamente, a partir da penúltima linha, até à segunda da imagem. Nesta segunda iteração, os valores do registo marcador são carregados a partir da memória RAM, contrariamente à primeira iteração, que utiliza os valores fornecidos pelo registo marker_canvas, trabalhando assim, com os resultados obtidos na primeira iteração. O sistema apresenta, em simulação, um tempo de processamento de cerca de 796μ segundos e 199022 ciclos de relógio para concluir o processo de reconstrução morfológica.
5.4. Resultados Práticos
Os resultados obtidos pelo módulo de reconstrução morfológica foram confirmados, através do envio dos dados refentes à imagem pela porta série. Para tal, o sistema (ffill_bus) foi ligado ao ZYNQ7 Processing System, através de um barramento AXI-4 (fill_bus) no modo simples. Todos os resultados foram obtidos utilizando a placa de desenvolvimento Zybo.
A seguir à conclusão do processo de reconstrução morfológica, o controlo sobre o endereço e acesso à memória RAM (dist_mem_gen_1), é passado ao barramento de dados, para que este possa comunicar os resultados obtidos com o CPU.
Após a construção e programação dos blocos constituintes do sistema, a arquitetura é validada pelo processo de synthesis. O bitstream gera o ficheiro de programação da placa, para que a implementação possa ser testada. Uma vez que o CPU é necessário para confirmar os resultados obtidos, na metodologia de teste utilizada, o hardware é exportado para o Vivado SDK, onde é possível programar o CPU, para interagir com a arquitetura do sistema proposto.
Após carregar os drivers referentes ao sistema de teste, e enviar a configuração do hardware da FPGA para a placa de desenvolvimento, é necessário criar uma rotina de teste, representada na Figura 5.4.2, a qual permite validar os resultados. No registo REG 0 é escrito o endereço de memória que se pretende ler, através da função mWriteReg. O resultado é lido no REG 1 como um valor inteiro, sem sinal, de 32 bits, pela função mReadReg. O valor é convertido de novo em binário e enviado pela porta série.
#include <stdio.h> #include "platform.h" #include "fill_bus.h" #include "xparameters.h" #include "xil_io.h" int main() { init_platform(); int count = 0; uint32_t result = 0; int bin = 0; int nmbr; do { FILL_BUS_mWriteReg(XPAR_FILL_BUS_0_S00_AXI_BASEADDR, FILL_BUS_S00_AXI_SLV_REG0_OFFSET,count); result = FILL_BUS_mReadReg(XPAR_FILL_BUS_0_S00_AXI_BASEADDR, FILL_BUS_S00_AXI_SLV_REG1_OFFSET);
xil_printf("POS:%d,", count); for (bin = 31; bin >=0; bin--) { nmbr = result >> bin; nmbr &=1; xil_printf("%d",nmbr); } xil_printf("\n\r"); count++; }while(count < 3131); cleanup_platform(); return 0; }
Figura 5.4.2 – Rotina de teste do CPU
O modo de funcionamento simples do barramento AXI-4 é muito útil, na depuração de resultados, no entanto a latência que apresenta, entre pedidos, não permite que seja utilizado em aplicações. Com uma frequência de operação de 250 MHz na FPGA, dois pedidos de leitura consecutivos, apresentam uma latência de 25 ciclos de relógio. O acesso por DMA à memória
externa, ou a utilização do barramento em modo stream, apresentam-se como soluções viáveis a este problema.
A aplicação em CUDA foi modificada para fornecer o valor dos pixéis da imagem, em registos de 32 bits, após o processo de reconstrução morfológica, criando assim uma base de comparação e validação de resultados entre ambas as abordagens. Na Figura 5.4.3 e Figura 5.4.4 é possível observar, à esquerda, os resultados recebidos, pela porta série, do sistema em FPGA e comparar os valores com os resultados obtidos pela aplicação em CUDA (imagem da direita), comprovando assim os resultados da implementação.
Figura 5.4.3 – Comparação de resultados entra FPGA e CUDA
Figura 5.4.4 – Comparação de resultados entra FPGA e CUDA 2
5.4.1. Escalabilidade do sistema com o aumento da resolução de imagem
Após a implementação do algoritmo, é possível elaborar algumas conclusões face à sua escalabilidade. Os resultados práticos demonstraram que o sistema necessita de 199022 ciclos
384x260. A partir deste resultado, é possível estimar o número de ciclos necessários para imagens de outras dimensões e o tempo de processamento, consoante a frequência de operação do sistema. O algoritmo é capaz de processar um valor um pouco superior a um pixel por ciclo de relógio, uma vez que as margens da imagem não são processadas. A Tabela 5.4.1.1 demonstra o estudo realizado sobre a escalabilidade do sistema, face ao aumento da resolução de imagem e diferentes frequências de operação.
Largura Altura Número de Pixéis Ciclos de relógio (estimativa) Frequência 100Mhz Frequência 250MHz Frequência 500 MHz 384 260 99840 199022 1,99 ms 0,796 ms 0,398 ms 640 480 307200 612375 6,12 ms 2,45 ms 1,225 ms 1024 640 655360 1306401 13,06 ms 5,226 ms 2,613 ms 1024 820 839680 1673826 16,74 ms 6,695 ms 3,348 ms 1280 720 921600 1837126 18,37 ms 7,349 ms 3,674 ms 1920 1080 2073600 4133534 41,34 ms 16,534 ms 8,267 ms
Tabela 5.4.1.1 – Escalabilidade do algoritmo
5.4.2. Recursos utilizados no FPGA
De uma forma geral, o módulo de reconstrução morfológica não ocupa muito espaço, mesmo numa FPGA com menor capacidade como a Zybo, pelo que a implementação do módulo de pré-processamento e de Threshold local são totalmente viáveis, numa placa de desenvolvimento com um pouco mais de capacidade. Pela análise da Figura 5.4.2.1, que representa a ocupação, em conjunto com o diagrama do sistema proposto (Figura 5.2.2.1), é possível verificar que grande parte do espaço utilizado advém da utilização de blocos de RAM internos. Na Figura 5.4.2.2 é possível analisar, mais detalhadamente, a utilização do sistema.
Figura 5.4.2.1 – Utilização de recursos do módulo de reconstrução morfológica
Figura 5.4.2.2 – Utilização de recursos (detalhada)
De uma forma geral, a placa de desenvolvimento apresenta uma arquitetura de memória externa unificada, onde é necessário a utilização de canais de DMA, para acesso à RAM externa, o que condicionou o processo de desenvolvimento. O sistema proposto apresenta um acesso repetido à memória, pelos diversos módulos de processamento, pelo que um sistema que permita maior velocidade de acesso, do FPGA à memória é essencial para o sucesso da metodologia.
5.5. Discussão
A implementação do módulo de reconstrução morfológica em FPGA pode ser considerada bem-sucedida, tendo sido alcançados resultados teóricos comparáveis à implementação em CPU, para uma resolução de 1024x820, com uma frequência de operação de 250 Mhz, como é possível verificar pela comparação da Tabela 5.4.1.1 com a Figura 4.8.4.1. No entanto, é preciso entrar em conta com a limitação de recursos disponíveis num FPGA, pelo que a resolução da imagem está mais limitada.
A implementação do sistema proposto em FPGA é considerada viável, especialmente porque apresenta uma solução embebida, com resultados próximos da implementação em desktop, para o módulo de reconstrução morfológica, que é considerado o mais crítico do sistema. Uma nova abordagem, que melhora o tempo de execução do módulo de reconstrução morfológica, mas limita a resolução das imagens analisadas, devido a uma maior utilização dos recursos disponíveis no FPGA, é proposta como trabalho futuro, no próximo capítulo.
6.
Conclusão e Trabalho Futuro
Neste capítulo, são apresentadas as principais conclusões relativas ao trabalho desenvolvido nesta dissertação de mestrado. De seguida, são propostas possíveis linhas de investigação a serem realizadas como trabalho futuro.
6.1. Conclusão
O principal problema das aplicações de seguimento é relacionar o mesmo objeto, em dois fotogramas diferentes. No seguimento de veículos, a matrícula pode ser utilizada como identificador único, que relacionará os veículos presentes em diferentes fotogramas. No entanto, as técnicas de segmentação da região da matrícula propostas na literatura, não apresentam as condições ideais para a implementação de um sistema de seguimento de veículos robusto. O