«Le Seigneur Tout-Puissant! Il semble que je viens de tuer M. May! ... Mais quoi qu'il en soit, nous continuons »(C) J. Clarkson
Dans cet article, je vais vous dire comment transférer de la vidéo (enfin presque de la vidéo) en utilisant le son dans l'eau à l'aide d'un ordinateur portable ordinaire, d'un morceau de fil, de deux prises 3,5 mm et de deux tweeter piézo. Je vais également expliquer pourquoi et comment cela fonctionne, raconter une histoire amusante sur la façon dont nous en sommes arrivés à cela. Et comme cerise sur le gâteau, un article sur C # avec des codes sources est joint à l'article afin que tous ceux qui sont intéressés puissent l'essayer eux-mêmes, car les connaissances scientifiques sont vérifiables, n'est-ce pas?
Si tout à coup le lecteur souhaite approfondir un peu les thèmes hydroacoustiques, je vous propose de vous familiariser avec nos publications précédentes, où nous parlons de nos projets d'une manière révélant les difficultés de transmission d'informations par l'eau:
GPS sous-marin à partir de zéro par anGPS sous-marin: suiteNavigation sous l'eau: radiogoniométrie - ne pas radiogoniométrie, vous êtes voué au succèsSur l'effet des cyanobactéries sur les fonctions vocales du présidentEn général, une vérité simple doit être apprise: la vidéo à travers l'eau à n'importe quelle distance significative (enfin, au moins des centaines de mètres) ne peut pas être transmise en utilisant l'acoustique. Le point est la bande de fréquences disponible extrêmement étroite et la forte inégalité de l'atténuation des différentes fréquences avec la distance. Les avantages sont le bruit, la propagation par trajets multiples, la réverbération, le changement de la vitesse du son dans le milieu par rapport à la densité (c.-à-d. La pression, la température et la salinité), l'effet Doppler, qui ne fonctionne d'ailleurs pas tout à fait comme dans les communications radio.
Les limites de vitesse pour les modems sonar les plus avancés sont très loin de pouvoir transmettre de la vidéo. Pour autant que je sache, le record appartient à EvoLogics et s'élève à 62,5 kbps avec une distance maximale déclarée de 300 mètres. De plus, les mots sur l'impossibilité de transmettre le son vidéo à travers l'eau (à des distances raisonnables) appartiennent uniquement à Konstantin Georgievich, fondateur et directeur d'EvoLogics.
Quand j'étais chercheur à l'Institut de recherche Hydrosvyaz, alors complètement inconscient, je voulais de grandes réalisations, des
victoires dans le nord et le sud, un grand ameublissement des sols (non, je les veux toujours, mais alors je n'étais pas du tout accablé d'expérience et de connaissances et tout semblait presque magique et fabuleux). Dans notre équipe de l'époque (dont une partie est la mienne), nous avons souvent fantasmé sur des projets de sonar irréalistes, fouillé dans une
décharge et essayé d'utiliser toutes sortes d'artefacts d'une grande civilisation ancienne d'affilée, dont cet institut de recherche tente en partie de comprendre le tao de la communication sonar .
L'immersion dans ces souvenirs évoque des sentiments contradictoires en moi. Alors rien ne semblait et personne ne pouvait nous arrêter: nous avons mis hors service une fraiseuse chinoise du directeur du prototypage de produits, assemblé des corps normobares à partir de conduites d'eau néerlandaises Van De Lande, dont le fabricant a même écrit une lettre sur le sujet: «Avez-vous vérifié accidentellement vos tuyaux résistent-ils à la pression extérieure? " Ils ont collecté des modèles de planche à pain pour leur propre argent dans des conteneurs de petit-déjeuner et se sont rendus secrètement au test pour les tester secrètement, collectant des forets à glace et des traîneaux pour des collègues et des parents, et ont même acheté un bateau chinois en PVC à Auchan. Avec le recul, je sens à quel point mon cœur est rempli d'horreur, de nostalgie et d'appréhension.
En toute honnêteté, il convient de noter que pendant tout ce temps, nous avons reçu un grand soutien de certains de nos dirigeants - en paroles et en actes, et en conséquence, tous nos métiers ont été légalisés en TOC (ce qui signifie travail de conception expérimentale et non trouble obsessionnel compulsif), qui était même présenté au salon naval international en 2013. Oui, oui, nous avons conduit au salon nos conduites d'eau, peint
StDmitirev de
notre propre main en orange vif! Les voici, dans des valises:

Un jour, mon ami et collègue
StDmitirev, au milieu d'une conversation sur les spectres et les spectrogrammes, a prononcé la phrase suivante:
"Mais, ce serait amusant de faire un tel système: le sous-marin est assis dans le sous-marin et regarde le moniteur, sur lequel le spectrogramme se déplace en douceur, sur lequel les lettres et les chiffres sont écrits comme le doigt d' un autre sous-marin sur la fenêtre brumeuse d' un autre sous-marin ."
Tout le monde a ri, développé ce sujet, il semble que même le même jour, ils aient dessiné un smiley sur le spectrogramme et écouté comment ça sonne. Je voulais vraiment apporter cela à un aspect pratique.
Maintenant, c'est difficile à retenir (c'était en 2012). J'avais un ordinateur en état de marche avec une webcam, divers artefacts-antennes et un "godet boosting" spécial (VG-1-P) avec de l'eau. Ils l'ont appelé une étape parce que j'ai montré à tous ses patrons le travail de différents modèles d'équipement, ce qui a conduit à ma promotion en tant que chercheur senior.
Je ne suis contraint par aucune obligation, la méthode elle-même est depuis longtemps publiée dans le domaine public et les résultats ont été rapportés à plusieurs reprises lors de conférences.
Donc, je vous dis comment dans l'esprit - comment transmettre une vidéo à travers l'eau:
Comment générer un signal?
Nous nous souvenons que l'idée est basée sur le «dessin sur un spectrogramme», c'est-à-dire que l'image transmise est le spectrogramme du signal. Pour convertir un signal du domaine temporel en domaine fréquentiel et vice versa, il est pratique d'utiliser (enfin, par exemple) la transformée de Fourier, ou plutôt, la transformée de Fourier rapide, par souci de concision, appelée FFT ou, plus communément, FFT (Fast Fourier Transform).
Comme nous devons transformer une image (image vidéo) en un signal audio qui pourrait être émis par la carte son de n'importe quel ordinateur, nous utiliserons évidemment la transformation inverse, IFFT, pour la former. Nous émettrons une image en colonnes, et un signal pour une colonne sera formé comme dans le diagramme suivant:
=
Supposons que la taille de la fenêtre FFT soit N et que nous ayons un tableau de taille N. Si nous le considérons comme le spectre du signal, alors son élément zéro correspond à la fréquence zéro (constante), et le compte avec l'indice N-1 correspond à la fréquence d'échantillonnage de la fréquence d'échantillonnage. Il est nécessaire de choisir ces tailles de trame d'image et la taille de la fenêtre FFT de sorte que, d'une part, tout cela ressemble en quelque sorte à la vidéo (le transfert d'une trame prendrait un temps raisonnable), et d'autre part, la bande de fréquence utilisée était adéquate en principe et adaptée à l'équipement disponible. . Maintenant, si nous entrons les valeurs de luminosité de la colonne de l'image (Colonne de cadre) à partir d'un décompte favori (de bas en haut dans le diagramme), puis effectuons la FFT inverse, la sortie recevra un signal codant une colonne de l'image. Il nous reste maintenant à former les signaux de la même manière pour les colonnes restantes de l'image et à les émettre alternativement à l'aide d'une carte son.
Il convient de noter que la FFT à la sortie donne un tableau de valeurs complexes, donc notre signal est la partie réelle. Bien sûr, le signal résultant dans les colonnes est réduit à des entiers signés 16 bits (sous cette forme, un signal audio numérique est généralement stocké) et normalisé.
En fait, au début de l'image, j'entre également quelques colonnes de luminosité maximale, plus tard du côté du récepteur, cela déterminera la réponse en fréquence du trajet de l'émetteur-récepteur (et du canal de transmission), qui, une fois inversée et légèrement lissée, nous aidera à améliorer la trame reçue.
À mon avis, le moyen le plus simple de démontrer le dispositif de l'émetteur est avec un morceau de code, le voici (méthode Encode de la classe Encoder):
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; }
Le code, naturellement, ne prétend rien et a été écrit à la hâte uniquement à des fins de démonstration.
Et la vitesse de transmission?
Et comment l'évaluer? Nous avons réussi (
du mal pas du mal) à maintenir l'intrigue pendant environ deux mois, et certains de nos camarades et dirigeants supérieurs ont réussi à écrire un tas de papier pendant leur temps libre, se demandant comment une vitesse de transmission aussi folle pourrait se produire.
Par exemple, si la fréquence d'échantillonnage est de 96 kHz et que nous prenons la taille de la fenêtre FFT à 512, nous enverrons 120 x 120 pixels (8 bits par pixel) à l'entrée de l'émetteur, alors le temps qu'il faut pour transmettre une trame d'image est:
120 * 512/96000 = 0,64 secondeLe débit binaire devrait sembler être:
120x120 * 8 / 0,64 = 180 000 bits par seconde!Le fils du réalisateur était ravi à l'époque - oui, vous pouvez déjà utiliser les protocoles Internet! C'est une percée!Comme je vais le montrer ci-dessous, il est très facile de tomber dans une telle illusion. Qu'est-ce qui ne va pas ici? Après tout, tout est si simple et élégant!
En fait, un tel calcul de vitesse n'est pas applicable à cette méthode, tout comme, par exemple, il ne s'applique pas à un signal de télévision analogique, combien y a-t-il de bits par pixel? =) Et qu'en est-il du récepteur détecteur le plus simple? =))
La méthode de transmission décrite est essentiellement
ANALOGIQUE et les concepts de «bit» et de «pixel» ne lui sont pas applicables - dans la même image, théoriquement, vous ne pouvez pas prendre 8 bits par luminosité de pixel mais 16 et «vitesse» doublera automatiquement.
Il est temps de montrer les tout premiers résultats de notre «percée»:

La photo ci-dessus a été prise par nous à l'hiver 2012 sur la rivière Pichuga. La distance de transmission était de 700 mètres. Oui, hélas, mon cher lecteur, ce n'est pas du tout HD et ne tire même pas sur le CamRip le plus honteux. Je ne me souviens pas déjà de qui, mais quelqu'un a très précisément remarqué que toutes nos «vidéos» sont comme envoyer des signaux d'aide d'une planète mourante.
Ce qui est remarquable, avec un étirement, cela peut être décrit comme une sorte d'OFDM - les données sont transmises sur des sous-porteuses orthogonales, ce qui signifie une bonne résistance aux interférences tonales et autres interférences à bande étroite - dans ce cas, les "lignes" individuelles de l'image sont déformées. Le bruit impulsionnel, au contraire, déforme une ou un groupe de colonnes. Le "bandage" caractéristique des images est causé par ce que l'on appelle évanouissement sélectif en fréquence dû à la propagation par trajets multiples, mais j'en parlerai une autre fois.
Comment est arrangé le récepteur?
Je dois réserver tout de suite que pour essayer cette méthode dans un seau ou même dans une petite piscine, des pièces de deux heures (rondes par exemple) avec un connecteur pour une carte son soudée seront suffisantes. Pour l'émetteur, vous pouvez prendre un câble assez long (2-3-4-5 mètres) et non blindé, scellant l'élément piézoélectrique avec du vernis au zapon ou une petite couche de mastic - c'est certainement suffisant à plusieurs reprises. L'antenne sonar résultante (pas, eh bien, quoi?) Est insérée dans la prise casque.
La photo ci-dessous montre différentes pièces qui étaient à portée de main au moment de la rédaction. Tous les éléments piézoélectriques illustrés sont tout à fait adaptés pour "essayer" et il y a généralement un magasin de radio dans n'importe quel
dépotoir . Pyatak n'a pas d'effet piézoélectrique et est présent sur l'image pour l'échelle.

Pour le récepteur, il est préférable de prendre un câble de microphone blindé avec le même connecteur et un piezo enduit de scellant ou de vernis à la fin. Nous insérons cette antenne dans la prise microphone.
Pour les expériences sur un étang, il est préférable de prendre une sorte d'anneau piézoélectrique comme émetteur et de l'alimenter amplifié (un amplificateur sur un TDA2030 avec un transformateur correctement enroulé durera plusieurs centaines de mètres dans un bon étang
ou 5 autres tours peuvent être enroulés). Pour le récepteur, dans ce cas, un préamplificateur et de préférence un filtre passe-bande sont également nécessaires. Si les lecteurs sont intéressés à en savoir plus à ce sujet en détail, dites-le nous dans les commentaires et nous essaierons de faire un article sur la création d'amplificateurs de puissance, de préamplis et d'antennes pour la communication sonar.
Revenons donc au récepteur, plus précisément à sa partie logicielle
La chose la plus importante en communication est la synchronisation et la détermination de la présence d'un signal utile. Dans notre exemple, la détection est effectuée par l'énergie dans la bande: les endroits où elle augmente fortement (début de la trame) et où elle chute fortement (la fin de la trame) sont déterminés, à condition que d'avant en bas il y ait au moins la durée de la trame.
Pour toute sa simplicité, il fonctionne étonnamment bien.
Les données de la carte son sont collectées par des échantillons FFTSize, la FFT est exécutée immédiatement sur elles et elles sont stockées sous forme de «tranches» séparées, en attendant le moment où elles seront traitées par la procédure de recherche, voici son code (méthode de recherche dans la classe 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); }
Et voici un morceau de code qui est responsable du décodage de l'image (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"); } }
Et maintenant je propose de regarder les résultats d'expériences sur la transmission de "vidéo", menées à différents moments dans différents réservoirs.
Les deux photos (ci-dessous) ont été enregistrées au salon naval international de Saint-Pétersbourg en 2013 sur notre (alors) stand à travers deux ordinateurs portables et un aquarium.
Il n'est pas possible de distinguer ce qui est écrit sur le badge


Et voici deux «vidéos» enregistrées par nous dans l'une des baies du lac Ladoga en Carélie, elles sont une sorte de record pour cette méthode (nous ne l'avons plus jamais essayée et il est peu probable qu'elle soit) - la première a été obtenue à une distance de 500 et la seconde à 1000 mètres :
Transmission vidéo dans l'eau, distance 500 m (fichier 8.7 mb)
Puisque la "vidéo" a été enregistrée en temps réel à l'aide d'une webcam, diverses choses étranges sont tombées dans le cadre. Ce sera très intéressant si quelqu'un devine et écrit dans un commentaire ce qui est en arrière-plan dans la dernière «vidéo»).
À l'appui du fait que la méthode a été publiée il y a longtemps -
notre article déjà pour 2013
J'ai utilisé la merveilleuse bibliothèque
AForge pour
capturer des images de webcam .
Le nombre complexe et les fonctions FFT sont utilisés à partir de l'excellente bibliothèque
AlgLib .
Et, comme je l'ai promis, l'ensemble du projet en C # (VS2012) est attaché à l'article comme matériau pour le travail "à domicile". Pour plus de commodité, le
projet et les
fichiers binaires sont séparés.
La démo offre la possibilité de changer (déplacer) la bande de fréquence occupée ainsi que la correction gamma de la trame de sortie (tout peut être changé en temps réel).
PS
Je n'ai pas choisi C # depuis longtemps et il est très difficile de trouver l'heure dans l'horaire de travail, donc je m'excuse à l'avance pour la confusion et la hâte du code.
PPS
Je n’attache pas un morceau de fil, deux prises et deux pièces à l’article - pas assez pour tout le monde.
Errata et annexe
- Dans certaines cartes son à l'entrée, il y a un filtre passe-bas qui coupe tragiquement tout ce qui dépasse ~ 15 kHz (pourquoi ???).
- Par défaut, le projet de démonstration fonctionne avec une fréquence d'échantillonnage de 96 kHz, mais toutes les cartes son modernes ne le prennent pas en charge (pourquoi ???). Si l'équipement ne peut pas 96 kHz, vous devez définir 48 kHz dans les paramètres, sinon, 44100 est certainement pris en charge partout, cependant, la durée de transmission d'une image sera d'autant plus longue.
Voici une liste d'ordinateurs portables et de cartes son pouvant être considérés comme de jeunes équipements sonars:
- Lenovo ideapad Y510P avec son JBL
- Asus n55s
- Asus K501U
- carte son externe Sound Blaster X-Fi Surround 5.1 (modèle n ° SB 1095)