Processamento de Imagem: Melhoria de Algoritmo para Reconhecimento 'Coca-Cola Can'


1659

Um dos projetos mais interessantes em que trabalhei nos últimos dois anos foi um projeto sobre processamento de imagens . O objetivo era desenvolver um sistema para reconhecer 'latas' da Coca-Cola (observe que estou enfatizando a palavra 'latas', você verá o porquê em um minuto). Você pode ver uma amostra abaixo, com a lata reconhecida no retângulo verde com escala e rotação.

Correspondência de modelos

Algumas restrições no projeto:

  • O fundo pode ser muito barulhento.
  • A lata pode ter qualquer escala ou rotação ou mesmo orientação (dentro de limites razoáveis).
  • A imagem pode ter algum grau de imprecisão (os contornos podem não ser totalmente retos).
  • Pode haver garrafas de Coca-Cola na imagem e o algoritmo deve detectar apenas a lata !
  • O brilho da imagem pode variar muito (então você não pode confiar "demais" na detecção de cores).
  • A lata pode estar parcialmente escondida nas laterais ou no meio e possivelmente parcialmente escondida atrás de uma garrafa.
  • Não havia nenhuma lata na imagem; nesse caso, você não precisava encontrar nada e escrever uma mensagem dizendo isso.

Então você pode acabar com coisas complicadas como esta (que neste caso tiveram meu algoritmo totalmente falho):

Falha total

Eu fiz esse projeto há um tempo atrás, e me diverti muito fazendo isso, e eu tive uma implementação decente. Aqui estão alguns detalhes sobre minha implementação:

Idioma : feito em C ++ usando a biblioteca OpenCV .

Pré-processamento : Para o pré-processamento de imagem, ou seja, transformar a imagem em uma forma mais bruta para fornecer ao algoritmo, usei 2 métodos:

  1. Alterando o domínio de cores de RGB para HSV e a filtragem com base em matiz "vermelho", saturação acima de um determinado limite para evitar cores alaranjadas e filtragem de baixo valor para evitar tons escuros. O resultado final foi uma imagem em preto e branco binária, na qual todos os pixels brancos representariam os pixels que correspondem a esse limite. Obviamente, ainda há muita porcaria na imagem, mas isso reduz o número de dimensões com as quais você precisa trabalhar. Imagem binarizada
  2. Filtragem de ruído usando filtragem mediana (pegando o valor mediano do pixel de todos os vizinhos e substituindo o pixel por esse valor) para reduzir o ruído.
  3. Usando o Canny Edge Detection Filter para obter os contornos de todos os itens após 2 etapas anteriores. Detecção de contorno

Algoritmo : O próprio algoritmo que eu escolhi para esta tarefa foi retirado deste livro incrível sobre extração de recursos e chamado Generalized Hough Transform (bem diferente da Hough Transform normal). Basicamente, diz algumas coisas:

  • Você pode descrever um objeto no espaço sem conhecer sua equação analítica (que é o caso aqui).
  • É resistente a deformações da imagem, como redimensionamento e rotação, pois basicamente testará sua imagem para todas as combinações de fator de escala e fator de rotação.
  • Ele usa um modelo base (um modelo) que o algoritmo "aprenderá".
  • Cada pixel restante na imagem de contorno votará em outro pixel que supostamente será o centro (em termos de gravidade) do seu objeto, com base no que aprendeu com o modelo.

No final, você acaba com um mapa de calor dos votos, por exemplo, aqui todos os pixels do contorno da lata votarão em seu centro gravitacional, para que você tenha muitos votos no mesmo pixel correspondente ao centro e verá um pico no mapa de calor como abaixo:

GHT

Depois disso, uma heurística simples baseada em limite pode fornecer a localização do pixel central, a partir do qual você pode derivar a escala e a rotação e, em seguida, plotar seu pequeno retângulo em torno dele (a escala final e o fator de rotação obviamente serão relativos ao seu tamanho). modelo original). Em teoria, pelo menos ...

Resultados : Agora, embora essa abordagem funcionasse nos casos básicos, faltava muito em algumas áreas:

  • É extremamente lento ! Não estou estressando isso o suficiente. Foi necessário quase um dia inteiro para processar as 30 imagens de teste, obviamente porque eu tinha um fator de escala muito alto para rotação e translação, já que algumas latas eram muito pequenas.
  • Perdeu-se completamente quando havia garrafas na imagem e, por algum motivo, quase sempre encontrou a garrafa em vez da lata (talvez porque as garrafas fossem maiores, tinham mais pixels, mais votos)
  • Imagens confusas também não eram boas, uma vez que os votos acabavam em pixels em locais aleatórios ao redor do centro, terminando com um mapa de calor muito barulhento.
  • A variação na translação e rotação foi alcançada, mas não na orientação, o que significa que uma lata que não estava diretamente voltada para a objetiva da câmera não foi reconhecida.

Você pode me ajudar a melhorar meu algoritmo específico , usando exclusivamente recursos OpenCV , para resolver os quatro problemas específicos mencionados?

Espero que algumas pessoas também aprendam algo com isso, afinal, acho que não apenas as pessoas que fazem perguntas devem aprender. :)


45
Pode-se dizer que essa pergunta é mais apropriada em dsp.stackexchange.com ou stats.stackexchange.com, e você certamente deve considerar pedir novamente nesses sites.
ely

49
A primeira coisa a fazer aqui é analisar por que os diferentes casos de falha estão acontecendo. Por exemplo, isole exemplos de lugares onde as garrafas vencem, onde as imagens são imprecisas etc. e faça algumas análises estatísticas para aprender a diferença entre as representações de Hough e as que você deseja que ele detecte. Alguns ótimos lugares para aprender sobre abordagens alternativas estão aqui e aqui
Ely

7
@stacker faz um bom argumento. Para obter velocidade, você deseja obter recursos baratos de calcular, como histogramas de gradientes orientados. Uma primeira abordagem realmente ingênua seria rotular manualmente um monte de retângulos de lata em algumas imagens de treinamento e usar esses exemplos negativos aleatórios para treinar um SVM ou classificador de árvore de decisão. O treinamento levará mais tempo, mas a execução em novas imagens será muito mais rápida. Estou planejando escrever esse método quando tiver mais tempo livre para incluir as referências corretas.
ely

9
Que tal uma abordagem semelhante à reCAPTCHA ? ;)
George Duckett

39
Por que isso foi movido do dsp.stackexchange.com ? Parece que esse local seria um ajuste ainda melhor do que stackoverflow o_O
BlueRaja - Danny Pflughoeft

Respostas:


672

Uma abordagem alternativa seria extrair recursos (pontos-chave) usando a transformação de recurso invariável em escala (SIFT) ou Recursos Robustos Acelerados (SURF).

É implementado no OpenCV 2.3.1.

Você pode encontrar um bom exemplo de código usando os recursos do Features2D + Homography para encontrar um objeto conhecido

Ambos os algoritmos são invariantes ao dimensionamento e rotação. Como eles funcionam com recursos, você também pode lidar com a oclusão (desde que pontos-chave suficientes sejam visíveis).

Digite a descrição da imagem aqui

Fonte da imagem: exemplo de tutorial

O processamento leva algumas centenas de ms para SIFT, SURF é um pouco mais rápido, mas não é adequado para aplicações em tempo real. O ORB usa FAST, que é mais fraco em relação à invariância de rotação.

Os documentos originais


6
Concordo com @stacker - SIFT é uma excelente escolha. É muito robusto contra operações de balança e rotação. É um tanto robusto contra a deformação de perspectiva (isso pode ser aprimorado como sugerido pelo empilhador: um banco de dados de modelo com diferentes vistas em perspectiva do objeto desejado). O calcanhar de Aquiles na minha experiência seria fortes variações de iluminação e computação muito cara. Não conheço nenhuma implementação de Java. Estou ciente de uma implementação OpenCV e usei uma implementação GPU c ++ / Windows ( SiftGPU ) adequada para desempenho em tempo real.

31
Uma nota de aviso: por mais que eu goste de SIFT / SURF e do que eles fizeram comigo, eles estão sobrecarregados de patentes. Isso pode ser um problema, dependendo de várias condições, incluindo a localização geográfica AFAIK.
Agos

12
Portanto, tente o ORB ou FREAK do OpenCV, que não possui problemas de patente. ORB é muito mais rápido que SIFT. ORB é um pouco pobre com variações de escala e luz na minha experiência, mas teste você mesmo.
Rui Marques

66
Como você pode aceitar isso como uma resposta ... Nenhum dos descritores de recursos pode diferenciar garrafas de latas. Todos eles exibem apenas descritores de padrões locais invariantes. Concordo que SIFT, SURF, ORB, FREAK etc. podem ajudá-lo na correspondência de recursos, mas ... E as outras partes da pergunta como oclusões, Bottle vs Can etc. Espero que esta não seja uma solução completa, de fato, se você GOOGLED seu problema, provavelmente o primeiro resultado seria apenas esta resposta.
G453

11
@ G453 você está absolutamente certo! Provavelmente ele estava fascinado com o desempenho de SHIFT e se esqueceu de que a extração de características e de correspondência não era o problema ...
sepdek

383

Para acelerar as coisas, eu aproveitaria o fato de que você não é solicitado a encontrar uma imagem / objeto arbitrário, mas especificamente um com o logotipo da Coca-Cola. Isso é significativo porque esse logotipo é muito distinto e deve ter uma assinatura característica e invariável na escala no domínio da frequência, particularmente no canal vermelho do RGB. Ou seja, o padrão alternado de vermelho para branco-vermelho encontrado por uma linha de varredura horizontal (treinada em um logotipo alinhado horizontalmente) terá um "ritmo" distinto ao passar pelo eixo central do logotipo. Esse ritmo irá "acelerar" ou "desacelerar" em diferentes escalas e orientações, mas permanecerá proporcionalmente equivalente. Você pode identificar / definir algumas dezenas de linhas de varredura, horizontal e verticalmente através do logotipo e várias mais na diagonal, em um padrão de explosão estelar. Chame isso de "linhas de verificação de assinatura".

Linha de verificação de assinatura

A busca dessa assinatura na imagem de destino é uma simples questão de digitalizar a imagem em faixas horizontais. Procure uma alta frequência no canal vermelho (indicando a mudança de uma região vermelha para uma branca) e, uma vez encontrada, veja se é seguida por um dos ritmos de frequência identificados na sessão de treinamento. Uma vez encontrada uma correspondência, você saberá instantaneamente a orientação e a localização da linha de verificação no logotipo (se você acompanhar essas coisas durante o treinamento), portanto, identificar os limites do logotipo a partir daí é trivial.

Eu ficaria surpreso se este não fosse um algoritmo linearmente eficiente, ou quase isso. Obviamente, não trata da discriminação com as garrafas, mas pelo menos você terá seus logotipos.

(Atualização: para o reconhecimento da garrafa, eu procuraria coque (o líquido marrom) adjacente ao logotipo - ou seja, dentro da garrafa. Ou, no caso de uma garrafa vazia, eu procuraria uma tampa que sempre terá o mesma forma, tamanho e distância básicos do logotipo e, geralmente, são brancos ou vermelhos. Pesquise uma forma elíptica de cor sólida em que um boné deve estar, em relação ao logotipo. Não é à prova de falhas, é claro, mas seu objetivo aqui é: encontrar as fáceis aqueles rápido .)

(Faz alguns anos desde os meus dias de processamento de imagem, por isso mantive essa sugestão de alto nível e conceitual. Acho que pode aproximar um pouco a maneira como um olho humano pode funcionar - ou pelo menos como meu cérebro funciona!)


24
Essa é uma ótima sugestão, eu particularmente gosto do fato de que esse algoritmo deve ser bem rápido, mesmo que provavelmente tenha muitos falsos negativos. Um dos meus objetivos ocultos é usar essa detecção em tempo real para robótica, para que possa ser um bom compromisso!
Charles Menguy

42
Sim, é frequentemente esquecido (em um campo caracterizado pela precisão) que algoritmos de aproximação são essenciais para a maioria das tarefas de modelagem do mundo real em tempo real. (Baseei minha tese nesse conceito.) Salve seus algoritmos que demandam tempo em regiões limitadas (para remover falsos positivos). E lembre-se: em robótica, você geralmente não está limitado a uma única imagem. Supondo que um robô móvel, um alg rápido pode pesquisar dezenas de imagens de diferentes ângulos em menos tempo do que os sofisticados gastam em um, reduzindo significativamente os falsos negativos.
kmote

29
Gosto da idéia de usar o que equivale a um scanner de código de barras para detecção extremamente rápida de logotipos da Coca-Cola. +1!
Li-Aung Yip

8
O problema de procurar assinaturas nesse caso é que, se virarmos a lata para o outro lado, ou seja, ocultar a assinatura, o algoritmo falhará ao detectar a lata.
precisa saber é o seguinte

34
@karlphillip: Se você ocultar a assinatura, ou seja, o logotipo, qualquer método baseado na procura do logotipo falhará.
precisa saber é o seguinte

162

Problema divertido: quando olhei para a sua imagem de garrafa, pensei que era uma lata também. Mas, como humano, o que fiz para dizer a diferença é que percebi que também era uma garrafa ...

Então, para diferenciar latas e garrafas, que tal simplesmente procurar garrafas primeiro? Se você encontrar um, oculte o rótulo antes de procurar latas.

Não é muito difícil de implementar se você já está usando latas. A desvantagem real é que ele dobra seu tempo de processamento. (Mas pensando em aplicações do mundo real, você acabará querendo fazer garrafas de qualquer maneira ;-)


5
Sim, eu também pensei nisso, mas não tive muito tempo para fazê-lo. Como você reconheceria uma garrafa, já que sua parte principal será semelhante a uma lata em escala? Eu estava pensando em procurar pelo plugue vermelho também e ver se ele está alinhado com o centro engarrafado, mas isso não parece muito robusto.
Charles Menguy

42
Se houver uma tampa vermelha (ou anel) paralela à "Coca Cola", é mais provável que seja uma garrafa.
Lukasz Madon

@linker Como você treinou seu algoritmo para latas? Você teve exemplos de latas? Que tal treinar com exemplos de garrafas?
siamii

1
A força desse algoritmo é que você só precisa de um modelo para treinar e, em seguida, aplica todas as transformações para corresponder a outras latas em potencial. Eu estava usando uma versão binarizada e baseada em contorno deste modelo para treinar, então a única diferença entre lata e garrafa seria o plugue, mas receio que traria mais falsos positivos, já que o centro de gravidade estaria em algum ponto no limite ou fora da garrafa. Vale a pena tentar, eu acho. Mas isso vai dobrar o meu tempo de processamento e eu vou chorar;)
Charles Menguy 16/04/12

7
Essencialmente, esta é uma direção razoável. Eu diria que é um pouco diferente: primeiro encontre todos os candidatos e, em seguida, para cada candidato, determine se é uma garrafa, uma lata ou outra coisa.
precisa saber é o seguinte

131

Não é difícil, mesmo para humanos, distinguir entre uma garrafa e uma lata na segunda imagem (desde que a região transparente da garrafa esteja oculta)?

Eles são quase os mesmos, exceto em uma região muito pequena (ou seja, a largura na parte superior da lata é um pouco pequena, enquanto o invólucro da garrafa tem a mesma largura por toda parte, mas uma pequena alteração, certo?)

A primeira coisa que me veio à mente foi verificar a tampa vermelha da garrafa. Mas ainda é um problema, se não houver tampa para a garrafa ou se ela estiver parcialmente oculta (como mencionado acima).

A segunda coisa que pensei foi sobre a transparência da garrafa. O OpenCV tem alguns trabalhos para encontrar objetos transparentes em uma imagem. Verifique os links abaixo.

Particularmente, observe isso para ver com que precisão eles detectam vidro:

Veja o resultado da implementação:

Digite a descrição da imagem aqui

Eles dizem que é a implementação do artigo "Uma Estrutura de Contorno Geodésico Ativo para Encontrar Vidro", de K. McHenry e J. Ponce, CVPR 2006 .

Pode ser útil no seu caso um pouco, mas o problema surge novamente se a garrafa estiver cheia.

Então, acho que aqui, você pode procurar primeiro o corpo transparente das garrafas ou uma região vermelha conectada lateralmente a dois objetos transparentes, que obviamente é a garrafa. (Ao trabalhar idealmente, uma imagem da seguinte maneira.)

Digite a descrição da imagem aqui

Agora você pode remover a região amarela, ou seja, o rótulo da garrafa e executar seu algoritmo para encontrar a lata.

De qualquer forma, esta solução também apresenta problemas diferentes, como nas outras soluções.

  1. Funciona apenas se a sua garrafa estiver vazia. Nesse caso, você terá que procurar a região vermelha entre as duas cores pretas (se o líquido da Coca Cola for preto).
  2. Outro problema se a parte transparente for coberta.

De qualquer forma, se não houver nenhum dos problemas acima nas fotos, isso parece ser o melhor caminho.


+1 Pensei sobre isso e estava no meu caminho para implementar essa abordagem. No entanto, o @linker deve compartilhar seu conjunto de imagens para que possamos tentar adivinhar mais.
precisa saber é o seguinte

sim .. eu também estou pensando que seria bom se houvesse mais imagens.
Abid Rahman K

Considerando se temos apenas os rótulos para garrafas / latas e nenhum dos outros fatores distintivos de tampa ou transparência da garrafa ou lata superior / inferior - A largura da garrafa é diferente da largura da lata.
Ken

E se uma lata for colocada na frente do logotipo da garrafa?
AlgoRythm 22/01

51

Eu realmente gosto das respostas de Darren Cook e Stacker para esse problema. Eu estava no meio de colocar meus pensamentos em um comentário sobre eles, mas acredito que minha abordagem tem uma forma de resposta muito grande para não sair daqui.

Em resumo, você identificou um algoritmo para determinar que um logotipo da Coca-Cola está presente em um local específico no espaço. Agora você está tentando determinar, por orientações arbitrárias e fatores arbitrários de escala, uma heurística adequada para distinguir latas de Coca-Cola de outros objetos, incluindo: garrafas , outdoors , anúncios e apetrechos da Coca-Cola, todos associados a este logotipo icônico. Você não mencionou muitos desses casos adicionais na declaração do problema, mas acho que eles são vitais para o sucesso do seu algoritmo.

O segredo aqui é determinar quais recursos visuais uma lata contém ou, através do espaço negativo, quais recursos estão presentes para outros produtos da Coca-Cola que não estão presentes nas latas. Para esse fim, a resposta principal atual esboça uma abordagem básica para selecionar "pode" se e somente se "garrafa" não for identificada, pela presença de uma tampa de garrafa, líquido ou outras heurísticas visuais semelhantes.

O problema é que isso ocorre. Uma garrafa pode, por exemplo, estar vazia e sem a presença de uma tampa, levando a um falso positivo. Ou poderia ser uma garrafa parcial com recursos adicionais destruídos, levando novamente à detecção falsa. Escusado será dizer que isso não é elegante, nem é eficaz para os nossos propósitos.

Para esse fim, os critérios de seleção mais corretos para latas parecem ser os seguintes:

  • A forma da silhueta do objeto, como você esboçou em sua pergunta , está correta? Se sim, +1.
  • Se assumimos a presença de luz natural ou artificial, detectamos um contorno cromado na garrafa que significa se é feito de alumínio? Se sim, +1.
  • Determinamos que as propriedades especulares do objeto estão corretas em relação às nossas fontes de luz ( link de vídeo ilustrativo na detecção de fontes de luz )? Se sim, +1.
  • Podemos determinar quaisquer outras propriedades sobre o objeto que o identifiquem como possível, incluindo, entre outras, a inclinação da imagem topológica do logotipo, a orientação do objeto, a justaposição do objeto (por exemplo, em uma superfície plana) como uma mesa ou no contexto de outras latas) e a presença de uma aba de puxar? Se sim, para cada um, +1.

Sua classificação pode parecer com a seguinte:

  • Para cada partida do candidato, se a presença de um logotipo da Coca Cola for detectada, desenhe uma borda cinza.
  • Para cada partida acima de +2, desenhe uma borda vermelha.

Isso destaca visualmente o usuário o que foi detectado, enfatizando positivos fracos que podem, corretamente, ser detectados como latas mutiladas.

A detecção de cada propriedade possui uma complexidade de tempo e espaço muito diferente e, para cada abordagem, uma rápida passagem pelo http://dsp.stackexchange.com é mais do que razoável para determinar o algoritmo mais correto e eficiente para seus propósitos. Minha intenção aqui é, pura e simplesmente, enfatizar que a detecção de algo é possível, invalidando uma pequena parte do espaço de detecção de candidatos não é a solução mais robusta ou eficaz para esse problema e, idealmente, você deve tomar as ações apropriadas adequadamente.

E ei, parabéns pela publicação do Hacker News! No geral, essa é uma pergunta bastante fantástica, digna da publicidade que recebeu. :)


2
Isso é uma abordagem interessante que é, pelo menos, vale a pena tentar, eu realmente gosto do seu raciocínio sobre o problema
Charles Menguy

Isso é o que eu estava pensando: não descarte tipos particulares de falsos positivos. Regra em mais recursos do que faz uma lata de coca-cola. Mas eu estou pensando: o que você faz com uma lata esmagada? Quero dizer, se você pisar em uma lata de coca, ainda é uma lata de coca. Mas não terá mais a mesma forma. Ou esse problema é AI-Complete?
24712 Ian

41

Olhando para a forma

Dê uma olhada na forma da parte vermelha da lata / garrafa. Observe como a lata diminui levemente na parte superior, enquanto a etiqueta da garrafa é reta. Você pode distinguir entre esses dois comparando a largura da parte vermelha ao longo do comprimento.

Olhando para os destaques

Uma maneira de distinguir entre garrafas e latas é o material. Uma garrafa é feita de plástico, enquanto uma lata é feita de metal de alumínio. Em situações suficientemente bem iluminadas, observar a especularidade seria uma maneira de distinguir um rótulo de garrafa de um rótulo de lata.

Até onde eu sei, é assim que um humano pode dizer a diferença entre os dois tipos de etiquetas. Se as condições de iluminação forem ruins, é provável que haja alguma incerteza na distinção entre as duas. Nesse caso, você precisaria detectar a presença da própria garrafa transparente / translúcida.


Gosto da ideia, mas parece que você precisaria de realmente boas condições de iluminação. Na imagem de exemplo, onde há lata e garrafa, por exemplo, isso parece um pouco difícil de fazer a distinção.
Charles Menguy

No seu exemplo, observe como a especularidade da etiqueta plástica é muito mais difusa do que os pontos muito brilhantes da lata? É assim que você pode dizer.
precisa

Entendo, que tipo de representação do espaço de cores você usaria nesse caso para capturar especularidade em seu algoritmo? Isso parece bastante difícil de obter em RGB ou HSV
Charles Menguy

3
E se a fonte de luz estivesse atrás da lata? Eu acho que você não veria o destaque.
Rui Marques

37

Por favor, dê uma olhada no rastreador Predator de Zdenek Kalal . Requer algum treinamento, mas pode aprender ativamente como o objeto rastreado olha para diferentes orientações e escalas e o faz em tempo real!

O código fonte está disponível em seu site. Está no MATLAB , mas talvez já exista uma implementação Java feita por um membro da comunidade. Reimplantei com êxito a parte do rastreador do TLD em C #. Se bem me lembro, o TLD está usando Ferns como o detector de ponto-chave. Em vez disso, uso SURF ou SIFT (já sugerido pelo @stacker) para recuperar o objeto se ele foi perdido pelo rastreador. O feedback do rastreador facilita a construção com o tempo de uma lista dinâmica de modelos de peneirar / surfar que, com o tempo, permitem recuperar o objeto com uma precisão muito alta.

Se você estiver interessado na minha implementação em C # do rastreador, não hesite em perguntar.


Obrigado pelo link que parece interessante. Em relação ao treinamento, qual é o tamanho do conjunto de treinamento que seria razoável para obter resultados razoáveis? Se você tiver uma implementação mesmo em c #, isso também seria muito útil!
Charles Menguy

Ao pesquisar o TLD, encontrei outro usuário procurando uma implementação em C # - existe algum motivo para não colocar seu trabalho no Github? stackoverflow.com/questions/29436719/…
spillner

2
NB Anos, mais tarde, o link está morto agora
J Evans

33

Se você não estiver limitado a apenas uma câmera que não estava em uma de suas restrições, talvez você possa usar um sensor de alcance como o Xbox Kinect . Com isso, você pode realizar a segmentação correspondente da imagem com base em profundidade e cor. Isso permite uma separação mais rápida dos objetos na imagem. Em seguida, você pode usar a correspondência de ICP ou técnicas semelhantes para igualar a forma da lata, em vez de apenas o contorno ou a cor e, dado que é cilíndrico, essa pode ser uma opção válida para qualquer orientação, se você tiver uma digitalização 3D anterior do alvo. Essas técnicas geralmente são bastante rápidas, especialmente quando usadas para uma finalidade específica que deve resolver seu problema de velocidade.

Também eu poderia sugerir, não necessariamente por precisão ou velocidade, mas por diversão, você poderia usar uma rede neural treinada em sua imagem segmentada de matiz para identificar o formato da lata. Eles são muito rápidos e podem ter até 80/90% de precisão. O treinamento seria um pouco demorado, pois você teria que identificar manualmente a lata em cada imagem.


3
Na verdade, não expliquei isso no post, mas, para essa tarefa, recebi um conjunto de aproximadamente 30 imagens e tive que fazer um algoritmo que as correspondesse a todas em várias situações, conforme descrito. É claro que algumas imagens foram exibidas para testar o algoritmo no final. Mas gosto da ideia dos sensores Kinect e adoraria ler mais sobre o assunto!
Charles Menguy

Qual seria o tamanho do conjunto de treinamento com uma rede neural para obter resultados satisfatórios? O bom desse método também é que eu só preciso de um modelo para corresponder a quase tudo.
Charles Menguy

2
Se o seu conjunto de imagens é pré-definido e limitado, apenas a resultados de hardcore perfeitos em seu prog;)
sne11ius

Sim, se eu treinar no conjunto de dados em que vou executar o algoritmo, com certeza vou obter resultados perfeitos :) Mas, por exemplo, para esta tarefa, o programa foi testado pelo professor no final em um conjunto de imagens exibidas . Eu gostaria de fazer algo que fosse robusto e não se adequasse aos dados de treinamento.
precisa saber é o seguinte

O número de conjuntos de treinamento varia, porém, você deve tomar cuidado com algumas coisas: não treine demais, provavelmente deseja um conjunto de testes para mostrar como está sua precisão. Além disso, o número de conjuntos de treinamento dependerá do número de camadas que você usará.
19412 Fantástico Sr. Fox

24

Eu detectaria retângulos vermelhos: RGB -> HSV, filtro vermelho -> imagem binária, feche (dilate e corroa, conhecido como imcloseno matlab)

Em seguida, observe os retângulos do maior para o menor. Retângulos que possuem retângulos menores em uma posição / escala conhecida podem ser removidos (assumindo que as proporções do frasco sejam constantes, o retângulo menor seria uma tampa do frasco).

Isso deixaria você com retângulos vermelhos, então você precisará detectar de alguma forma os logotipos para saber se eles são um retângulo vermelho ou uma lata de coca-cola. Como o OCR, mas com um logotipo conhecido?


2
Como isso estava sendo discutido no DSP no curto período em que foi movido, algumas garrafas podem não ter plugues;) ou o plugue pode estar parcialmente oculto.
Charles Menguy

22

Essa pode ser uma idéia muito ingênua (ou pode não funcionar), mas as dimensões de todas as latas de coque são fixas. Assim, se a mesma imagem contiver uma lata e uma garrafa, você poderá diferenciá-las por considerações de tamanho (as garrafas serão maiores). Agora, devido à falta de profundidade (ou seja, mapeamento 3D para mapeamento 2D), é possível que uma garrafa pareça encolhida e não haja diferença de tamanho. Você pode recuperar algumas informações detalhadas usando imagem estéreo e depois recuperar o tamanho original.


3
Na verdade não: não há restrição de tamanho ou orientação (ou orientação, mas eu realmente não lidei com isso), então você pode ter uma garrafa muito longe no fundo e uma lata em primeiro plano, e a lata seria muito maior do que a garrafa.
Charles Menguy

Também verifiquei que a proporção largura / altura é bastante semelhante para garrafa e lata, então isso também não é realmente uma opção.
Charles Menguy

A proporção do rótulo (sendo uma marca comercial) é a mesma. Portanto, se a garrafa (maior) estiver um pouco mais distante na foto, seu tamanho será exatamente o mesmo que o da lata.
Littleadv

3
Para explicar um pouco mais. Suponha que lata esteja em z = 0 e garrafa em z = -100. Como a garrafa está muito atrás, ela parecerá menor. Mas se eu souber que a garrafa está em z = -100 e pode em z = 0, então posso calcular o tamanho esperado da lata / garrafa se ambas forem traduzidas para z = 0. Então agora eles estão na mesma profundidade e, portanto, eu posso tomar decisões com base no tamanho.
Sharad

2
Este é apenas um comentário, não uma resposta, mas está muito mais próximo de ser uma resposta do que o comentário como resposta acima, com 120 votos.
Fattie # 25/17

22

Hmm, acho que estou de acordo com alguma coisa (esta é a pergunta mais interessante de todas - então seria uma pena não continuar tentando encontrar a resposta "perfeita", mesmo que uma resposta aceitável tenha sido encontrada) .. .

Depois de encontrar o logotipo, seus problemas estão pela metade. Então você só precisa descobrir as diferenças entre o que está ao redor do logotipo. Além disso, queremos fazer o mínimo possível. Eu acho que essa é realmente essa parte fácil ...

O que ao redor do logotipo? Para uma lata, podemos ver o metal que, apesar dos efeitos da iluminação, não muda em sua cor básica. Desde que conheçamos o ângulo do rótulo, podemos dizer o que está diretamente acima dele, então estamos vendo a diferença entre eles:

Aqui, o que está acima e abaixo do logotipo é completamente escuro, de cor consistente. Relativamente fácil a esse respeito.

Aqui, o que está acima e abaixo é claro, mas ainda é consistente em cores. É todo prateado, e o metal todo prateado realmente parece muito raro, assim como as cores prateadas em geral. Além disso, ele está em um deslizamento fino e próximo o suficiente do vermelho que já foi identificado, para que você possa traçar sua forma por todo o comprimento para calcular uma porcentagem do que pode ser considerado o anel de metal da lata. Realmente, você só precisa de uma pequena fração disso em qualquer lugar da lata para dizer que faz parte, mas ainda precisa encontrar um equilíbrio que garanta que não seja apenas uma garrafa vazia com algo de metal por trás.

E, finalmente, o mais complicado. Mas não é tão complicado, uma vez que estamos apenas passando pelo que podemos ver diretamente acima (e abaixo) do invólucro vermelho. É transparente, o que significa que mostrará o que está por trás. Isso é bom, porque as coisas que estão por trás dela provavelmente não são tão consistentes em cores quanto o metal circular prateado da lata. Pode haver muitas coisas diferentes por trás dele, o que nos diria que é uma garrafa vazia (ou cheia de líquido claro) ou uma cor consistente, o que pode significar que ela está cheia de líquido ou que a garrafa está simplesmente na frente de uma garrafa. Cor sólida. Estamos trabalhando com o que há de mais próximo à parte superior e inferior, e as chances de as cores certas estarem no lugar certo são relativamente pequenas. Sabemos que é uma garrafa, porque não possui esse elemento visual essencial da lata,

(essa última foi a melhor que pude encontrar de uma garrafa grande de coca-cola vazia - curiosamente, a tampa E o anel são amarelos, indicando que provavelmente não se deve confiar na vermelhidão da tampa)

Na rara circunstância de que uma sombra semelhante de prata esteja atrás da garrafa, mesmo após a abstração do plástico, ou de que a garrafa esteja de alguma forma cheia da mesma sombra de líquido prateado, podemos recorrer ao que podemos estimar aproximadamente como sendo o forma da prata - que como mencionei, é circular e segue a forma da lata. Mas, mesmo que eu não tenha um certo conhecimento em processamento de imagem, isso parece lento. Melhor ainda, por que não deduzir isso verificando uma vez ao redor das laterais do logotipo para garantir que não haja nada da mesma cor prata lá? Ah, mas e se houver o mesmo tom de prata atrás de uma lata? Então, precisamos prestar mais atenção às formas, olhando novamente para a parte superior e inferior da lata.

Dependendo da perfeição de tudo isso, pode ser muito lento, mas acho que meu conceito básico é verificar as coisas mais fáceis e próximas primeiro. Observe as diferenças de cores em torno da forma já combinada (que parece a parte mais trivial disso) antes de se esforçar para descobrir a forma dos outros elementos. Para listar, ele diz:

  • Encontre a atração principal (fundo do logotipo vermelho e, possivelmente, o próprio logotipo para orientação, embora, caso a lata seja recusada, você precise se concentrar apenas no vermelho)
  • Verifique a forma e a orientação, mais uma vez através da vermelhidão muito distinta
  • Verifique as cores ao redor da forma (já que é rápida e indolor)
  • Por fim, se necessário, verifique a forma dessas cores ao redor da atração principal para obter a redondeza correta.

Caso você não possa fazer isso, provavelmente significa que a parte superior e inferior da lata está coberta, e as únicas coisas possíveis que um ser humano poderia ter usado para fazer uma distinção confiável entre a lata e a garrafa são a oclusão e a reflexão da lata, o que seria uma batalha muito mais difícil de processar. No entanto, para ir ainda mais longe, você pode seguir o ângulo da lata / garrafa para verificar se há mais características semelhantes a garrafas, usando as técnicas de digitalização semitransparentes mencionadas nas outras respostas.

Pesadelos adicionais interessantes podem incluir uma lata convenientemente atrás da garrafa, a uma distância tão grande que o metal dela apareça acima e abaixo da etiqueta, o que continuaria a falhar desde que você digitalize por todo o comprimento do vermelho label - o que é realmente mais um problema, porque você não está detectando uma lata onde poderia estar, em vez de considerar que você está realmente detectando uma garrafa, incluindo a lata por acidente. O copo está meio vazio, nesse caso!


Como isenção de responsabilidade, não tenho experiência nem jamais pensei em processamento de imagem fora desta pergunta, mas é tão interessante que me fez pensar profundamente sobre isso e, depois de ler todas as outras respostas, considero que isso pode ser a maneira mais fácil e eficiente de fazer isso. Pessoalmente, eu estou feliz que eu não realmente tem que pensar em programar esta!

EDITAR

desenho ruim de uma lata em tinta MS Além disso, veja este desenho que fiz no MS Paint ... É absolutamente horrível e bastante incompleto, mas com base apenas na forma e nas cores, você pode adivinhar o que provavelmente será. Em essência, essas são as únicas coisas que você precisa se preocupar em procurar. Quando você olha para aquela forma e combinação de cores muito distintas tão próximas, o que mais poderia ser? A parte que não pintei, o fundo branco, deve ser considerada "qualquer coisa inconsistente". Se tivesse um plano de fundo transparente, poderia passar por quase qualquer outra imagem e você ainda poderá vê-la.


10
O tom específico do vermelho é principalmente subjetivo e fortemente influenciado por considerações de iluminação e balanço de branco. Você pode se surpreender com o quanto eles podem mudar. Considere, por exemplo, esta ilusão de xadrez .
Octopus

2
Uma atualização do link que o @Octopus postou: persci.mit.edu/gallery/checkershadow
Hat

Uma ilusão de percepção não afeta o que sua webcam vê - ou seja, o que seu código obtém - apenas como um olho humano ajuda (?) Engana o cérebro.
barny 13/03

17

Não conheço o OpenCV, mas, olhando o problema logicamente, acho que você pode diferenciar entre garrafa e lata alterando a imagem que procura, como a Coca Cola. Você deve incorporar até a parte superior da lata, pois no caso da lata existe um revestimento de prata no topo da coca-cola e, no caso da garrafa, não haverá esse revestimento de prata.

Mas, obviamente, esse algoritmo falhará nos casos em que a parte superior da lata estiver oculta, mas, nesse caso, mesmo os humanos não serão capazes de diferenciar entre os dois (se apenas a parte da coca-cola da garrafa / lata estiver visível)


1
Eu tinha o mesmo pensamento, mas acho que o revestimento prateado em cima da lata muda drasticamente, dependendo do ângulo da lata na foto. Pode ser uma linha reta ou um círculo. Talvez ele pudesse usar os dois como referência?
Alexis Dufrenoy

15

Eu gosto do desafio e queria dar uma resposta, que resolva o problema, eu acho.

  1. Extrair recursos (pontos-chave, descritores como SIFT, SURF) do logotipo
  2. Combine os pontos com uma imagem de modelo do logotipo (usando o Matcher, como Brute Force)
  3. Estimar as coordenadas do corpo rígido (problema PnP - SolvePnP)
  4. Estimar a posição da tampa de acordo com o corpo rígido
  5. Faça retroprojeção e calcule a posição do pixel da imagem (ROI) da tampa da garrafa (presumo que você tenha os parâmetros intrínsecos da câmera)
  6. Verifique com um método se a tampa está lá ou não. Se houver, então esta é a garrafa

A detecção da tampa é outra questão. Pode ser complicado ou simples. Se eu fosse você, simplesmente verificaria o histograma de cores no ROI para uma decisão simples.

Por favor, dê o feedback se eu estiver errado. Obrigado.


13

Estou alguns anos atrasado em responder a essa pergunta. Com o estado da arte levado ao limite pelas CNNs nos últimos 5 anos, eu não usaria o OpenCV para fazer essa tarefa agora! ( Eu sei que você queria especificamente recursos do OpenCv na pergunta ) Sinto que algoritmos de detecção de objetos como RCNNs mais rápidos, YOLO, SSD etc. aceitariam esse problema com uma margem significativa em comparação aos recursos do OpenCV. Se eu resolvesse esse problema agora (após 6 anos !!), definitivamente usaria o Faster-RCNN .


5
A OP disse que havia 30 imagens em alta resolução, o que provavelmente não é o melhor cenário para o treinamento de ConvNets. Não são apenas muito poucos (mesmo aumentados), a parte de alta resolução destruiria ConvNets.
Kostas Mouratidis

11

Gostei da sua pergunta, independentemente de estar fora do tópico ou não: P

Um aparte interessante; Acabei de concluir um assunto em minha graduação em que abordamos robótica e visão computacional. Nosso projeto para o semestre foi incrivelmente semelhante ao que você descreve.

Tivemos que desenvolver um robô que usasse um Xbox Kinect para detectar garrafas e latas de coca-cola em qualquer orientação em uma variedade de condições ambientais e de iluminação. Nossa solução envolveu o uso de um filtro passa-banda no canal Hue em combinação com a transformação de círculo de hough. Conseguimos restringir um pouco o ambiente (pudemos escolher onde e como posicionar o robô e o sensor Kinect); caso contrário, usaríamos as transformações SIFT ou SURF.

Você pode ler sobre a nossa abordagem no meu blog sobre o tema :)


2
Projeto interessante, mas só se aplica à sua configuração muito específica.
Rui Marques

10

Existem vários descritores de cores usados ​​para reconhecer objetos, o artigo abaixo compara muitos deles. Eles são especialmente poderosos quando combinados com SIFT ou SURF. SURF ou SIFT sozinhos não são muito úteis na imagem de uma lata de coca-cola, porque eles não reconhecem muitos pontos de interesse, você precisa das informações de cores para ajudar. Eu uso o BIC (Border / Interior Pixel Classification) com SURF em um projeto e funcionou muito bem para reconhecer objetos.

Descritores de cores para recuperação de imagens na Web: um estudo comparativo


10

Aprendizagem Profunda

Reúna pelo menos algumas centenas de imagens contendo latas de cola, anote a caixa delimitadora em volta delas como classes positivas, inclua garrafas de cola e outros produtos de cola os rotulam de classes negativas e objetos aleatórios.

A menos que você colete um conjunto de dados muito grande, execute o truque de usar os recursos de aprendizado profundo para conjuntos de dados pequenos. Idealmente, usando uma combinação de SVM (Support Vector Machines) com redes neurais profundas.

Depois de alimentar as imagens com um modelo de aprendizado profundo previamente treinado (por exemplo, GoogleNet), em vez de usar a camada de decisão (final) da rede neural para fazer classificações, use os dados das camadas anteriores como recursos para treinar seu classificador.

OpenCV e Google Net: http://docs.opencv.org/trunk/d5/de7/tutorial_dnn_googlenet.html

OpenCV e SVM: http://docs.opencv.org/2.4/doc/tutorials/ml/introduction_to_svm/introduction_to_svm.html


9

Você precisa de um programa que aprenda e melhore a precisão da classificação organicamente a partir da experiência.

Sugiro aprendizado profundo, com o aprendizado profundo isso se torna um problema trivial.

Você pode treinar novamente o modelo de iniciação v3 no Tensorflow:

Como treinar novamente a camada final do Inception para novas categorias .

Nesse caso, você estará treinando uma rede neural convolucional para classificar um objeto como uma coca-cola pode ou não.


2
Cachorro-quente ou não-cachorro-quente?
YellowPillow

6

Como alternativa a todas essas boas soluções, você pode treinar seu próprio classificador e tornar seu aplicativo robusto a erros. Como exemplo, você pode usar o Haar Training , fornecendo um bom número de imagens positivas e negativas do seu alvo.

Pode ser útil extrair apenas latas e pode ser combinado com a detecção de objetos transparentes.


3

Existe um pacote de visão computacional chamado HALCON do MVTec cujas demos podem fornecer boas idéias de algoritmos. Existem muitos exemplos semelhantes ao seu problema que você pode executar no modo de demonstração e, em seguida, examinar os operadores no código e ver como implementá-los a partir de operadores OpenCV existentes.

Eu usei este pacote para prototipar rapidamente algoritmos complexos para problemas como esse e depois descobrir como implementá-los usando os recursos OpenCV existentes. Em particular no seu caso, você pode tentar implementar no OpenCV a funcionalidade incorporada no operador find_scaled_shape_model . Alguns operadores apontam para o artigo científico sobre implementação de algoritmos, que pode ajudar a descobrir como fazer algo semelhante no OpenCV. Espero que isto ajude...


0

Se você estiver interessado em que seja em tempo real, o que você precisa é adicionar um filtro de pré-processamento para determinar o que é verificado com o material pesado. Um bom filtro de pré-processamento rápido, em tempo real, que permitirá que você escaneie coisas com maior probabilidade de ser uma coca-cola do que não antes de passar para coisas mais duvidosas é algo como isto: pesquise na imagem os maiores patches de cores que estão a uma certa tolerância da sqrt(pow(red,2) + pow(blue,2) + pow(green,2))lata de coca-cola. Comece com uma tolerância de cores muito rigorosa e trabalhe até tolerâncias de cores mais brandas. Então, quando seu robô fica sem tempo para processar o quadro atual, ele usa os frascos encontrados atualmente para seus propósitos. Observe que você precisará ajustar as cores RGB sqrt(pow(red,2) + pow(blue,2) + pow(green,2))para obtê-las corretamente.

Além disso, isso parece realmente idiota, mas você -oFastativou as otimizações do compilador ao compilar seu código C?


0

Talvez muitos anos atrasado, mas ainda assim uma teoria para tentar.

A proporção do retângulo delimitador da região vermelha do logotipo e a dimensão geral da garrafa / lata é diferente. No caso do Can, deve ser 1: 1, ao passo que será diferente no do frasco (com ou sem tampa). Isso deve facilitar a distinção entre os dois.

Atualização: a curvatura horizontal da região do logotipo será diferente entre a lata e a garrafa devido à respectiva diferença de tamanho. Isso pode ser especialmente útil se o seu robô precisar pegar a lata / garrafa e você decidir a aderência de acordo.


-1

As primeiras coisas que eu procuraria são as cores - como o VERMELHO, ao fazer a detecção de olhos vermelhos em uma imagem - há um certo intervalo de cores a ser detectado, algumas características a respeito da área circundante e distância como o outro olho. é realmente visível na imagem.

1: A primeira característica é a cor e o vermelho é muito dominante. Depois de detectar o Coca Cola Red, existem vários itens de interesse 1A: Qual é o tamanho dessa área vermelha (é suficiente para determinar uma lata verdadeira ou não - 10 pixels provavelmente não é suficiente), 1B: contém a cor da etiqueta - "Coca-Cola" ou onda. 1B1: Existe o suficiente para considerar uma alta probabilidade de que seja um rótulo.

O item 1 é uma espécie de atalho - pré-processo, se esse ranho existir na imagem - seguir em frente.

Portanto, se for esse o caso, posso utilizar esse segmento da minha imagem e começar a olhar um pouco mais para fora da área em questão - basicamente, observe a região / bordas circundantes ...

2: Dada a área da imagem acima identificada em 1 - verifique os pontos adjacentes [arestas] do item em questão. A: Existe o que parece ser uma lata na parte superior ou inferior - prata? B: Uma garrafa pode parecer transparente, mas também uma mesa de vidro - existe uma mesa / prateleira de vidro ou uma área transparente - se houver, existem várias saídas possíveis. Uma garrafa PODE ter uma tampa vermelha, pode não ter, mas deve ter o formato dos parafusos da parte superior da garrafa / linha ou uma tampa. C: Mesmo que isso falhe em A e B, ainda assim pode ser uma lata - parcial. Isso é mais complexo quando é parcial porque uma lata parcial de garrafa / parcial pode ter a mesma aparência; portanto, mais processamento de medição da borda da região vermelha até a borda .. pequena garrafa pode ser semelhante em tamanho ..

3: Após a análise acima, é quando eu olhava as letras e o logotipo da onda - porque posso orientar minha pesquisa por algumas letras nas palavras Como você pode não ter todo o texto devido à falta de todo o texto possível, a onda se alinharia em certos pontos ao texto (distância), para que eu pudesse procurar essa probabilidade e saber quais letras deveriam existir naquele ponto da onda na distância x.


-9

Este é um projeto antigo em que trabalhei. As imagens MAP são muito fáceis de usar com javascript. Eu ofereço a você o objeto, você o lê e sabe como usá-lo. Não precisamos do JQuery e outros sistemas para usar imagens MAP.

    //Copyright Cherif yahiaoui, by ELEBAN.FR

//variables de flottement.
var myInstOne = null;
var globalize = null;

var eleban_preload_images = function (name, imgs, url){
try{
    var oThis = this;
    this.images = new Array();
    this.imageshover = new Array();
    this.imagesNames = new Array(imgs.split(";"));


        for(var i=0; i < this.imagesNames[0].length; i++){
            this.images[i] = new Image();
            this.imageshover[i] = new Image();
        }

    this.url = url;

    this.GetAbsoluteurl = function () {

    var img = new Image(); img.src = url;
    url = img.src; img = null; 
        this.url = url; 

    };

    this.Preload = function () {

        for(var i=0; i < this.imagesNames[0].length; i++){
            this.images[i].src = this.url+("btn-"+this.imagesNames[0][i]+".png");
            this.imageshover[i].src = this.url+("btn-"+this.imagesNames[0][i]+"-hover.png");
        }

    };
    this.GetAbsoluteurl();
    this.Preload();
}
finally {return;}
}

var g_preloaderhover = new eleban_preload_images("loaderhover","menu;malette;reservation;cabine;facebook;map;amis","./images/");


//variable arret flottement
var g_stopflo = false;

var myObjfloater = function(name, idname, itop, differ ) {
var oThis = this; // création d'une référence vers l'objet courant
this.name = name;
this.id =idname;
this.xstep= 0.3;
this.itime = 30;
this.obj = null;
this.y = itop;
this.yadd = 0;
this.up = true;
this.pause = false;
this.differ = differ;
this.coordsimage = null;
this.objimg = null;
this.initimages = false;
this.compteur = 0;
this.over = false;
this.timeoutstop = null;
try{
this.initimage = function(){
var img = this.obj.getElementsByTagName('img')[0];
this.coordsimage = new Array(img.width, img.height);
this.objimg = img;
this.initimages = true;
};


this.myMethod = function() {
if(!g_stopflo){
    if(this.differ != 0){ 
this.differ=this.differ-0.1; 
}else{

if(this.obj){
if(this.over == false){
    this.yadd=this.yadd+0.1; this.itime = this.itime + 10;
this.obj.style.visibility = "hidden";
this.y = ((this.up)? this.y - this.yadd : this.y + this.yadd);
this.obj.style.marginTop = this.y +"%" ;
this.obj.style.visibility = "visible";

if (this.yadd > this.xstep){ 
    this.up = (this.up)? false : true;
    this.yadd = -0.1; this.itime=180;
}
}
}else{
    if (document){
        if(document.getElementById) {
         this.obj = document.getElementById(this.id); 
        //this.y = this.obj.offsetTop;
        }else{
        if(document.getElementByTagName) { this.obj = document.getElementByTagName(this.id); this.y = this.obj.offsetTop;}
        }

    }
}
}
this.timeoutstop=setTimeout(function() { oThis.myMethod(); }, this.itime);
}    
};

this.callDelayed = function() {
    // utilisation de la référence vers l'objet
if(!g_stopflo){
    this.timeoutstop=setTimeout(function() { oThis.myMethod(); }, this.itime);
}
};
}
finally {return;}
};

// special creation des zones AREA
function eleban_createallarea(){
try{
var measur = new Array("w", "h");
measur["w"] = new Array(330,570,185,300,115,390,225);
measur["h"] = new Array(460,570,295,450,100,190,115);
var ititle = new Array("Voir les menus  et nos suggestions","Repas &agrave; emporter","R&eacute;servation d&rsquo;une table","Nous contacter","Nous rejoindre sur FaceBook","Calculer votre trajet","liste des amis");
var ihref = new Array("menus.html","emporter.html","reservation.html","contact.html","likebox.html","google.html","amis.html");
var b_map = new Array(0,1,2,3,4,5,6);
b_map[0] = "71,32,240,32,249,43,289,352,280,366,102,385,90,371,51,38";
b_map[1] = "66,52,95,14,129,56,115,91,100,93,112,273,128,284,122,366,176,343,193,296,191,194,147,189,145,166,201,111,199,84,545,105,532,354,509,388,412,478,32,401,77,383,87,375,82,286,95,269,94,221,24,195,11,165,9,120,89,123,89,94,78,92,77,92,77,93,75,93,77,93,76,93,79,92";
b_map[2] = "19,25,169,38,173,112,161,113,105,103,90,125,91,262,121,269,124,281,96,293,62,289,49,281,56,268,83,264,84,121,71,98,16,90";
b_map[3] = "60,0,216,1,226,20,225,403,168,421,42,410,45,10";
b_map[4] = "31,7,72,10,82,18,88,45,88,71,76,81,29,80,17,68,16,18";
b_map[5] = "91,40,141,38,178,27,184,4,211,5,223,24,240,23,386,135,229,121,103,180,6,156,49,94";
b_map[6] = "6,32,69,18,79,6,118,7,141,2,149,10,211,17,202,28,209,30,189,62,195,70,178,74,180,90,164,90,154,107,68,101,34,104,34,98,18,97,28,84,15,84,30,65";

if (document.getElementById){
for (var i=0; i<b_map.length;i++){
var obj = document.getElementById("pc_menu"+i);
    if(obj){
    var ct = '<img class=\"pc_menu\" src=\"'+g_preloaderhover.images[i].src+'\" alt=\"\" width=\"'+measur["w"][i]+'\" height=\"'+measur["h"][i]+'\" usemap=\"#MAP_INDEX'+i+'\" \/>';
    ct+='<map name=\"MAP_INDEX'+i+'\">';
    ct+='<area shape=\"poly\" coords=\"'+b_map[i]+'\" title=\"'+ititle[i]+'\" href=\"'+ihref[i]+'\" \/>';
    ct+='<\/map>';
    obj.innerHTML = ct;
    }
}
}
}
finally {return;}
}

//preload, creation et gestion de tous les evenements


var image_resizer = function(g_layer){


    b_org_elm = new Array("w",  "h");
    b_org_elm["w"] = new Array(330,570,185,300,115,390,225);
    b_org_elm["h"] = new Array(460,570,295,450,100,190,115);

    b_map = new Array(0,1,2,3,4,5,6);
    b_map[0] = new Array(71,32,240,32,249,43,289,352,280,366,102,385,90,371,51,38);
    b_map[1] = new Array(66,52,95,14,129,56,115,91,100,93,112,273,128,284,122,366,176,343,193,296,191,194,147,189,145,166,201,111,199,84,545,105,532,354,509,388,412,478,32,401,77,383,87,375,82,286,95,269,94,221,24,195,11,165,9,120,89,123,89,94,78,92,77,92,77,93,75,93,77,93,76,93,79,92);
    b_map[2] = new Array(19,25,169,38,173,112,161,113,105,103,90,125,91,262,121,269,124,281,96,293,62,289,49,281,56,268,83,264,84,121,71,98,16,90);
    b_map[3] = new Array(60,0,216,1,226,20,225,403,168,421,42,410,45,10);
    b_map[4] = new Array(31,6,70,10,78,18,84,23,88,44,88,70,78,80,75,81,33,82,23,76,18,69,16,22,21,13);
    b_map[5] = new Array(91,40,141,38,178,27,184,4,211,5,223,24,240,23,386,135,229,121,103,180,6,156,49,94);
    b_map[6] = new Array(6,32,69,18,79,6,118,7,141,2,149,10,211,17,202,28,209,30,189,62,195,70,178,74,180,90,164,90,154,107,68,101,34,104,34,98,18,97,28,84,15,84,30,65);


    b_layer = g_layer;

//gere mouseover
    this.mouseover = function(e){
        if (!e) var e = window.event;
        var tg = (window.event) ? e.srcElement : e.target
            if (tg.nodeName){
                if(tg.nodeName == "AREA"){
                var divpar = (tg.parentNode)? tg.parentNode.parentNode : tg.parentElement.parentElement;
                    if (divpar){
                        if(divpar.nodeName == "DIV"){
                            var iiobjimg = divpar.getElementsByTagName('img');
                                if (iiobjimg){
                                    ii = parseInt(divpar.id.substring(divpar.id.length-1,divpar.id.length));
                                    iiobjimg[0].src = g_preloaderhover.imageshover[ii].src;
                                }
                        }
                    }
                }
            }
    };

//gere mouseout
    this.mouseout = function(e){
        if (!e) var e = window.event;
        tg = (window.event) ? e.srcElement : e.target
            if (tg.nodeName){
                if(tg.nodeName == "AREA"){
                divpar = (tg.parentNode)? tg.parentNode.parentNode : tg.parentElement.parentElement;
                    if (divpar){
                        if(divpar.nodeName == "DIV"){
                            var iiobjimg = divpar.getElementsByTagName('img');
                                if (iiobjimg){
                                    ii = parseInt(divpar.id.substring(divpar.id.length-1,divpar.id.length));
                                    iiobjimg[0].src = g_preloaderhover.images[ii].src;
                                }
                        }
                    }
                }
            }
    };

//ajout evenements entree sortie à la page web lors du chargement de la page
    this.init = function () {

        for(var i=0; i<b_org_elm["w"].length;i++){
            w = document.getElementById("pc_menu"+i).offsetWidth;
            h = document.getElementById("pc_menu"+i).offsetHeight;

            xa = w/parseFloat(b_org_elm["w"][i]);
            ya = h/parseFloat(b_org_elm["h"][i]);

            area = document.getElementById("pc_menu"+i).getElementsByTagName('area')[0];

            b_map2 = area.coords.split(",");
            yswitch = true;
                for(m=0; m<b_map2.length;m++){
                b_map2[m] = Math.round(parseFloat(b_map[i][m]) * ((yswitch)? xa: ya));
                yswitch = (yswitch)? false :  true;
                }
            area.coords = b_map2.join(',');
        }
    }; 


    this.resize = function () {
    clearTimeout(myInstOne.timeoutstop);
    g_stopflo=true;

    globalize.init();
    g_stopflo=false;
    myInstOne.obj = null;
    myInstOne.callDelayed();
    };


    nar = document.getElementsByTagName('area').length;

        for(var i=0; i<nar;i++){
            var elem = document.getElementsByTagName('area')[i];
            if (elem.addEventListener){
                    elem.addEventListener("onmouseover",this.mouseover,true);
                elem.addEventListener("onmouseout",this.mouseout,true);
            }else if (elem.attachEvent) {
                    elem.attachEvent("onmouseover", this.mouseover);
                    elem.attachEvent("onmouseout", this.mouseout);
            }else{
                    elem["onmouseover"] = this.mouseover;
                    elem["onmouseout"] = this.mouseout;
            }
        }

            window.onresize = this.resize;
        window.onmouseover = this.mouseover;
        window.onmouseout = this.mouseout;
}


//permet de temporiser et éviter les erreurs de chargement des objets
function temporise_Init(Lastdiv){
if(document.getElementById){
    if(document.getElementById(Lastdiv)){

    eleban_createallarea();

    myInstOne = new myObjfloater('b_menumap11', 'pc_menu1', 1, 0);

    globalize = new image_resizer(document.getElementById('pc_redim'));
    globalize.init();
        globalize.resize();



    }else{
    setTimeout(temporise_Init(Lastdiv), 30);
    }
}
}


window.onload = function () {
temporise_Init("pc_bandeau");
}

3
o que isso faz?
User8408080 13/03
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.