Como ver reverberação ou transmissão de vídeo pelo som através da água - 2

Olá querida!



Hoje, novamente transmitiremos a imagem com ultra-som através da água: literalmente veremos reverberação e eco, e até mesmo como eles mudam dependendo das condições. Tudo o que vou lhe dizer é simples, é interessante repetir eu mesmo e pode ser feito por quase qualquer pessoa.

Se algo está vibrando em sua alma com essas palavras, bem-vindo a Kat, nas águas escuras de nossa lagoa!




"O melhor descanso é interpretar verdades conhecidas." (C) ABS, meio-dia, século XXII


Preliminares


A regra básica do clube de testemunhas de hidroacústica é que o vídeo usando hidroacústica a uma distância mais ou menos significativa (mais de alguns metros) no corpo de água do meio não pode ser transmitido e sempre será impossível.
Existem sérias razões para isso - um canal de comunicação com largura de banda muito baixa, baixa velocidade de propagação do sinal (na água, apenas 1.500 m / s) e alta probabilidade de erro. A banda de frequência disponível é de apenas algumas dezenas de quilohertz.
Mas isso não é tudo - se, relativamente falando, um sinal em frequências da ordem de 10 kHz se propaga na água a uma distância de cerca de 8 a 10 km, então a uma frequência de 20 kHz já é de 3-5 km, e quanto maior a frequência, maior a atenuação. . Por exemplo, nossos menores modems uWAVE do mundo operam na faixa de 20 a 30 kHz e transmitem dados a uma velocidade de 78 bits / s por 1000 metros, e o RedLINE com uma faixa de 5-15 a 8000 metros. O recorde entre dispositivos comerciais pertence à EvoLogics - 68 kBits por 300 metros.
A física, infelizmente, não pode ser enganada e é impossível concordar com ela - pode ser transmitida muito lentamente e imune a ruídos, ou rapidamente, mas por curtas distâncias.
No entanto, em alguns casos, é possível "cortar alguns cantos", que cantos que cortaremos desta vez são mais baixos.

O que faremos hoje e o que é necessário para isso?


Nos artigos anteriores, já transmitimos “vídeo” com som através da água , lembro que ali o quadro foi “desenhado no espectro”, ou seja, o espectro, ou melhor, o espectrograma do sinal era uma imagem.
Mais tarde, criamos antenas hidroacústicas simples a partir do lixo e fizemos o modem hidroacústico mais simples . Também fizemos um pré-amplificador para a antena (o design do PCB para autoprodução por LUT-ohm ainda está aqui ).

Pensamos: de que outra forma você pode tentar transmitir a imagem para que até mesmo um aluno do jardim de infância possa descobrir isso e, ao que parece, eles vieram com uma maneira ainda mais simples do que antes.

Então, para resumir, elabore uma lista do que precisamos:

- um par de antenas de sonar de catadores
- pré - amplificador fabricado pela LUT
- código fonte do projeto C #
- um par de baterias de chumbo a 12 volts
- um amplificador no TDA, tomei um por apenas 50 rublos no Ali

Pouco de teoria


Lembre-se de que nosso modem de sonar foi baseado em um detector de tons simples, cuja frequência é 4 vezes menor que a frequência de amostragem. Lembre-se brevemente de como funciona.


A figura mostra duas oscilações deslocadas uma em relação à outra no Pi / 2 - ou seja, as fases seno e cosseno. E se a frequência é exatamente quatro vezes menor que a frequência de amostragem, apenas 4 amostras caem no período.
Um habuchitel atento certamente notou que os dois sinais são transferidos para Pi / 4. Com essa mudança, o sinal recebe apenas dois valores: √2 / 2 e -√2 / 2.
E valores específicos nem sequer são importantes, é importante que você possa usar apenas os sinais: "+" e "-".

Agora podemos representar a fase senoidal como uma sequência de sinais "+" "+" "-" "-" e a fase cosseno como "+" "-" "-" "+".

Sob o spoiler, repita o detector:
Deixe o sinal de entrada estar no buffer sn, temos dois buffers de média de anel para as fases seno e cosseno - bs e bc do tamanho N. Eles têm indicadores comuns de cabeça e cauda - bH e bT. No momento inicial do tempo, bH = N-1, bT = 0. Contador médio do ciclo C = 0.
Tomamos 4 amostras do buffer de entrada e as adicionamos de acordo com as seqüências de caracteres.

a = sn(i)
bs(bH) = a
bc(bH) = a
s1 = s1 + a - bs(bT)
s2 = s2 + a - bc(bT)
bH = (bH + 1) % N
bT = (bT + 1) % N

a = sn(i+1)
bs(bH) = a
bc(bH) = -a
s1 = s1 + a - bs(bT)
s2 = s2 - a - bc(bT)
bH = (bH + 1) % N
bT = (bT + 1) % N

a = sn(i+2)
bs(bH) = -a
bc(bH) = -a
s1 = s1 - a - bs(bT)
s2 = s2 - a - bc(bT)
bH = (bH + 1) % N
bT = (bT + 1) % N

a = sn(i+3)
bs(bH) = -a
bc(bH) = a
s1 = s1 - a - bs(bT)
s2 = s2 + a - bc(bT)
bH = (bH + 1) % N
bT = (bT + 1) % N


Após cada quatro amostras processadas, verificamos o contador dos ciclos médios e, se excedeu N, calculamos a amplitude cA da transportadora:

if ++cycle >= N
cA = sqrt(s1 * s1 + s2 * s2)
cycle = 0
end



Tomamos esse método como base, ele será responsável pela “sincronização”.
Agora vamos ver como a imagem é codificada. Sugiro usar manipulação de amplitude . Manipulação é quando um sinal é dividido em segmentos iguais chamados chips ou símbolos, e algum parâmetro variável (no nosso caso, a amplitude) é armazenado ao longo do comprimento do chip.
Se, por exemplo, podemos variar a amplitude no intervalo de 0 a 32767 (amostras de 16 bits) e precisamos transmitir 255 valores do brilho dos pixels, por unidade de mudança no brilho do pixel, a amplitude do chip mudará para 32768/255 = 128.
Outro parâmetro importante é o comprimento do chip, começamos com um período de transportadora - quatro amostras no nosso caso.
Portanto, a imagem será transmitida pixel por pixel, cada pixel dura 4 amostras e a amplitude desse período será b [x, y] * 128, onde b [x, y] é o valor de brilho do pixel com as coordenadas xey na imagem b.

Vamos estimar qual será a velocidade de transmissão.
No exemplo, usei um tamanho de quadro de 120x120 pixels. Isso significa que, para transferir um quadro, precisamos

120x120x4 = 57600 amostras,

Se a frequência de amostragem for 96 kHz, a transmissão de um quadro levará tempo:

57600/96000 = 0,6 segundos

Obviamente, precisamos de algum tipo de pausa, um certo intervalo de guarda, para que o detector possa determinar o início do próximo quadro. Por razões humanas, suponha que 0,1 segundos é suficiente para nós, durante o qual todos os ecos desaparecem (na verdade não). Então, no final, a taxa de transferência será:

1 / (0,6 + 0,1) = 1.428 quadros por segundo.

É muito fácil cometer um erro aqui e tentar calcular a velocidade em bits por segundo. Veja como a velocidade de transmissão é incrível:

120 * 120 * 8 / 1.428 = 80627 bps

Mas o que acontece se eu não tiver pixels de 8 bits, mas os de 16 bits?

120 * 120 * 16 / 1.428 = 161344 bps

O problema aqui é que, novamente, esse método de transmissão não pode ser chamado de digital, e o conceito de taxa de bits não é totalmente válido para ele.
Tente calcular a taxa de bits para um sinal de televisão analógica. E para o receptor detector? :)

Assim, por exemplo, uma parte do sinal será semelhante, transmitindo o brilho de 10 pixels, cujos valores mudam alternadamente: 1 2 1 2 1 2 1 2 1 2


Agora vamos ver como isso funciona no exemplo. Os métodos Encode e Decode vivem na classe Encoder e são responsáveis ​​por modular e desmodular a imagem:

 public double[] Encode(Bitmap source, double carrier, int pSize, int interframePauseMs) { Bitmap frame; if (source.PixelFormat != System.Drawing.Imaging.PixelFormat.Format8bppIndexed) frame = Grayscale.CommonAlgorithms.RMY.Apply(source); else frame = source; if (!frame.Size.Equals(frameSize)) frame = resizer.Apply(frame); int cols = frameSize.Width; int rows = frameSize.Height; int col = 0; int row = 0; double delta = Math.PI * 2 * carrier / sampleRate; double alpha = 0; double phase = 0; double pxAmplitude = 0; double chipLimit = Math.PI * 2 * chipSize; double pLimit = Math.PI * 2; List<double> samples = new List<double>(); bool isFinished = false; for (int i = 0; i < pSize; i++) { alpha = Math.Sin(phase); phase += delta; if (phase >= pLimit) { phase -= pLimit; } samples.Add(alpha * short.MaxValue); } while (!isFinished) { alpha = Math.Sin(phase); phase += delta; if (phase >= chipLimit) { phase -= chipLimit; pxAmplitude = (((double)frame.GetPixel(col, row).R) / 255.0) * short.MaxValue; if (++col >= cols) { if (++row >= rows) isFinished = true; else col = 0; } } samples.Add(alpha * pxAmplitude); } if (interframePauseMs > 0) { samples.AddRange(new double[(int)((((double)interframePauseMs) / 1000.0) * (double)sampleRate)]); } return samples.ToArray(); } 


Pode ser visto a partir do código que, antes de modular a imagem, um prefixo de sincronização que consiste em tom puro (amostras pSize) é adicionado ao sinal de saída - isso é necessário para que a sincronização no lado receptor possa ocorrer antes da própria imagem e, em geral, em condições adversas.
O método Decode é o seguinte:

 public Bitmap Decode(double[] samples, double carrier, int pSize) { int cols = frameSize.Width; int rows = frameSize.Height; int col = 0; int row = 0; Bitmap result = new Bitmap(cols, rows); double delta = Math.PI * 2 * carrier / sampleRate; double alpha = 0; double phase = 0; double chipLimit = Math.PI * 2 * chipSize; double chipAmplitude = 0; double maxAmplitude = WaveUtils.GetMaxAmplitude(samples); double pxMax = -maxAmplitude; double pxMin = maxAmplitude; double smp; for (int i = pSize; (i < samples.Length) && (row < rows); i++) { alpha = Math.Sin(phase); phase += delta; if (phase >= chipLimit) { phase -= chipLimit; chipAmplitude = (Math.Max(Math.Abs(pxMax), Math.Abs(pxMin)) / maxAmplitude); pxMin = maxAmplitude; pxMax = -maxAmplitude; var gs = Convert.ToByte(chipAmplitude * 255); result.SetPixel(col, row, Color.FromArgb(255, gs, gs, gs)); if (++col >= cols) { col = 0; row++; } } else { smp = samples[i] * alpha; if (smp > pxMax) pxMax = smp; if (smp < pxMin) pxMin = smp; } } return result; } 


Pode-se observar que ambos os métodos não estão vinculados a nenhuma frequência específica e podem ser usados ​​com outro detector.

A busca do sinal em si (detecção, sincronização) também ocorre como em nosso modem hidroacústico mais simples , com a única diferença de colocá-lo em uma classe separada FsBy4CarrierDetector para uma alteração.
Toda mágica não complicada acontece no método booleano ProcessSample (curta a)

 public bool ProcessSample(short a) { bool result = false; if (smpCount == 0) { ring1[ringHead] = a; ring2[ringHead] = a; s1 += a - ring1[ringTail]; s2 += a - ring2[ringTail]; } else if (smpCount == 1) { ring1[ringHead] = a; ring2[ringHead] = -a; s1 += a - ring1[ringTail]; s2 += - a - ring2[ringTail]; } else if (smpCount == 2) { ring1[ringHead] = -a; ring2[ringHead] = -a; s1 += -a - ring1[ringTail]; s2 += -a - ring2[ringTail]; } else if (smpCount == 3) { ring1[ringHead] = -a; ring2[ringHead] = a; s1 += -a - ring1[ringTail]; s2 += a - ring2[ringTail]; } ringHead = (ringHead + 1) % ringSize; ringTail = (ringTail + 1) % ringSize; if (++smpCount >= 4) { smpCount = 0; if (++cycle >= ringSize) { s = Math.Sqrt(s1 * s1 + s2 * s2) / ringSize; cycle = 0; result = (s - sPrev) >= Threshold; sPrev = s; } } return result; } 


Ele é chamado em todas as amostras recebidas e retorna verdadeiro em caso de detecção de transportadora.

Como o detector está longe de ser perfeito e pode ser facilmente sincronizado no meio da linha, adicionei um controle deslizante especial, movendo o qual você pode obter uma sincronização mais precisa.

Agora, depois de examinarmos brevemente como tudo isso funciona, vamos para a parte mais deliciosa: o que pode ser obtido com tudo isso.

Um pouco de prática


Primeiro, vamos verificar como tudo funciona sem um canal de sonar - simplesmente conectando as antenas de recepção e transmissão umas às outras.
Primeiro, a imagem é maior (240x120) para que pelo menos algo possa ser descoberto:


E então rapidamente, para que haja mais vida parecida com um vídeo:


Parece não ser ruim? Mas não se apresse em tirar conclusões e vá para a piscina:


E aqui, como prometi no título, veremos um eco com nossos próprios olhos:


Como você gosta disso, Elon Musk? Você gosta de HD? Por que isso é assim?
E tudo é muito simples - o eco, na verdade, são as cópias atrasadas do sinal original, interferindo de maneira famosa no ponto de recebimento, dobrando-se em uma fase diferente e fornecendo uma imagem. Desde que transferimos a imagem, no final, temos muitas imagens sobrepostas umas com as outras com amplitudes diferentes. Tudo isso leva a desfocagem e reprodução.

Olhando para trás, vamos verificar tudo na imagem ampliada do modelo. Tirei uma foto aleatória:


Modulei, adicionei um eco e um pouco de ruído, depois foi decodificado e sim - o resultado se assemelha ao que obtivemos na piscina:


Em princípio, é possível realizar a desconvolução e subtrair as reflexões, mas sejam pessoas de fora da nossa área que deixamos esse ponto para um trabalho independente.

A propósito, o método anterior na piscina funciona um pouco melhor, mas também mal - em sinais de banda larga, caminhos múltiplos e reverberação levam ao desbotamento seletivo de frequência, que na imagem (lido no espectro) se parece com listras em preto e branco - onde o sinal está em fase antifásica, e onde ele se desenvolveu na fase (de fato, ainda existem várias opções intermediárias):


Em abril, aproveitamos o momento e fomos para o lago com um modelo de tábua de pão e nos mimos lá também:




O resultado não é muito diferente dos resultados obtidos no pool:




E imediatamente para comparação, o método anterior:


E aqui estão as animações gif coletadas dos quadros salvos, método 1:


E o método 2, que discutimos neste artigo:


Em conclusão


Conforme prometido, mostramos como o eco e o reverb parecem literalmente, gastamos tempo com benefícios e fizemos algo com nossas mãos.

Dessa forma, é claro, o método não é aplicável na prática, mas trabalhar com ele será muito útil para iniciantes.

Em geral, verificamos em um lago raso, onde as condições são muito desfavoráveis, e seria legal se alguém repetisse nossos experimentos em outros reservatórios e certamente contasse seus resultados.

Se o leitor quiser apenas tentar (mesmo no ar com um microfone e alto-falantes), aqui estão os links para os lançamentos:
Método 1
Método 2 (deste artigo)

PS

Estamos realmente ansiosos pelo feedback dos leitores, pois é muito importante entender que você está fazendo algo em vão (ou em vão, e então precisa interrompê-lo imediatamente).

PS / 2

Responderei imediatamente a uma pergunta comum: para peixes e outras formas de vida marinha em instalações para crianças, tudo isso é imperceptível.

Source: https://habr.com/ru/post/pt453678/


All Articles