4_9_5_Estratificação de contorno - Documentação oficial chinesa do OpenCV
contente
Representação hierárquica no OpenCV
1. RETR_LIST
Esta é a mais simples das quatro bandeiras (do ponto de vista da interpretação). Ele apenas recupera todos os contornos, mas não cria nenhum relacionamento pai-filho. Sob esta regra, os contornos pai e filho são iguais, são apenas contornos . Todos pertencem ao mesmo nível.
2. RETR_EXTERNAL Se este sinalizador for usado, ele retornará apenas o sinalizador externo extremo. Todas as silhuetas infantis são deixadas para trás. Podemos dizer que de acordo com essa regra, apenas o filho mais velho de cada família recebe atenção. Não se importa com o resto da família :) .
3. RETR_CCOMP Este sinalizador recupera todos os contornos e os organiza em uma hierarquia de 2 níveis. O contorno externo do objeto (ou seja, o limite do objeto) é colocado na hierarquia-1. O contorno do buraco dentro do objeto (se houver) é colocado na hierarquia-2.
4. RETR_TREE: Recupera todos os contornos e cria uma lista completa de hierarquia de famílias. Até conta, quem é o avô, pai, filho, neto e muito mais... :).
teoria
Diversas funções relacionadas aos contornos fornecidos pelo OpenCV foram discutidas anteriormente. Mas quando usamos a função **cv.findcontour**() para encontrar o contorno na imagem, passamos um parâmetro, o modo de recuperação de contorno . Geralmente passamos **cv.RETR_LIST ** ou **cv.RETR_TREE ** , que funciona bem. Mas o que exatamente isso significa?
Na saída, temos três arrays,
- A primeira é a imagem,
- O segundo é o esboço,
- Há também uma saída que chamamos de **hierarquia** (verifique o código no artigo anterior).
Mas nunca usamos essa hierarquia em nenhum lugar. Então, o que é essa hierarquia? Para que é usada? Como ela se relaciona com os parâmetros da função acima mencionados?É isso que vamos discutir neste artigo.
Qual é a hierarquia?
- Normalmente usamos a função **cv.findcontour**() para detectar objetos na imagem, às vezes os objetos estão em posições diferentes.
- Mas em alguns casos algumas formas estão dentro de outras formas . Assim como gráficos aninhados. Nesse caso, chame a externa de **classe pai** e a interna de **subclasse** . Desta forma, os contornos na imagem têm uma certa relação entre si.
- Você pode especificar como um contorno é conectado entre si, por exemplo, se é um contorno filho de outro contorno, um contorno pai, etc. A representação dessa relação é chamada de ** hierarquia **.
Abaixo segue um exemplo:
Nesta foto, há algumas formas que numerei de **0-5**. *2* e *2a* representam os contornos externo e interno da caixa mais externa .
- Os contornos 0,1,2 são **externos ou externos**. Podemos dizer que estão no **nível-0**, ou simplesmente, estão no **mesmo nível**.
- O próximo é **contorno-2a**. Ele pode ser considerado um filho do contorno-2 (ou, inversamente, o contorno-2 é um pai do contorno-2a). Digamos que esteja no **nível 1**.
- Da mesma forma, contour-3 é filho de contour-2, que está na próxima hierarquia.
- Finalmente, os contornos 4,5 são filhos do contorno-3a, estão no último nível. Pela numeração das caixas, acho que o contorno-4 é o primeiro filho do contorno-3a (também poderia ser o contorno-5).
Menciono estes para entender alguns termos como ** mesmo nível **, contorno externo , contorno filho , contorno pai , **primeiro contorno filho**, etc. Agora vamos entrar no OpenCV.
Representação hierárquica no OpenCV
Portanto, cada perfil tem suas próprias informações sobre o nível, quem é seu filho, quem é seu pai, etc.
O OpenCV o representa como um array com quatro valores:
[Next, Previous, First_Child, Parent]
"Próximo representa o próximo contorno no mesmo nível."
Por exemplo, pegue o contorno-0 em nossa imagem. Quem é o próximo contorno no mesmo nível? Este é o contorno-1. basta encomendar
Next = 1
. Da mesma forma, Contour-1 também é contorno-2. Então.Next = 2
_ E quanto ao contorno 2? Não há próxima linha de contorno na mesma linha horizontal. Simplesmente, deixeNext = -1
. E o contorno 4? Está no mesmo nível do contorno 5. Seu próximo contorno é o contour-5, entãonext = 5
." Anterior representa um contorno anterior no mesmo nível."
O mesmo que acima. O contorno antes do contorno-1 é o contorno-0 no mesmo nível. Da mesma forma, o contorno-2 também é o contorno-1. Para contour-0, não há item anterior, portanto, é definido como -1.
"First_Child representa seu primeiro contorno filho."
Nenhuma explicação é necessária. Para contorno-2, a criança é contorno-2a. Assim, obtém-se o valor do índice correspondente ao contorno-2a. E o contorno 3a? Ele tem dois filhos. Mas focamos apenas no primeiro filho. É contorno-4. Então
First_Child = 4
para contorno-3a."Parent representa o índice de seu contorno pai."
É o oposto de **First_Child**. Para contorno-4 e contorno-5, o contorno pai é contorno-3a. Para o contorno 3a, é o contorno 3 e assim por diante.
Observe que este campo é tratado como -1 se não houver elementos filho ou pai
Agora que entendemos os estilos hierárquicos usados no OpenCV, podemos verificar o modo de recuperação de contorno no OpenCV com a ajuda da mesma imagem fornecida acima. O significado de alguns sinalizadores como cv.RETR_LIST , cv.RETR_TREE , cv.RETR_CCOMP , **cv.RETR_EXTERNAL** e assim por diante.
Modo de pesquisa de contorno
1. RETR_LIST
Esta é a mais simples das quatro bandeiras (do ponto de vista da interpretação).
- Ele apenas recupera todos os contornos, mas não cria nenhum relacionamento pai-filho.
- Sob esta regra, os contornos pai e filho são iguais, são apenas contornos . Todos pertencem ao mesmo nível.
Aqui, o 3º e o 4º itens são sempre -1. Mas obviamente, o próximo item e o item anterior têm valores correspondentes. Basta verificar você mesmo.
Abaixo está o resultado que obtive, cada linha é o nível de detalhe para o contorno correspondente. Por exemplo, a primeira linha corresponde ao contorno 0. O próximo contorno é o contorno 1. Então.
Next = 1
_ Não há contorno anterior, entãoPrevious=-1
. Os dois restantes, como mencionado, são-1
.>>> hierarchy array([[[ 1, -1, -1, -1], [ 2, 0, -1, -1], [ 3, 1, -1, -1], [ 4, 2, -1, -1], [ 5, 3, -1, -1], [ 6, 4, -1, -1], [ 7, 5, -1, -1], [-1, 6, -1, -1]]])
Essa é a melhor opção para usar em seu código se você não estiver usando nenhum recurso de hierarquia.
2. RETR_ EXTERNO
Se este sinalizador for usado, ele retornará apenas o sinalizador externo extremo. Todas as silhuetas infantis são deixadas para trás. Podemos dizer que de acordo com essa regra, apenas o filho mais velho de cada família recebe atenção. Não se importa com o resto da família :) .
Então, na nossa imagem, quantos contornos externos extremos existem? No nível 0? Existem 3, ou seja, o contorno é 0 1 2, certo? Agora tente encontrar o contorno com este sinalizador. Aqui, dê a cada elemento o mesmo valor acima. e comparado com os resultados acima. Aqui está o que eu recebo:
Você pode usar este sinalizador se quiser apenas extrair contornos externos. Pode ser útil em alguns casos.>>> hierarchy array([[[ 1, -1, -1, -1], [ 2, 0, -1, -1], [-1, 1, -1, -1]]])
3. RETR_CCOMP
Este sinalizador recupera todos os contornos e os organiza em uma hierarquia de 2 níveis.
- O contorno externo do objeto (ou seja, o limite do objeto) é colocado na hierarquia-1.
- O contorno do buraco dentro do objeto (se houver) é colocado na hierarquia-2.
Se houver algum objeto nele, seu contorno só é reposicionado na hierarquia 1. e suas vulnerabilidades na Camada 2 e assim por diante.
Basta considerar uma imagem "zero branco" em um fundo preto. O círculo externo de zero pertence ao primeiro nível e o círculo interno de zero pertence ao segundo nível.
Podemos explicá-lo com uma imagem simples. Aqui marquei a ordem dos contornos e as camadas a que pertencem em vermelho e em verde (1 ou 2), na mesma ordem em que o OpenCV detecta os contornos.
Considere o primeiro contorno, que é o contorno-0. Esta é a hierarquia-1. Possui dois furos, Contornos 1 e 2, que pertencem ao segundo nível. Assim, para o contorno-0, o próximo contorno no mesmo nível é o contorno-3. Nem anterior. Na hierarquia-2, seu primeiro filho é o contorno-1. Ele não tem classe pai porque está na hierarquia-1. Portanto, sua matriz hierárquica é
[3,-1,1,-1]
Agora contorno-1. Está no nível 2. O próximo na mesma hierarquia (sob o pai do contorno-1) é o contorno-2. Não há anterior. Não
child
, masparent
contorno-0. Então a matriz é[2,-1,-1,0]
Similar contorno-2: está na hierarquia-2. Sob o contorno-0, não há próximo contorno na mesma hierarquia. Então não
Next
.previous
é contorno-1. Nãochild
,parent
é contorno0. Então a matriz é[-1,1,-1,0]
contorno-3: Ao lado do nível-1 está o contorno-5. Costumava ser contorno-0.
child
é contorno4, nãoparent
. Então a matriz é[5,0,4,-1]
contorno-4: Está na hierarquia 2 sob o contorno-3, não tem irmãos. Não
next
, nãoprevious
, nãochild
,parent
é contorno-3. Então a matriz é[-1,-1,-1,3]
Você pode adicionar o resto. Aqui está a resposta final que obtive:
>>> hierarchy array([[[ 3, -1, 1, -1], [ 2, -1, -1, 0], [-1, 1, -1, 0], [ 5, 0, 4, -1], [-1, -1, -1, 3], [ 7, 3, 6, -1], [-1, -1, -1, 5], [ 8, 5, -1, -1], [-1, 7, -1, -1]]])
4. RETR_TREE
Ele recupera todos os contornos e cria uma lista completa de hierarquia de família. Até conta, quem é o avô, pai, filho, neto e muito mais... :).
Por exemplo, tirei a foto acima e reescrevi o código para cv. RETR_TREE, reordene os contornos e analise-os de acordo com os resultados fornecidos pelo OpenCV. Novamente, as letras vermelhas indicam o número de contornos e as letras verdes indicam a ordem de hierarquia.
Pegue
contour-0
: estáhierarchy-0
dentro. O contorno da mesma hierarquianext
é o contorno-7. nenhumaprevious
silhueta.child
é contorno-1, nãoparent
. Então a matriz é[7,-1,1,-1]
Tomemos por
contour-2
exemplo: está emhierarchy-1
. Nenhum contorno está no mesmo nível.previous
Nº _child
Simcontour-3
. Os pais sãocontour-1
. Então a matriz é[-1,-1,3,1]
De resto, experimente você mesmo. Aqui está a resposta completa:
>>> hierarchy array([[[ 7, -1, 1, -1], [-1, -1, 2, 0], [-1, -1, 3, 1], [-1, -1, 4, 2], [-1, -1, 5, 3], [ 6, -1, -1, 4], [-1, 5, -1, 4], [ 8, 0, -1, -1], [-1, 7, -1, -1]]])