DIY家庭甚マルチメディアシステム向けのナニバヌサルアンビラむト-Atmosvet

こんにちは

最初の蚘事では、最も成功した手芞品の1぀を遞択したした。これは、フィリップスのAmbilightのHDMIパススルヌアナログです。今埌、この構成を「Atmosvet」ず呌びたす。

はじめに

むンタヌネット䞊で、PCから画像を衚瀺する堎合、モニタヌ/テレビ甚のAmbilightを䜜成する方法に関する既補の/オヌプンな゜リュヌションず蚘事を芋぀けるこずはそれほど難しくありたせん。 しかし、私のマルチメディアシステムでは、PCからテレビに画像を出力するのに䜿甚する時間はたった5で、ゲヌムコン゜ヌルからプレむする時間が増えたす。぀たり、自分で䜕かを考え出す必芁がありたした。


゜ヌスデヌタ


ほずんどのデバむスは、 HDCPを䜿甚しお、再生䞭でもコンテンツを再生したす。
芁件

TVに接続されおいるすべおのデバむスに察しおAtmosvetの集䞭サポヌトを提䟛する必芁がありたす。

実装

4.5mのLEDストリップをテレビに取り付けた方法ずArduinoで䜕をする必芁があるかに぀いおは説明したせん。 この蚘事をベヌスずしお䜿甚できたす。

唯䞀の泚意事項
画面の䞋郚に奇劙なちら぀きがあるこずに気づきたした。最初にミスをしお、deflayerを遞び盎し、画像のサむズ倉曎を倉曎し、すべおのものを掘り䞋げたしたが、それは良くなりたしたが、ちら぀きの助けにはなりたせんでした。 私は芳察し始めたした。 ちら぀きはテヌプの最埌でしかなく、その埌は鮮明なシヌンでした。 マルチメヌタヌを䜿甚しお、テヌプの始め、䞭間、および終わりで電圧を枬定し、ちら぀きの原因を掚枬したしたテヌプの始めで4.9Vはい、䞭囜のPSUは偏差のある電圧を䞎えたす、これは重芁ではありたせん、4.52の終わりで4.22-電圧降䞋が倧きすぎたす、私は単玔に問題を解決しなければなりたせんでした-テヌプの途䞭で、PSUからの電力を合蚈し、ケヌブルをテレビの埌ろに通したした。 それは即座に圹立ち、ちら぀きは完党に止たりたした。

りェブカメラで写真をキャプチャする

アむデアずその芖芚化を実行するための最初のテストバヌゞョンは、Webカメラで画像をキャプチャするこずで遞択されたした、次のようになりたした。
画像

䜎レンダリングず高レむテンシは、この実装がいかなる方法でも䜿甚できないこずを瀺したした。

HDMIを介した画像のキャプチャ


可胜なオプションを怜蚎する過皋で、最も信頌性の高い予算ずしお次のスキヌムが遞択されたした。


最初はワむルドで束葉杖のように芋えたすが、


HDMIキャプチャにボヌドを䜿甚しなかったのはなぜですか それは簡単です最も安䟡なオプションず手頃な䟡栌はBlackmagic Intensity Shuttleですが、1080p / 60fpsの信号では動䜜せず、1080p / 30fpsでのみ動䜜したす-これは受け入れられたせん 写真をキャプチャできるように、フレヌムレヌトを䞋げたくありたせんでした。 +このケヌスの費甚は玄1䞇です。 ルヌブル。 -安䟡ではなく、結果は䞍明です。

HDMIからSビデオぞの倉換の損倱は、46x26 LEDバックラむトの解像床でカラヌをキャプチャする堎合には重芁ではありたせん。

最初はEasyCapを䜿甚しおSビデオをキャプチャしようずしたした䞭囜語のバリ゚ヌションが倚数ありたすが、ポむントは䜿甚するチップが非垞に悲惚であり、openCVを䜿甚しお操䜜できないこずです。

唯䞀のマむナスは、Sビデオ出力信号の゚ッゞに黒いバヌが含たれおおり、実際のコンテンツ玄2〜5がカットされおいるこずです。キャプチャカヌドから出力画像をカットしおこれらのバンドを削陀したしたが、これらの領域の画像の損倱は実際の結果に圱響したせんでした。

゜フト

私にずっおそれは最も興味深い郚分でした、なぜなら 鉄片で、私は本圓に呚りを突くのが奜きではありたせん。

画像をキャプチャするために、 openCV 、特にその.NETラッパヌemgu CVを䜿甚したした 。

たた、コントロヌラヌに色のリストを枡す前に、画像を埌凊理しお準備するためのいく぀かの異なる手法を適甚するこずにしたした。

フレヌム凊理

1.キャプチャされたフレヌムを取埗する

2.フレヌムを切り取っお黒いバヌを陀倖したす

ここではすべおが簡単です
frame.ROI = new Rectangle(8, 8, frame.Width - 8, frame.Height - 18 - 8); 

䞊郚から8ピクセル、右偎から8ピクセル、䞋郚から18ピクセルをトリミングしたす巊偎にストリップはありたせん。

3.バックラむトの解像床でフレヌムのサむズを倉曎したす。健康的な写真を持ち歩く必芁はありたせん。

それほど耇雑なこずはありたせん。openCVツヌルを䜿甚しお行いたす。
frame.ResizeLedWidth-2 * LedSideOverEdge、
LedHeight-LedBottomOverEdge-LedTopOverEdge、
INTER.CV_INTER_LINEAR;
泚意深い読者は、豊富な倉数に気付くでしょう。 実際、私のテレビフレヌムは十分に倧きく、偎面に1個、䞊郚に1個、䞋郚に3個のLEDを占有しおいるため、サむズ倉曎はディスプレむの真向かいのLEDで行われ、埌でコヌナヌを補完したす。 サむズ倉曎するずき、LEDのピクセルが持぀べき平均色を取埗したす。

4.カットフレヌムからLEDのマッピングを実行したす

さお、ここでも、すべおが簡単です。それぞれの偎で愚かに行き、136個の倀の配列をLEDの色で順番に埋めおいきたす。 珟時点では、他のすべおの操䜜は、凊理が難しいフレヌムを䜿甚するよりも、LEDアレむを䜿甚する方が簡単です。 たた、将来的には、キャプチャ深床パラメヌタヌLEDの色を平均するための画面境界からのピクセル数を远加したしたが、最終的なセットアップでは、それなしでより良いこずが刀明したした。

5.色補正を実行したすホワむトバランス/カラヌバランス

私がビヌムから持っおいるテレビの埌ろの壁、ビヌムは黄色なので、黄色さを補う必芁がありたす。
var blue = 255.0f /255.0f + blueLevelFloat* pixelBuffer [k];
var green = 255.0f /255.0f + greenLevelFloat* pixelBuffer [k + 1];
var red = 255.0f /255.0f + redLevelFloat* pixelBuffer [k + 2];
実際、私は最初にいく぀かのオヌプン゜ヌス゚ディタヌの゜ヌスからカラヌバランスを取りたしたが、癜を倉曎せず癜は癜のたた、匏を少し倉曎しお封印し、必芁なものを盎接取埗したした色成分のレベルが負の堎合この色は十分ではありたせん、その匷床を远加し、逆も同様です。 私の壁では、RGB-30.5.85で機胜したした。

色補正では、各コンポヌネントから13を枛算するだけで、黒のレベリングも行いたす黒はRGBで13.13.13前埌になりたす。

6.圩床を䞋げる画像の圩床を䞋げる

最終的なセットアップでは、圩床䜎䞋は䜿甚したせんが、ある時点で必芁になる堎合がありたす。実際には、フィリップスアンビラむトのように色をより「パステル」にしたす。 コヌドは提䟛したせん。単にRGB-> HSLから倉換し、圩床コンポヌネント圩床を枛らし、RGBに戻したす。

7.ちら぀き

したがっお、入力画像が「揺れおいる」こずがわかりたす。これは、アナログ信号ぞの倉換の結果だず思いたす。 最初は自分のやり方を決めようずしたしたが、VirtualDubで䜿甚されおいるDeflikerフィルタヌの゜ヌスを調べ、Cで曞き盎したしたC ++でした。機胜しないこずがわかりたした。結局、私は決定ずこのデフレアを組み合わせお、奇劙な䜕かを埗たしたが、予想以䞊にうたく機胜したした。 最初のdeflayerはフレヌム党䜓の匷床でのみ機胜し、各LEDが個別に必芁です。 初期デラむサヌは匷床の倉化を合蚈ずしお比范したしたが、色ベクトルの長さの比范が奜きです。初期デラむサヌは前のフレヌムず比范した匷床の倉化のデルタを比范したしたが、これは適合せず、前のフレヌムのりィンドり内の匷床の平均倀に倉換したした。 そしお、他の倚くのささいなこず。その結果、最初のデフレダヌにはほずんど残っおいたせん。
䞻なアむデア前のフレヌムの平均匷床から進んで、匷床が特定のしきい倀25の最終蚭定でこのしきい倀を持っおいるを超えおいない堎合、珟圚のフレヌムを倉曎したす。しきい倀を超えるず、りィンドりは倉曎なしにリセットされたす。
deflicerのコヌドを少しコンテキストから読みやすくするために倉曎したした
 Array.Copy(_leds, _ledsOld, _leds.Length); for (var i = 0; i < _leds.Length; i++) { double lumSum = 0; // Calculate the luminance of the current led. lumSum += _leds[i].R*_leds[i].R; lumSum += _leds[i].G*_leds[i].G; lumSum += _leds[i].B*_leds[i].B; lumSum = Math.Sqrt(lumSum); // Do led processing var avgLum = 0.0; for (var j = 0; j < LedLumWindow; j++) { avgLum += _lumData[j, i]; } var avg = avgLum/LedLumWindow; var ledChange = false; if (_strengthcutoff < 256 && _lumData[0, i] != 256 && Math.Abs((int) lumSum - avg) >= _strengthcutoff) { _lumData[0, i] = 256; ledChange = true; } // Calculate the adjustment factor for the current led. var scale = 1.0; int r, g, b; if (ledChange) { for (var j = 0; j < LedLumWindow; j++) { _lumData[j, i] = (int) lumSum; } } else { for (var j = 0; j < LedLumWindow - 1; j++) { _lumData[j, i] = _lumData[j + 1, i]; } _lumData[LedLumWindow - 1, i] = (int) lumSum; if (lumSum > 0) { scale = 1.0f/((avg+lumSum)/2); var filt = 0.0f; for (var j = 0; j < LedLumWindow; j++) { filt += (float) _lumData[j, i]/LedLumWindow; } scale *= filt; } // Adjust the current Led. r = _leds[i].R; g = _leds[i].G; b = _leds[i].B; // save source values var sr = r; var sg = g; var sb = b; var max = r; if (g > max) max = g; if (b > max) max = b; double s; if (scale*max > 255) s = 255.0/max; else s = scale; r = (int) (s*r); g = (int) (s*g); b = (int) (s*b); // keep highlight double k; if (sr > _lv) { k = (sr - _lv)/(double) (255 - _lv); r = (int) ((k*sr) + ((1.0 - k)*r)); } if (sg > _lv) { k = (sg - _lv)/(double) (255 - _lv); g = (int) ((k*sg) + ((1.0 - k)*g)); } if (sb > _lv) { k = (sb - _lv)/(double) (255 - _lv); b = (int) ((k*sb) + ((1.0 - k)*b)); } _leds[i] = Color.FromArgb(r, g, b); } /* Temporal softening phase. */ if (ledChange || _softening == 0) continue; var diffR = Math.Abs(_leds[i].R - _ledsOld[i].R); var diffG = Math.Abs(_leds[i].G - _ledsOld[i].G); var diffB = Math.Abs(_leds[i].B - _ledsOld[i].B); r = _leds[i].R; g = _leds[i].G; b = _leds[i].B; int sum; if (diffR < _softening) { if (diffR > (_softening >> 1)) { sum = _leds[i].R + _leds[i].R + _ledsOld[i].R; r = sum/3; } } if (diffG < _softening) { if (diffG > (_softening >> 1)) { sum = _leds[i].G + _leds[i].G + _ledsOld[i].G; g = sum/3; } } if (diffB < _softening) { if (diffB > (_softening >> 1)) { sum = _leds[i].B + _leds[i].B + _ledsOld[i].B; b = sum/3; } } _leds[i] = Color.FromArgb(r, g, b); } 

_ledsをColorクラスのLED配列、_ledsOldを倉換前のフレヌム倀、LedLumWindowを前のフレヌムのりィンドり幅ずし、匷床の平均倉化を掚定するために、最終セットアップで100のりィンドりがあり、これは玄30fpsで3秒に盞圓したす。 _lumData-前のフレヌムの匷床倀の配列。

最終的に、このメカニズムは写真に予期しない結果をもたらしたす。芖芚的にどのように知芚されるかを説明するこずは困難ですが、ダむナミックコントラストのように必芁に応じお暗く、必芁に応じお明るくしたす。 結果ずしおのデフレッカヌの目的は広く、ちら぀きを排陀するだけでなく、りィンドり内のコンポヌネントず時間の䞡方の点で、衚瀺される色の党䜓的なバランスを取りたした。

8.隣のLEDを平滑化したす。

䞀般に、最終的なセットアップでは、スムヌゞングがあたり奜きではなかったのでオフにしたしたが、堎合によっおは䟿利になりたす。 ここでは、各LEDの色をその隣接するものず単玔に平均しおいたす。
 var smothDiameter = 2*_smoothRadius + 1; Array.Copy(_leds, _ledsOld, _leds.Length); for (var i = 0; i < _ledsOld.Length; i++) { var r = 0; var g = 0; var b = 0; for (var rad = -_smoothRadius; rad <= _smoothRadius; rad++) { var pos = i + rad; if (pos < 0) { pos = _ledsOld.Length + pos; } else if (pos > _ledsOld.Length - 1) { pos = pos - _ledsOld.Length; } r += _ledsOld[pos].R; g += _ledsOld[pos].G; b += _ledsOld[pos].B; } _leds[i] = Color.FromArgb(r/smothDiameter, g/smothDiameter, b/smothDiameter); } 


9.珟圚の状態を保存しお、パケット送信スレッドが取埗しおバックラむトコントロヌラヌに送信するようにしたす。

フレヌムを凊理し、コントロヌラにパケットを送信するプロセスを意図的に分割したしたArduinoが前のパケットを凊理できるように、パケットは特定の間隔40ミリ秒で1回送信されたす。そのプロセスをキャプチャし、干枉したせんただし、パケットの送信にも時間がかかりたす。

Arduinoに぀いお少し

倧量のパッケヌゞをArduinoに取り蟌んで送信するこずはできたせん。これは、デフォルトのHardwareSerialバッファヌを超えおしたい、終わりを倱うためです。
これは非垞に簡単に解決されたす。HardwareSerialバッファヌのサむズを、送信されたパケット党䜓が色の配列で収たる倧きさに蚭定したす。私にずっおは、410です。

UI

゜フトりェア自䜓はwinサヌビスずしお実装され、すべおのパラメヌタヌを蚭定しお有効化/無効化するために、サヌビスのWebServiceを介しおサヌビスに接続するWeb UIを䜜成したした。 モバむル画面の最終的なむンタヌフェヌスは次のようになりたす。
画像

次に、HTCPに接続されたKinect for Windowsを介しお音声コントロヌルをねじ蟌む予定です。

結果

その結果、結果はすべおの期埅を満たし、今ではコン゜ヌルでゲヌムをプレむするこずで、ゲヌムの雰囲気にさらに没頭できたす。

仕事の䞀般的な結果ずしお、私は私のスキヌムに埓っお倧気の仕事でビデオを蚘録したした

テストサンプル1䞊海での戊闘シヌンであるパシフィックリム。この映画は、テストずデモ、倚くの鮮明なシヌンずフラッシュ、萜雷などに適しおいたす。



テストサンプル2YouTubeからマヌゞされたMLPのある皮のビデオは、明るい色のシヌンストラむプが奜きのテストや、倉化の速いシヌンビデオの最埌で、ビデオでのみ衚瀺される遅延の結果を芋るこずができたすに非垞に適しおいたすこれの実際の芖聎は目立ちたせん、私はビデオで遅延を枬定しようずしたした-それは10-20msになりたした



最埌に、HTPCからのリ゜ヌス消費に぀いお泚意する䟡倀がありたす。
HTPC i3​​でASRock Vision 3Dを䜿甚しおいたすが、倧気サヌビスはCPUず32MB RAMの5〜10を消費したす。

ご枅聎ありがずうございたした。私の蚘事が誰かに圹立぀こずを本圓に願っおいたす。

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


All Articles