“¡El Señor Todopoderoso! ¡Parece que acabo de matar al Sr. May! ... Pero sea como sea, continuamos ”(C) J. Clarkson
En este artículo, le diré cómo transferir video (bueno, casi video) usando sonido a través del agua usando una computadora portátil común, un cable, dos conectores de 3,5 mm y dos piezo tweeter. También explicaré por qué y cómo funciona, contaré una historia divertida sobre cómo se nos ocurrió esto. Y como guinda de un pastel, se adjunta un artículo sobre C # con códigos fuente para que todos los interesados puedan probarlo ellos mismos, porque el conocimiento científico es verificable, ¿no?
Si de repente el lector quiere profundizar un poco más en los temas del sonar, le sugiero que se familiarice con nuestras publicaciones anteriores, donde hablamos sobre nuestros proyectos de una manera que revela las dificultades de transmitir información a través del agua:
GPS subacuático desde cero por añoGPS subacuático: continuaciónNavegación bajo el agua: búsqueda de dirección: no busque dirección, está condenado al éxitoSobre el efecto de las cianobacterias en las funciones del habla del presidenteEn general, se debe aprender una verdad simple: el video a través del agua a cualquier distancia significativa (bueno, al menos cientos de metros) no se puede transmitir utilizando la acústica. El punto es la banda de frecuencia disponible extremadamente estrecha y la fuerte desigualdad de la atenuación de las diferentes frecuencias con la distancia. Las ventajas son el ruido, la propagación por trayectos múltiples, la reverberación, el cambio en la velocidad del sonido en el medio de la densidad (es decir, la presión, la temperatura y la salinidad), el efecto Doppler, que por cierto no funciona del todo como en las comunicaciones por radio.
Los límites de velocidad para los módems de sonda más avanzados están muy lejos de poder transmitir video. Hasta donde yo sé, el registro pertenece a EvoLogics y asciende a 62.5 kbps con una distancia máxima establecida de 300 metros. Además, las palabras sobre la imposibilidad de transmitir sonido de video a través del agua (a distancias razonables) solo pertenecen a Konstantin Georgievich, fundador y director de EvoLogics.
Cuando era investigador en el Instituto de Investigación de Hidrocomunicación, completamente inconsciente, quería grandes logros,
victorias en el norte y en el sur, gran aflojamiento de los suelos (no, todavía los quiero, pero no estaba cargado de experiencia y conocimiento). todo parecía casi mágico y fabuloso). En nuestro equipo de esa época (parte del cual es el mío real), a menudo fantaseamos con algunos proyectos de sonar poco realistas, hurgamos en un
vertedero y tratamos de utilizar todo tipo de artefactos de una gran civilización antigua en fila, de los cuales este instituto de investigación está tratando en parte de comprender el tao de la comunicación sonar. .
La inmersión en esos recuerdos evoca sentimientos conflictivos en mí. Entonces nada pareció y nadie pudo detenernos: noqueamos una fresadora china del director para la creación de prototipos de productos, ensamblamos cuerpos normobáricos de las tuberías de agua holandesas Van De Lande, cuyo fabricante incluso escribió una carta sobre el tema: "¿Has verificado accidentalmente qué ¿Sus tuberías soportan la presión externa? Recogieron modelos de placas de pan por su propio dinero en contenedores para el desayuno y salieron a prueba en secreto para obtener orientación, recolectar taladros de hielo y trineos para colegas y parientes, e incluso compraron un bote chino de PVC en Auchan por un colapso. Mirando hacia atrás, siento cómo mi corazón se llena de horror, nostalgia y temor.
Para ser justos, vale la pena señalar que todo este tiempo recibimos un gran apoyo de algunos de nuestros líderes, en palabras y hechos, y como resultado, todos nuestros oficios se legalizaron en OCD (que significa trabajo de diseño experimental y no trastorno obsesivo-compulsivo), que fue incluso presentado en el salón naval internacional en 2013. Sí, sí, condujimos al salón nuestras tuberías de agua, ¡pintamos
StDmitirev en
nuestra mano en naranja brillante! Aquí están, en maletas:

Un día, mi amigo y colega
StDmitirev, en medio de una conversación sobre espectros y espectrogramas, pronunció la siguiente oración:
"Pero sería divertido crear un sistema así: el submarinista se sienta en el submarino y mira el monitor, en el que se mueve suavemente el espectrograma, en el que las letras y los números se escriben como el dedo de otro submarino en la ventana de niebla de otro submarino ".
Todos se rieron, desarrollaron este tema, parece que incluso el mismo día dibujaron una carita sonriente en el espectrograma y escucharon cómo suena. Realmente quería llevar esto a un aspecto práctico.
Ahora es difícil de recordar (fue en 2012). Tenía una computadora que funcionaba con una cámara web, varios artefactos-antenas y un "refuerzo de sonar de balde" especial (VG-1-P) con agua. Lo llamaron un paso adelante debido al hecho de que le mostré a todos sus jefes el trabajo de diferentes modelos de equipos en él, lo que llevó a mi ascenso a investigador senior.
No estoy obligado por ninguna obligación, el método en sí mismo se ha publicado durante mucho tiempo en el dominio público, y los resultados se han informado repetidamente en conferencias.
Entonces, te digo cómo, en espíritu, cómo transmitir un video a través del agua:
¿Cómo generar una señal?
Recordamos que la idea se basa en "dibujar en un espectrograma", es decir, la imagen transmitida es el espectrograma de la señal. Para convertir una señal del dominio del tiempo al dominio de la frecuencia y viceversa, es conveniente usar (bueno, por ejemplo) la transformada de Fourier, o mejor dicho, la transformada rápida de Fourier, por brevedad, llamada FFT o, más comúnmente, FFT (Transformada rápida de Fourier).
Dado que necesitamos convertir una imagen (cuadro de video) en una señal de audio que pueda emitir la tarjeta de sonido de cualquier computadora, obviamente utilizaremos la transformación inversa, IFFT, para formarla. Emitiremos una imagen en columnas, y se formará una señal para una columna como en el siguiente diagrama:
=
Suponga que el tamaño de la ventana FFT es N y hay una matriz de tamaño N. Si lo consideramos como el espectro de la señal, entonces su elemento cero corresponde a la frecuencia cero (constante), y el recuento con índice N-1 corresponde a la frecuencia de muestreo Frecuencia de muestreo. Es necesario seleccionar tales tamaños de cuadro de imagen y tamaño de ventana FFT para que, por un lado, todo se parezca al video (transferir un cuadro tomaría un tiempo razonable), y por otro lado, la banda de frecuencia utilizada era adecuada en principio y adecuada para el equipo disponible. . Ahora, si ingresamos los valores de brillo de la columna de la imagen (cuadro de color) de algún recuento favorito (de abajo hacia arriba en el diagrama), y luego realizamos la FFT inversa, la salida recibirá una señal que codifica una columna de la imagen. Ahora nos queda por formar las señales de la misma manera para las columnas restantes de la imagen y emitirlas alternativamente usando una tarjeta de sonido.
Vale la pena señalar que la FFT en la salida proporciona una serie de valores complejos, por lo que nuestra señal es la parte real. Por supuesto, la señal resultante en las columnas se reduce a enteros con signo de 16 bits (de esta forma, generalmente se almacena una señal de audio digital) y se normaliza.
De hecho, al comienzo de la imagen también ingreso algunas columnas de brillo máximo, luego en el lado del receptor esto determinará la respuesta de frecuencia de la ruta del transceptor (y el canal de transmisión), que, cuando se invierte y se suaviza ligeramente, nos ayudará a mejorar el marco recibido.
En mi opinión, la forma más fácil de demostrar el dispositivo del transmisor es con un fragmento de código, aquí está (método de codificación de la clase de codificador):
public double[] Encode(Bitmap source) { 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); double[] samples = new double[fftSize * frameSize.Width]; alglib.complex[] slice = new alglib.complex[fftSize]; double maxSlice; int sampleIndex = 0; int colsCount = frameSize.Width; int startRow = startLine; int endRow = startRow + frameSize.Height; for (int x = 0; x < colsCount; x++) { for (int y = startRow; y < endRow; y++) slice[y].x = (frame.GetPixel(x, frameSize.Height - (y - startRow) - 1).R / 255.0) * short.MaxValue; for (int y = 0; y < fftSize; y++) slice[y].x *= randomizerMask[y]; alglib.fftc1dinv(ref slice); maxSlice = double.MinValue; for (int y = 0; y < slice.Length; y++) if (Math.Abs(slice[y].x) > maxSlice) maxSlice = Math.Abs(slice[y].x); for (int i = 0; i < slice.Length; i++) { samples[sampleIndex] = (short)Math.Round(slice[i].x * short.MaxValue / maxSlice); sampleIndex++; } } return samples; }
El código, naturalmente, no pretende nada y fue escrito a toda prisa solo para demostración.
Entonces, ¿qué pasa con la velocidad de transmisión?
¿Y cómo evaluarlo? Nos las arreglamos (
del mal, no del mal) para mantener la intriga durante unos dos meses, y algunos de nuestros camaradas y líderes superiores en su tiempo libre lograron escribir un montón de papel, preguntándose cómo podría resultar una velocidad de transferencia tan loca.
Por ejemplo, si la frecuencia de muestreo es de 96 kHz, y tomamos el tamaño de la ventana FFT a 512, enviaremos 120 x 120 píxeles (8 bits por píxel) a la entrada del transmisor, entonces el tiempo que tarda en transmitir un cuadro de imagen es:
120 * 512/96000 = 0.64 segundosLa tasa de bits debería parecer ser:
120x120 * 8 / 0.64 = 180,000 bits por segundo!El hijo del director estaba encantado en ese momento, sí, ¡ya puedes usar protocolos de Internet! Este es un gran avance!Como mostraré a continuación, es muy fácil caer en una idea errónea. ¿Qué está mal aquí? Después de todo, ¡todo es tan simple y elegante!
De hecho, tal cálculo de velocidad no es aplicable a este método, así como, por ejemplo, no es aplicable a una señal de televisión analógica, ¿cuántos bits por píxel hay? =) ¿Y qué hay del receptor detector más simple? =))
El método de transmisión descrito es esencialmente
ANALÓGICO y los conceptos de "bit" y "pixel" no le son aplicables: en la misma imagen, en teoría, no puede tomar 8 bits por brillo de pixel, pero 16 y "velocidad" se duplicarán automáticamente.
Es hora de mostrar los primeros resultados de nuestro "avance":

La foto de arriba fue tomada por nosotros en el invierno de 2012 en el río Pichuga. La distancia de transmisión fue de 700 metros. Sí, por desgracia, mi querido lector, esto no es en absoluto HD y ni siquiera se basa en el CamRip más vergonzoso. No recuerdo quién ya, pero alguien notó con mucha precisión que todos nuestros "videos" son como enviar señales de ayuda desde un planeta moribundo.
Lo que es notable, con un estiramiento, esto se puede caracterizar como una especie de OFDM: los datos se transmiten en subportadoras ortogonales, lo que significa una buena resistencia a la interferencia tonal y de otra banda estrecha; en este caso, las "líneas" individuales de la imagen están distorsionadas. El ruido de impulso, por el contrario, distorsiona una o un grupo de columnas. La característica "banda" de las imágenes es causada por el llamado desvanecimiento selectivo de frecuencia debido a la propagación por trayectos múltiples, pero hablaré de esto en otro momento.
¿Cómo se organiza el receptor?
Haré una reserva de inmediato para que para probar este método en un cubo o incluso en una piscina pequeña, basten dos piezas de una hora (como las redondas) con un conector para una tarjeta de sonido soldada. Para el transmisor, puede tomar un cable bastante largo (2-3-4-5 metros) y sin blindaje, sellando el elemento piezoeléctrico con barniz de zapon o una pequeña capa de sellador, suficiente para varias veces. La antena de sonda resultante (¿no, bueno, qué?) Se inserta en la toma de auriculares.
La foto a continuación muestra varias piezas que estaban a mano en el momento de la escritura. Todos los elementos piezoeléctricos que se muestran son bastante adecuados para "probar" y generalmente hay una tienda de radio en cualquier
vertedero de basura . Pyatak no tiene un efecto piezoeléctrico y está presente en la imagen para la escala.

Para el receptor, es mejor tomar un cable de micrófono blindado con el mismo conector y un piezo con un sellador o barniz al final. Insertamos esta antena en el conector del micrófono.
Para los experimentos en un estanque, es mejor tomar algún tipo de anillo piezoeléctrico como transmisor y alimentarlo con uno amplificado (un amplificador en un TDA2030 con un transformador correctamente enrollado durará varios cientos de metros en un buen estanque
o se pueden enrollar
otros 5 giros ). Para el receptor, en este caso, también se requiere un preamplificador y preferiblemente un filtro de paso de banda. Si los lectores estarán interesados en aprender más sobre esto, cuéntanoslo en los comentarios y trataremos de hacer un artículo sobre la creación de amplificadores de potencia, preamplificadores y antenas para la comunicación sonar.
Entonces, volviendo al receptor, más precisamente a su parte de software
Lo más importante en la comunicación es la sincronización y determinación de la presencia de una señal útil. En nuestro ejemplo, la detección se realiza por la energía en la banda: se determinan los lugares donde aumenta bruscamente (comienzo del marco) y donde cae bruscamente (final del marco), con la condición de que de adelante hacia abajo debe haber al menos la duración del marco.
A pesar de su simplicidad, funciona sorprendentemente bien.
Los datos de la tarjeta de sonido se recopilan de acuerdo con las muestras de FFTSize, la FFT se realiza inmediatamente en ellos y se almacenan como "cortes" separados, esperando el momento en que serán procesados por el procedimiento de búsqueda, aquí está su código (Método de búsqueda en la clase Receiver):
private void Search() { int sliceIndex = 0; int frameWidth = encoder.FrameSize.Width; int minSlicesToSearch = Convert.ToInt32((frameWidth + 5) * 2); int sliceSize = encoder.FFTSize; double weight; int lastRisePosition = 0; int prevRisePosition = 0; while ((slices.Count > minSlicesToSearch) && (sliceIndex < slices.Count)) { weight = 0.0; for (int i = 0; i < sliceSize; i++) weight += Math.Abs(slices[sliceIndex][i]); double ratio = weight / previousWeight; if ((ratio >= risePeekRatio) && (sliceIndex - prevRisePosition > frameWidth)) { prevRisePosition = lastRisePosition; lastRisePosition = sliceIndex; if (lastRisePosition + (frameWidth + 5) < slices.Count) { double[][] samples = new double[frameWidth + 5][]; for (int i = 0; i < frameWidth + 5; i++) { samples[i] = new double[sliceSize]; Array.Copy(slices[lastRisePosition + i], samples[i], sliceSize); } slices.RemoveRange(0, sliceIndex); lastRisePosition = 0; if (FrameReceived != null) FrameReceived(this, new FrameReceivedEventArgs(encoder.DecodeEx(samples, 5))); lastRisePosition = sliceIndex; } } sliceIndex++; previousWeight = weight; } Interlocked.Decrement(ref isSearching); }
Y aquí hay un código que se encarga de decodificar la imagen (Encoder.DecodeEx):
public Bitmap Decode(double[] samples, int measureCols) { int colCount = samples.Length / fftSize; if (colCount == frameSize.Width + measureCols) { int rowCount = frameSize.Height; Bitmap temp = new Bitmap(colCount, rowCount); double[] slice = new double[fftSize]; alglib.complex[] sliceC = new alglib.complex[fftSize]; int samplesCount = 0; byte component; int decodeStart = startLine; int decodeEnd = startLine + rowCount; double maxSlice; for (int x = 0; x < colCount; x++) { for (int y = 0; y < fftSize; y++) { slice[y] = samples[samplesCount]; samplesCount++; } alglib.fftr1d(slice, out sliceC); maxSlice = double.MinValue; for (int y = decodeStart; y < decodeEnd; y++) if (alglib.math.abscomplex(sliceC[y].x) > maxSlice) maxSlice = alglib.math.abscomplex(sliceC[y].x); int offset = temp.Height + decodeStart - 1; for (int y = decodeStart; y < decodeEnd; y++) { component = (byte)(255.0 * alglib.math.abscomplex(sliceC[y].x) / maxSlice); temp.SetPixel(x, offset - y, Color.FromArgb(component, component, component)); } } return temp; } else { throw new ApplicationException("Specified array length error"); } }
Y ahora me propongo mirar los resultados de los experimentos sobre la transmisión de "video", realizados en diferentes momentos en diferentes depósitos.
Ambas imágenes (abajo) fueron grabadas en el salón naval internacional en San Petersburgo en 2013 en nuestro (entonces) puesto a través de dos computadoras portátiles y un acuario.
No es posible distinguir lo que está escrito en la insignia


Y aquí hay dos "videos" grabados por nosotros en una de las bahías del lago Ladoga en Karelia, son una especie de registro para este método (simplemente nunca lo intentamos y es poco probable que lo sea): el primero de ellos se obtuvo a una distancia de 500 y el segundo hasta 1000 metros :
Transmisión de video a través del agua, distancia 500 m (archivo 8.7 mb)
Dado que el "video" se grabó en tiempo real usando una cámara web, varias cosas extrañas cayeron en el marco. Será muy interesante si alguien adivina y escribe en un comentario lo que está en el fondo en el último "video").
Para respaldar el hecho de que el método se publicó hace mucho tiempo,
nuestro artículo ya es para 2013
Usé la maravillosa biblioteca
AForge para
capturar imágenes de la cámara web .
Las funciones de número complejo y FFT se utilizan de la excelente biblioteca
AlgLib .
Y, como prometí, todo el proyecto en C # (VS2012) se adjunta al artículo como material para el trabajo "en casa". Por conveniencia, el
proyecto y los
archivos binarios están separados.
La demostración proporciona la capacidad de cambiar (mover) la banda de frecuencia ocupada, así como la corrección gamma del cuadro de salida (todo se puede cambiar en tiempo real).
PS
No he recogido C # durante mucho tiempo y es muy difícil encontrar el tiempo en el horario de trabajo, así que me disculpo de antemano por la confusión y la prisa del código.
PPS
No adjunto un pedazo de cable, dos conectores y dos piezas al artículo, no es suficiente para todos.
Errata y Apéndice
- En algunas tarjetas de sonido en la entrada hay un filtro de paso bajo que corta trágicamente todo por encima de ~ 15 kHz (¿por qué ???).
- Por defecto, el proyecto de demostración funciona con una frecuencia de muestreo de 96 kHz, pero no todas las tarjetas de sonido modernas lo admiten (¿Por qué ???). Si el equipo no puede 96 kHz, entonces debe establecer 48 kHz en la configuración, de lo contrario, 44100 es compatible en todas partes, sin embargo, la duración de transmisión de un cuadro será correspondientemente más larga.
Aquí hay una lista de computadoras portátiles y tarjetas de sonido que pueden considerarse equipos de sonar jóvenes:
- Lenovo ideapad Y510P con sonido JBL
- Asus n55s
- Asus K501U
- tarjeta de sonido externa Sound Blaster X-Fi Surround 5.1 (modelo no. SB 1095)