diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..fa7e17c
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+**/__pycache__
+/checkpoint/
\ No newline at end of file
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/DH_live.iml b/.idea/DH_live.iml
new file mode 100644
index 0000000..cc22754
--- /dev/null
+++ b/.idea/DH_live.iml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..f5543d8
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,157 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..632ebc5
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..897d86e
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..e364551
--- /dev/null
+++ b/README.md
@@ -0,0 +1,71 @@
+# Mobile and Web Real-time Live Streaming Digital Human!
+# 实时直播数字人 [bilibili video](https://www.bilibili.com/video/BV1Ppv1eEEgj/?vd_source=53601feee498369e726af7dbc2dae349)
+# 数字人方案对比
+
+以下表格展示了不同数字人方案的性能、使用方式、脸部分辨率及适用设备等信息,方便用户根据需求选择合适的方案。
+
+| 方案名称 | 单帧算力(Mflops) | 使用方式 | 脸部分辨率 | 适用设备 |
+|------------------------------|-------------------|------------|------------|------------------------------------|
+| Ultralight-Digital-Human(mobile) | 1100 | 单人训练 | 160 | 中高端手机APP |
+| DH_live_mini | 39 | 无须训练 | 128 | 所有设备,网页&APP&小程序 |
+| DH_live | 55,046 | 无须训练 | 256 | 30系以上显卡 |
+| duix.ai | 1,200 | 单人训练 | 168 | 中高端手机APP |
+
+### News
+## Fastest model released! More demos joins me through the contact information at the bottom!
+ All checkpoint files are moved to [baiduNetDisk](https://pan.baidu.com/s/1jH3WrIAfwI3U5awtnt9KPQ?pwd=ynd7)
+## Training
+Details on the render model training can be found [here](https://github.com/kleinlee/DH_live/tree/master/train).
+Audio Model training Details can be found [here](https://github.com/kleinlee/DH_live/tree/master/train_audio).
+### Video Example
+
+
+https://github.com/user-attachments/assets/7e0b5bc2-067b-4048-9f88-961afed12478
+
+
+## Overview
+This project is a real-time live streaming digital human powered by few-shot learning. It is designed to run smoothly on all 30 and 40 series graphics cards, ensuring a seamless and interactive live streaming experience.
+
+### Key Features
+- **Real-time Performance**: The digital human can interact in real-time with 25+ fps for common NVIDIA 30 and 40 series GPUs
+- **Few-shot Learning**: The system is capable of learning from a few examples to generate realistic responses.
+## Usage
+
+### Create Environment and Unzip the Model File
+First, navigate to the `checkpoint` directory and unzip the model file:
+```bash
+conda create -n dh_live python=3.12
+conda activate dh_live
+pip install torch --index-url https://download.pytorch.org/whl/cu124
+pip install -r requirements.txt
+cd checkpoint
+```
+unzip checkpoint files from [baiduNetDisk](https://pan.baidu.com/s/1jH3WrIAfwI3U5awtnt9KPQ?pwd=ynd7)
+### Prepare Your Video
+Next, prepare your video using the data_preparation script. Replace YOUR_VIDEO_PATH with the path to your video:
+```bash
+python data_preparation.py YOUR_VIDEO_PATH
+```
+The result (video_info) will be stored in the ./video_data directory.
+### Run with Audio File
+Run the demo script with an audio file. Make sure the audio file is in .wav format with a sample rate of 16kHz and 16-bit single channel. Replace video_data/test with the path to your video_info file, video_data/audio0.wav with the path to your audio file, and 1.mp4 with the desired output video path:
+```bash
+python demo.py video_data/test video_data/audio0.wav 1.mp4
+```
+### Real-Time Run with Microphone
+For real-time operation using a microphone, simply run the following command:
+```bash
+python demo_avatar.py
+```
+
+## Acknowledgements
+We would like to thank the contributors of [Wav2Lip](https://github.com/Rudrabha/Wav2Lip), [DINet](https://github.com/MRzzm/DINet), [LiveSpeechPortrait](https://github.com/YuanxunLu/LiveSpeechPortraits) repositories, for their open research and contributions.
+
+## License
+DH_live is licensed under the MIT License.
+
+DH_live_mini is licensed under the Apache 2.0.
+## 联系
+| 进入QQ群聊,分享看法和最新咨询。 | 加我好友,请备注“进群”,拉你进去微信交流群。 |
+|-------------------|----------------------|
+| ![QQ群聊](https://github.com/user-attachments/assets/29bfef3f-438a-4b9f-ba09-e1926d1669cb) | ![微信交流群](https://github.com/user-attachments/assets/b1f24ebb-153b-44b1-b522-14f765154110) |
diff --git a/data/face_pts_mean.txt b/data/face_pts_mean.txt
new file mode 100644
index 0000000..6156796
--- /dev/null
+++ b/data/face_pts_mean.txt
@@ -0,0 +1,478 @@
+500.0 701.5 110.2
+500.0 588.2 29.8
+500.0 624.2 113.5
+472.2 470.8 75.8
+500.0 551.6 18.9
+500.0 504.4 32.9
+500.0 389.6 124.6
+266.6 375.6 255.2
+500.0 295.9 148.2
+500.0 247.2 142.4
+500.0 78.0 180.5
+500.0 715.3 114.0
+500.0 729.9 124.9
+500.0 739.6 140.7
+500.0 779.9 151.7
+500.0 797.2 147.6
+500.0 818.5 142.1
+500.0 839.8 149.8
+500.0 867.8 184.2
+500.0 607.1 46.5
+470.4 606.8 91.8
+140.2 243.2 416.6
+356.6 405.7 220.1
+324.8 408.5 222.6
+293.6 407.6 232.1
+252.1 388.8 260.1
+383.6 398.0 223.9
+309.4 302.6 209.1
+346.6 307.0 209.2
+274.6 309.0 220.3
+252.1 324.0 234.0
+223.9 412.4 276.5
+377.4 906.5 221.4
+254.6 367.0 266.4
+125.2 398.4 426.0
+186.7 386.1 310.9
+334.1 559.7 186.7
+460.9 695.2 115.1
+465.3 729.6 130.0
+422.6 710.5 135.2
+398.4 726.6 161.4
+436.1 733.8 143.9
+414.1 740.5 168.1
+350.4 790.8 217.8
+473.1 587.5 32.8
+468.6 552.3 22.9
+205.6 290.1 245.7
+401.5 469.0 183.1
+398.6 579.0 114.5
+395.6 560.0 124.7
+234.5 556.2 228.8
+470.1 508.3 43.3
+282.4 247.9 188.2
+237.0 262.0 214.6
+173.4 178.9 351.5
+427.6 280.1 158.4
+378.4 322.9 218.7
+327.4 752.8 223.3
+167.8 734.2 510.8
+424.0 599.4 127.0
+449.6 609.9 123.7
+372.3 755.8 219.1
+381.0 755.8 209.7
+219.2 238.8 230.9
+397.6 595.0 132.7
+344.0 250.4 168.7
+338.6 221.1 162.2
+307.9 95.4 223.1
+196.4 211.8 282.4
+327.3 160.9 190.7
+185.9 274.5 274.8
+162.1 263.7 340.9
+462.1 713.7 118.7
+429.1 723.0 137.9
+405.7 733.8 161.8
+431.6 606.0 134.1
+376.8 755.8 214.1
+389.4 770.3 196.1
+385.3 755.7 208.8
+438.7 587.3 81.2
+420.7 744.5 173.8
+442.1 740.2 157.5
+468.6 738.7 144.9
+453.8 864.8 185.3
+458.0 835.2 151.8
+460.2 814.0 145.9
+463.8 793.0 151.9
+468.1 777.5 155.9
+420.5 768.3 182.2
+413.1 775.0 178.0
+404.6 785.0 173.8
+397.8 796.2 180.2
+363.1 688.8 172.6
+127.1 556.0 561.8
+500.0 615.5 90.0
+404.6 763.2 198.6
+397.0 766.3 195.8
+458.7 623.5 122.3
+408.5 616.0 157.0
+454.4 617.0 122.2
+366.2 489.9 194.2
+311.4 514.0 203.8
+390.2 576.2 143.4
+226.3 128.2 282.6
+248.7 175.8 233.4
+270.8 219.8 194.3
+375.8 819.5 204.0
+417.6 231.3 146.1
+408.2 160.0 166.3
+396.1 80.8 188.6
+267.3 401.3 246.6
+188.4 438.0 294.8
+401.5 389.6 228.5
+219.8 339.9 263.2
+425.0 445.5 171.2
+417.8 565.2 82.1
+151.9 466.5 331.4
+210.6 463.5 264.0
+252.9 476.8 232.9
+316.5 470.8 218.2
+362.8 455.8 210.8
+397.3 439.3 202.1
+468.7 398.1 137.3
+157.8 542.2 321.0
+193.8 334.6 279.5
+483.9 606.0 48.5
+404.6 504.4 168.0
+116.1 395.5 538.4
+423.4 420.2 197.3
+387.0 578.5 177.1
+239.0 367.2 272.9
+415.9 542.1 94.9
+141.3 642.8 545.4
+401.2 377.3 237.1
+442.2 521.1 63.0
+240.9 821.1 337.1
+242.6 860.2 395.8
+127.6 550.7 440.7
+199.3 772.5 376.6
+142.3 326.2 393.2
+371.6 939.5 239.9
+487.4 614.2 92.2
+374.6 531.0 180.0
+158.6 393.1 344.5
+297.6 385.6 234.9
+324.4 387.8 226.7
+382.5 775.3 201.5
+166.8 614.8 330.6
+430.8 988.5 249.8
+333.1 938.2 312.8
+291.5 906.2 348.9
+500.0 162.0 158.9
+500.0 996.2 240.7
+350.8 385.9 225.2
+375.8 381.8 229.8
+392.6 379.7 236.6
+170.2 327.6 313.6
+372.8 355.1 224.7
+345.1 346.5 219.1
+317.4 345.0 220.8
+289.9 349.5 229.2
+272.8 356.6 240.1
+122.5 311.7 485.2
+279.4 381.0 245.7
+500.0 652.6 120.9
+394.2 667.7 154.4
+423.9 593.3 114.8
+454.8 655.0 124.2
+500.0 343.4 149.1
+284.5 867.4 307.1
+326.4 903.1 275.6
+429.2 966.8 208.8
+203.4 807.4 455.2
+392.2 368.3 232.0
+447.3 455.1 125.6
+500.0 973.9 201.1
+377.8 967.1 274.9
+140.9 630.4 434.6
+441.8 773.2 167.7
+434.6 784.7 163.4
+428.1 800.7 158.8
+423.3 819.3 164.4
+409.4 845.8 190.5
+396.3 747.9 190.2
+388.4 744.8 190.3
+381.8 741.0 190.3
+339.9 717.7 197.4
+211.9 634.2 263.6
+447.4 419.2 156.6
+426.4 347.2 213.3
+406.0 353.0 226.2
+403.4 749.6 193.6
+212.1 721.4 314.0
+456.9 345.2 171.1
+392.1 874.4 208.8
+500.0 465.4 64.6
+470.1 436.4 103.5
+500.0 429.0 95.9
+424.6 511.5 124.8
+500.0 940.8 184.4
+500.0 901.5 185.2
+443.8 897.1 191.5
+320.2 803.3 237.8
+359.4 607.5 185.9
+352.3 843.3 224.8
+283.1 602.8 200.4
+329.4 644.0 192.2
+258.2 661.2 226.9
+433.5 934.8 192.9
+405.2 532.0 148.2
+293.4 829.1 269.1
+334.8 869.5 249.6
+295.1 756.7 239.1
+178.8 676.5 342.4
+254.2 761.9 271.6
+162.2 704.5 419.8
+305.8 690.8 208.7
+426.7 479.2 148.4
+428.6 581.2 74.8
+409.4 590.7 110.6
+441.4 557.0 51.4
+400.1 310.8 203.6
+346.2 286.2 198.4
+298.7 282.1 201.2
+259.4 290.6 215.2
+232.5 309.3 236.1
+216.5 376.2 286.4
+121.6 473.8 435.0
+241.7 427.6 259.0
+275.4 437.9 238.9
+319.4 437.1 225.1
+360.4 428.8 218.6
+392.1 417.5 217.8
+414.2 406.1 215.6
+120.2 475.0 561.5
+410.2 600.4 127.1
+447.1 487.4 98.8
+450.6 582.8 48.9
+468.0 600.7 62.0
+451.2 589.2 64.9
+418.9 611.0 138.4
+473.9 603.8 53.1
+477.5 612.0 92.2
+413.2 378.0 231.9
+431.5 386.1 211.7
+443.0 392.0 188.4
+262.6 362.1 251.6
+238.2 342.3 253.4
+527.8 470.8 75.8
+733.5 375.6 255.2
+529.6 606.8 91.8
+859.8 243.2 416.6
+643.5 405.7 220.1
+675.2 408.5 222.6
+706.4 407.6 232.1
+747.9 388.8 260.1
+616.4 398.0 223.9
+690.5 302.6 209.1
+653.4 307.0 209.2
+725.4 309.0 220.3
+748.0 324.0 234.0
+776.1 412.4 276.5
+622.5 906.5 221.4
+745.4 367.0 266.4
+874.8 398.4 426.0
+813.3 386.1 310.9
+665.9 559.7 186.7
+539.1 695.2 115.1
+534.7 729.6 130.0
+577.4 710.5 135.2
+601.6 726.6 161.4
+563.9 733.8 143.9
+586.0 740.5 168.1
+649.6 790.8 217.8
+526.9 587.5 32.8
+531.4 552.3 22.9
+794.5 290.1 245.7
+598.5 469.0 183.1
+601.4 579.0 114.5
+604.4 560.0 124.7
+765.5 556.2 228.8
+529.9 508.3 43.3
+717.6 247.9 188.2
+763.0 262.0 214.6
+826.6 178.9 351.5
+572.5 280.1 158.4
+621.6 322.9 218.7
+672.6 752.8 223.3
+832.2 734.2 510.8
+576.0 599.4 127.0
+550.5 609.9 123.7
+627.7 755.8 219.1
+619.0 755.8 209.7
+780.8 238.8 230.9
+602.5 595.0 132.7
+656.0 250.4 168.7
+661.4 221.1 162.2
+692.0 95.4 223.1
+803.5 211.8 282.4
+672.7 160.9 190.7
+814.1 274.5 274.8
+837.9 263.7 340.9
+537.9 713.7 118.7
+571.0 723.0 137.9
+594.3 733.8 161.8
+568.4 606.0 134.1
+623.2 755.8 214.1
+610.6 770.3 196.1
+614.7 755.7 208.8
+561.3 587.3 81.2
+579.3 744.5 173.8
+558.0 740.2 157.5
+531.5 738.7 144.9
+546.2 864.8 185.3
+542.0 835.2 151.8
+539.8 814.0 145.9
+536.2 793.0 151.9
+531.9 777.5 155.9
+579.5 768.3 182.2
+586.9 775.0 178.0
+595.4 785.0 173.8
+602.2 796.2 180.2
+636.9 688.8 172.6
+872.9 556.0 561.8
+595.4 763.2 198.6
+603.0 766.3 195.8
+541.3 623.5 122.3
+591.5 616.0 157.0
+545.6 617.0 122.2
+633.8 489.9 194.2
+688.6 514.0 203.8
+609.8 576.2 143.4
+773.7 128.2 282.6
+751.3 175.8 233.4
+729.2 219.8 194.3
+624.2 819.5 204.0
+582.4 231.3 146.1
+591.8 160.0 166.3
+604.0 80.8 188.6
+732.7 401.3 246.6
+811.6 438.0 294.8
+598.5 389.6 228.5
+780.2 339.9 263.2
+575.0 445.5 171.2
+582.2 565.2 82.1
+848.1 466.5 331.4
+789.4 463.5 264.0
+747.0 476.8 232.9
+683.5 470.8 218.2
+637.2 455.8 210.8
+602.7 439.3 202.1
+531.3 398.1 137.3
+842.2 542.2 321.0
+806.2 334.6 279.5
+516.1 606.0 48.5
+595.5 504.4 168.0
+883.9 395.5 538.4
+576.6 420.2 197.3
+613.0 578.5 177.1
+761.0 367.2 272.9
+584.0 542.1 94.9
+858.7 642.8 545.4
+598.8 377.3 237.1
+557.8 521.1 63.0
+759.1 821.1 337.1
+757.4 860.2 395.8
+872.4 550.7 440.7
+800.7 772.5 376.6
+857.7 326.2 393.2
+628.4 939.5 239.9
+512.6 614.2 92.2
+625.4 531.0 180.0
+841.5 393.1 344.5
+702.5 385.6 234.9
+675.6 387.8 226.7
+617.5 775.3 201.5
+833.2 614.8 330.6
+569.2 988.5 249.8
+666.9 938.2 312.8
+708.5 906.2 348.9
+649.2 385.9 225.2
+624.2 381.8 229.8
+607.5 379.7 236.6
+829.8 327.6 313.6
+627.2 355.1 224.7
+654.9 346.5 219.1
+682.6 345.0 220.8
+710.0 349.5 229.2
+727.2 356.6 240.1
+877.5 311.7 485.2
+720.6 381.0 245.7
+605.8 667.7 154.4
+576.0 593.3 114.8
+545.2 655.0 124.2
+715.5 867.4 307.1
+673.6 903.1 275.6
+570.8 966.8 208.8
+796.6 807.4 455.2
+607.8 368.3 232.0
+552.7 455.1 125.6
+622.2 967.1 274.9
+859.0 630.4 434.6
+558.2 773.2 167.7
+565.4 784.7 163.4
+572.0 800.7 158.8
+576.7 819.3 164.4
+590.6 845.8 190.5
+603.7 747.9 190.2
+611.5 744.8 190.3
+618.2 741.0 190.3
+660.1 717.7 197.4
+788.1 634.2 263.6
+552.6 419.2 156.6
+573.6 347.2 213.3
+594.0 353.0 226.2
+596.6 749.6 193.6
+787.9 721.4 314.0
+543.0 345.2 171.1
+607.9 874.4 208.8
+529.9 436.4 103.5
+575.5 511.5 124.8
+556.2 897.1 191.5
+679.8 803.3 237.8
+640.6 607.5 185.9
+647.7 843.3 224.8
+717.0 602.8 200.4
+670.6 644.0 192.2
+741.8 661.2 226.9
+566.5 934.8 192.9
+594.8 532.0 148.2
+706.5 829.1 269.1
+665.2 869.5 249.6
+705.0 756.7 239.1
+821.2 676.5 342.4
+745.8 761.9 271.6
+837.8 704.5 419.8
+694.2 690.8 208.7
+573.3 479.2 148.4
+571.5 581.2 74.8
+590.5 590.7 110.6
+558.5 557.0 51.4
+599.9 310.8 203.6
+653.8 286.2 198.4
+701.3 282.1 201.2
+740.6 290.6 215.2
+767.5 309.3 236.1
+783.5 376.2 286.4
+878.5 473.8 435.0
+758.3 427.6 259.0
+724.5 437.9 238.9
+680.6 437.1 225.1
+639.6 428.8 218.6
+607.9 417.5 217.8
+585.8 406.1 215.6
+879.8 475.0 561.5
+589.8 600.4 127.1
+552.9 487.4 98.8
+549.4 582.8 48.9
+532.0 600.7 62.0
+548.8 589.2 64.9
+581.1 611.0 138.4
+526.1 603.8 53.1
+522.5 612.0 92.2
+586.8 378.0 231.9
+568.5 386.1 211.7
+557.0 392.0 188.4
+737.4 362.1 251.6
+761.8 342.3 253.4
+328.8 363.2 235.9
+361.5 362.8 235.9
+328.6 333.5 235.9
+295.7 363.5 235.9
+328.8 392.9 235.9
+671.2 363.2 235.9
+704.3 363.5 235.9
+671.4 333.5 235.9
+638.5 362.8 235.9
+671.2 392.9 235.9
diff --git a/data/face_pts_mean_mainKps.txt b/data/face_pts_mean_mainKps.txt
new file mode 100644
index 0000000..9dd217d
--- /dev/null
+++ b/data/face_pts_mean_mainKps.txt
@@ -0,0 +1,141 @@
+8.660000000000000000e+02 3.320000000000000000e+02 1.300000000000000000e+01
+8.500000000000000000e+02 3.170000000000000000e+02 -3.000000000000000000e+00
+8.260000000000000000e+02 3.110000000000000000e+02 -1.600000000000000000e+01
+7.930000000000000000e+02 3.140000000000000000e+02 -2.600000000000000000e+01
+7.470000000000000000e+02 3.300000000000000000e+02 -3.100000000000000000e+01
+7.520000000000000000e+02 3.050000000000000000e+02 -3.700000000000000000e+01
+7.960000000000000000e+02 2.990000000000000000e+02 -2.900000000000000000e+01
+8.320000000000000000e+02 2.970000000000000000e+02 -1.300000000000000000e+01
+8.580000000000000000e+02 3.060000000000000000e+02 5.000000000000000000e+00
+8.750000000000000000e+02 3.240000000000000000e+02 2.800000000000000000e+01
+5.480000000000000000e+02 3.260000000000000000e+02 1.800000000000000000e+01
+5.640000000000000000e+02 3.120000000000000000e+02 1.000000000000000000e+00
+5.880000000000000000e+02 3.060000000000000000e+02 -1.300000000000000000e+01
+6.210000000000000000e+02 3.080000000000000000e+02 -2.400000000000000000e+01
+6.670000000000000000e+02 3.250000000000000000e+02 -3.000000000000000000e+01
+6.620000000000000000e+02 2.990000000000000000e+02 -3.600000000000000000e+01
+6.190000000000000000e+02 2.930000000000000000e+02 -2.700000000000000000e+01
+5.820000000000000000e+02 2.910000000000000000e+02 -1.000000000000000000e+01
+5.550000000000000000e+02 3.000000000000000000e+02 1.000000000000000000e+01
+5.390000000000000000e+02 3.180000000000000000e+02 3.300000000000000000e+01
+7.460000000000000000e+02 4.170000000000000000e+02 -2.500000000000000000e+01
+7.570000000000000000e+02 4.480000000000000000e+02 -2.700000000000000000e+01
+7.680000000000000000e+02 4.870000000000000000e+02 -2.200000000000000000e+01
+7.550000000000000000e+02 5.070000000000000000e+02 -3.300000000000000000e+01
+7.260000000000000000e+02 5.120000000000000000e+02 -5.100000000000000000e+01
+7.030000000000000000e+02 5.120000000000000000e+02 -5.600000000000000000e+01
+6.790000000000000000e+02 5.110000000000000000e+02 -5.100000000000000000e+01
+6.520000000000000000e+02 5.050000000000000000e+02 -3.200000000000000000e+01
+6.410000000000000000e+02 4.840000000000000000e+02 -2.100000000000000000e+01
+6.520000000000000000e+02 4.460000000000000000e+02 -2.600000000000000000e+01
+6.650000000000000000e+02 4.160000000000000000e+02 -2.300000000000000000e+01
+7.060000000000000000e+02 3.870000000000000000e+02 -4.900000000000000000e+01
+7.050000000000000000e+02 4.090000000000000000e+02 -6.500000000000000000e+01
+7.050000000000000000e+02 4.280000000000000000e+02 -8.200000000000000000e+01
+7.040000000000000000e+02 4.480000000000000000e+02 -9.900000000000000000e+01
+7.030000000000000000e+02 4.740000000000000000e+02 -1.070000000000000000e+02
+6.324848484848484986e+02 5.827878787878787534e+02 3.545454545454545414e+00
+6.364040404040404155e+02 5.946868686868687064e+02 -5.989898989898989612e+00
+6.433333333333333712e+02 6.077878787878787534e+02 -1.729292929292929415e+01
+6.563232323232323324e+02 6.224848484848484986e+02 -2.594949494949494806e+01
+6.754141414141414543e+02 6.323030303030302548e+02 -3.345454545454545325e+01
+6.995353535353535790e+02 6.354242424242423795e+02 -3.512121212121212466e+01
+7.245050505050504626e+02 6.321717171717172050e+02 -3.454545454545454675e+01
+7.451818181818181301e+02 6.218888888888889142e+02 -2.800000000000000000e+01
+7.605050505050504626e+02 6.067676767676767895e+02 -1.987878787878787890e+01
+7.698888888888889142e+02 5.930909090909091219e+02 -9.252525252525252597e+00
+7.758484848484848726e+02 5.806767676767676676e+02 -2.222222222222222099e-01
+7.710808080808080831e+02 5.711313131313131635e+02 -1.558585858585858652e+01
+7.615151515151515014e+02 5.625555555555555429e+02 -3.061616161616161591e+01
+7.474040404040404155e+02 5.534141414141414543e+02 -4.424242424242424221e+01
+7.245353535353535790e+02 5.453232323232323324e+02 -5.421212121212121104e+01
+7.015050505050504626e+02 5.487474747474747119e+02 -5.628282828282828376e+01
+6.792626262626262132e+02 5.458989898989899530e+02 -5.314141414141413833e+01
+6.583232323232323324e+02 5.545757575757576205e+02 -4.211111111111111427e+01
+6.454343434343434183e+02 5.639797979797980361e+02 -2.765656565656565746e+01
+6.369494949494949196e+02 5.729292929292929557e+02 -1.195959595959596022e+01
+6.399898989898989612e+02 5.829696969696969973e+02 -2.060606060606060552e+00
+6.498181818181818699e+02 5.886161616161616621e+02 -7.171717171717172157e+00
+6.575353535353535790e+02 5.926363636363636260e+02 -1.580808080808080796e+01
+6.682222222222221717e+02 5.965050505050504626e+02 -2.379797979797979934e+01
+6.823636363636363740e+02 5.992626262626262132e+02 -3.029292929292929415e+01
+7.001515151515151274e+02 6.004949494949495374e+02 -3.307070707070707272e+01
+7.189191919191919169e+02 5.986262626262625872e+02 -3.135353535353535293e+01
+7.344343434343434183e+02 5.951818181818181301e+02 -2.544444444444444287e+01
+7.469797979797980361e+02 5.910505050505050804e+02 -1.815151515151515227e+01
+7.564343434343434183e+02 5.868585858585859114e+02 -1.007070707070707094e+01
+7.680000000000000000e+02 5.807878787878787534e+02 -5.333333333333333037e+00
+7.580707070707070443e+02 5.764747474747474598e+02 -1.369696969696969724e+01
+7.479898989898989612e+02 5.731616161616161662e+02 -2.410101010101010033e+01
+7.355858585858585457e+02 5.706969696969697452e+02 -3.276767676767676818e+01
+7.201616161616161662e+02 5.697777777777778283e+02 -3.927272727272727337e+01
+7.016868686868687064e+02 5.645858585858585457e+02 -4.913131313131312794e+01
+6.847070707070706703e+02 5.702525252525252881e+02 -3.825252525252525260e+01
+6.703434343434342964e+02 5.717171717171717091e+02 -3.096969696969696884e+01
+6.591111111111110858e+02 5.745858585858585457e+02 -2.187878787878787890e+01
+6.499898989898989612e+02 5.783030303030302548e+02 -1.081818181818181834e+01
+8.430000000000000000e+02 3.720000000000000000e+02 2.500000000000000000e+01
+8.360000000000000000e+02 3.780000000000000000e+02 1.900000000000000000e+01
+8.290000000000000000e+02 3.830000000000000000e+02 1.400000000000000000e+01
+8.190000000000000000e+02 3.860000000000000000e+02 9.000000000000000000e+00
+8.040000000000000000e+02 3.870000000000000000e+02 5.000000000000000000e+00
+7.890000000000000000e+02 3.850000000000000000e+02 4.000000000000000000e+00
+7.740000000000000000e+02 3.830000000000000000e+02 7.000000000000000000e+00
+7.640000000000000000e+02 3.820000000000000000e+02 1.100000000000000000e+01
+7.590000000000000000e+02 3.800000000000000000e+02 1.100000000000000000e+01
+7.650000000000000000e+02 3.740000000000000000e+02 9.000000000000000000e+00
+7.760000000000000000e+02 3.640000000000000000e+02 5.000000000000000000e+00
+7.920000000000000000e+02 3.570000000000000000e+02 2.000000000000000000e+00
+8.090000000000000000e+02 3.550000000000000000e+02 2.000000000000000000e+00
+8.250000000000000000e+02 3.580000000000000000e+02 6.000000000000000000e+00
+8.340000000000000000e+02 3.640000000000000000e+02 1.200000000000000000e+01
+8.390000000000000000e+02 3.680000000000000000e+02 1.800000000000000000e+01
+5.740000000000000000e+02 3.660000000000000000e+02 2.900000000000000000e+01
+5.800000000000000000e+02 3.720000000000000000e+02 2.300000000000000000e+01
+5.860000000000000000e+02 3.770000000000000000e+02 1.800000000000000000e+01
+5.960000000000000000e+02 3.800000000000000000e+02 1.200000000000000000e+01
+6.110000000000000000e+02 3.820000000000000000e+02 8.000000000000000000e+00
+6.260000000000000000e+02 3.810000000000000000e+02 7.000000000000000000e+00
+6.400000000000000000e+02 3.780000000000000000e+02 1.000000000000000000e+01
+6.500000000000000000e+02 3.770000000000000000e+02 1.300000000000000000e+01
+6.550000000000000000e+02 3.760000000000000000e+02 1.300000000000000000e+01
+6.500000000000000000e+02 3.690000000000000000e+02 1.100000000000000000e+01
+6.390000000000000000e+02 3.590000000000000000e+02 7.000000000000000000e+00
+6.240000000000000000e+02 3.520000000000000000e+02 4.000000000000000000e+00
+6.080000000000000000e+02 3.500000000000000000e+02 5.000000000000000000e+00
+5.920000000000000000e+02 3.530000000000000000e+02 1.000000000000000000e+01
+5.830000000000000000e+02 3.580000000000000000e+02 1.600000000000000000e+01
+5.780000000000000000e+02 3.620000000000000000e+02 2.200000000000000000e+01
+9.080000000000000000e+02 4.380000000000000000e+02 1.790000000000000000e+02
+9.070000000000000000e+02 4.820000000000000000e+02 1.790000000000000000e+02
+9.010000000000000000e+02 5.300000000000000000e+02 1.710000000000000000e+02
+8.880000000000000000e+02 5.820000000000000000e+02 1.550000000000000000e+02
+8.680000000000000000e+02 6.240000000000000000e+02 1.270000000000000000e+02
+8.470000000000000000e+02 6.540000000000000000e+02 9.900000000000000000e+01
+8.190000000000000000e+02 6.800000000000000000e+02 7.700000000000000000e+01
+7.950000000000000000e+02 6.990000000000000000e+02 6.000000000000000000e+01
+7.690000000000000000e+02 7.160000000000000000e+02 4.100000000000000000e+01
+7.380000000000000000e+02 7.300000000000000000e+02 2.900000000000000000e+01
+7.000000000000000000e+02 7.340000000000000000e+02 2.500000000000000000e+01
+6.610000000000000000e+02 7.280000000000000000e+02 3.000000000000000000e+01
+6.330000000000000000e+02 7.130000000000000000e+02 4.300000000000000000e+01
+6.100000000000000000e+02 6.930000000000000000e+02 6.300000000000000000e+01
+5.890000000000000000e+02 6.730000000000000000e+02 8.000000000000000000e+01
+5.640000000000000000e+02 6.450000000000000000e+02 1.020000000000000000e+02
+5.450000000000000000e+02 6.140000000000000000e+02 1.310000000000000000e+02
+5.270000000000000000e+02 5.710000000000000000e+02 1.590000000000000000e+02
+5.140000000000000000e+02 5.190000000000000000e+02 1.760000000000000000e+02
+5.080000000000000000e+02 4.710000000000000000e+02 1.840000000000000000e+02
+5.060000000000000000e+02 4.270000000000000000e+02 1.840000000000000000e+02
+7.740000000000000000e+02 4.620000000000000000e+02 -2.100000000000000000e+01
+7.960000000000000000e+02 4.780000000000000000e+02 -1.700000000000000000e+01
+8.240000000000000000e+02 5.020000000000000000e+02 -1.000000000000000000e+01
+8.370000000000000000e+02 5.350000000000000000e+02 7.000000000000000000e+00
+8.400000000000000000e+02 5.930000000000000000e+02 3.400000000000000000e+01
+8.220000000000000000e+02 6.570000000000000000e+02 5.700000000000000000e+01
+5.860000000000000000e+02 6.490000000000000000e+02 6.000000000000000000e+01
+5.700000000000000000e+02 5.850000000000000000e+02 3.900000000000000000e+01
+5.720000000000000000e+02 5.280000000000000000e+02 1.100000000000000000e+01
+5.850000000000000000e+02 4.970000000000000000e+02 -6.000000000000000000e+00
+6.130000000000000000e+02 4.740000000000000000e+02 -1.500000000000000000e+01
+6.350000000000000000e+02 4.590000000000000000e+02 -1.900000000000000000e+01
diff --git a/data/pca.pkl b/data/pca.pkl
new file mode 100644
index 0000000..ed2db82
Binary files /dev/null and b/data/pca.pkl differ
diff --git a/data_preparation.py b/data_preparation.py
new file mode 100644
index 0000000..866c3ae
--- /dev/null
+++ b/data_preparation.py
@@ -0,0 +1,230 @@
+import uuid
+import tqdm
+import numpy as np
+import cv2
+import sys
+import os
+import math
+import pickle
+import mediapipe as mp
+mp_face_mesh = mp.solutions.face_mesh
+mp_face_detection = mp.solutions.face_detection
+
+def detect_face(frame):
+ # 剔除掉多个人脸、大角度侧脸(鼻子不在两个眼之间)、部分人脸框在画面外、人脸像素低于80*80的
+ with mp_face_detection.FaceDetection(
+ model_selection=1, min_detection_confidence=0.5) as face_detection:
+ results = face_detection.process(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
+ if not results.detections or len(results.detections) > 1:
+ return -1, None
+ rect = results.detections[0].location_data.relative_bounding_box
+ out_rect = [rect.xmin, rect.xmin + rect.width, rect.ymin, rect.ymin + rect.height]
+ nose_ = mp_face_detection.get_key_point(
+ results.detections[0], mp_face_detection.FaceKeyPoint.NOSE_TIP)
+ l_eye_ = mp_face_detection.get_key_point(
+ results.detections[0], mp_face_detection.FaceKeyPoint.LEFT_EYE)
+ r_eye_ = mp_face_detection.get_key_point(
+ results.detections[0], mp_face_detection.FaceKeyPoint.RIGHT_EYE)
+ # print(nose_, l_eye_, r_eye_)
+ if nose_.x > l_eye_.x or nose_.x < r_eye_.x:
+ return -2, out_rect
+
+ h, w = frame.shape[:2]
+ # print(frame.shape)
+ if rect.xmin < 0 or rect.ymin < 0 or rect.xmin + rect.width > w or rect.ymin + rect.height > h:
+ return -3, out_rect
+ if rect.width * w < 100 or rect.height * h < 100:
+ return -4, out_rect
+ return 1, out_rect
+
+
+def calc_face_interact(face0, face1):
+ x_min = min(face0[0], face1[0])
+ x_max = max(face0[1], face1[1])
+ y_min = min(face0[2], face1[2])
+ y_max = max(face0[3], face1[3])
+ tmp0 = ((face0[1] - face0[0]) * (face0[3] - face0[2])) / ((x_max - x_min) * (y_max - y_min))
+ tmp1 = ((face1[1] - face1[0]) * (face1[3] - face1[2])) / ((x_max - x_min) * (y_max - y_min))
+ return min(tmp0, tmp1)
+
+
+def detect_face_mesh(frame):
+ with mp_face_mesh.FaceMesh(
+ static_image_mode=True,
+ max_num_faces=1,
+ refine_landmarks=True,
+ min_detection_confidence=0.5) as face_mesh:
+ results = face_mesh.process(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
+ pts_3d = np.zeros([478, 3])
+ if not results.multi_face_landmarks:
+ print("****** WARNING! No face detected! ******")
+ else:
+ image_height, image_width = frame.shape[:2]
+ for face_landmarks in results.multi_face_landmarks:
+ for index_, i in enumerate(face_landmarks.landmark):
+ x_px = min(math.floor(i.x * image_width), image_width - 1)
+ y_px = min(math.floor(i.y * image_height), image_height - 1)
+ z_px = min(math.floor(i.z * image_width), image_width - 1)
+ pts_3d[index_] = np.array([x_px, y_px, z_px])
+ return pts_3d
+
+
+def ExtractFromVideo(video_path, circle = False):
+ cap = cv2.VideoCapture(video_path)
+ if not cap.isOpened():
+ return 0
+
+ dir_path = os.path.dirname(video_path)
+ vid_width = cap.get(cv2.CAP_PROP_FRAME_WIDTH) # 宽度
+ vid_height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT) # 高度
+
+ totalFrames = cap.get(cv2.CAP_PROP_FRAME_COUNT) # 总帧数
+ totalFrames = int(totalFrames)
+ pts_3d = np.zeros([totalFrames, 478, 3])
+ frame_index = 0
+ face_rect_list = []
+ mat_list = []
+ model_name = os.path.basename(video_path)[:-4]
+
+ # os.makedirs("../preparation/{}/image".format(model_name))
+ for frame_index in tqdm.tqdm(range(totalFrames)):
+ ret, frame = cap.read() # 按帧读取视频
+ # #到视频结尾时终止
+ if ret is False:
+ break
+ # cv2.imwrite("../preparation/{}/image/{:0>6d}.png".format(model_name, frame_index), frame)
+ tag_, rect = detect_face(frame)
+ if frame_index == 0 and tag_ != 1:
+ print("第一帧人脸检测异常,请剔除掉多个人脸、大角度侧脸(鼻子不在两个眼之间)、部分人脸框在画面外、人脸像素低于80*80")
+ pts_3d = -1
+ break
+ elif tag_ == -1: # 有时候人脸检测会失败,就用上一帧的结果替代这一帧的结果
+ rect = face_rect_list[-1]
+ elif tag_ != 1:
+ print("第{}帧人脸检测异常,请剔除掉多个人脸、大角度侧脸(鼻子不在两个眼之间)、部分人脸框在画面外、人脸像素低于80*80, tag: {}".format(frame_index, tag_))
+ # exit()
+ if len(face_rect_list) > 0:
+ face_area_inter = calc_face_interact(face_rect_list[-1], rect)
+ # print(frame_index, face_area_inter)
+ if face_area_inter < 0.6:
+ print("人脸区域变化幅度太大,请复查,超出值为{}, frame_num: {}".format(face_area_inter, frame_index))
+ pts_3d = -2
+ break
+
+ face_rect_list.append(rect)
+
+ x_min = rect[0] * vid_width
+ y_min = rect[2] * vid_height
+ x_max = rect[1] * vid_width
+ y_max = rect[3] * vid_height
+ seq_w, seq_h = x_max - x_min, y_max - y_min
+ x_mid, y_mid = (x_min + x_max) / 2, (y_min + y_max) / 2
+ # x_min = int(max(0, x_mid - seq_w * 0.65))
+ # y_min = int(max(0, y_mid - seq_h * 0.4))
+ # x_max = int(min(vid_width, x_mid + seq_w * 0.65))
+ # y_max = int(min(vid_height, y_mid + seq_h * 0.8))
+ crop_size = int(max(seq_w * 1.35, seq_h * 1.35))
+ x_min = int(max(0, x_mid - crop_size * 0.5))
+ y_min = int(max(0, y_mid - crop_size * 0.45))
+ x_max = int(min(vid_width, x_min + crop_size))
+ y_max = int(min(vid_height, y_min + crop_size))
+
+ frame_face = frame[y_min:y_max, x_min:x_max]
+ print(y_min, y_max, x_min, x_max)
+ # cv2.imshow("s", frame_face)
+ # cv2.waitKey(20)
+ frame_kps = detect_face_mesh(frame_face)
+ pts_3d[frame_index] = frame_kps + np.array([x_min, y_min, 0])
+ cap.release() # 释放视频对象
+ return pts_3d
+
+
+def CirculateVideo(video_in_path, video_out_path, export_imgs = False):
+ # 1 视频转换为25FPS, 并折叠循环拼接
+ front_video_path = "front.mp4"
+ back_video_path = "back.mp4"
+ # ffmpeg_cmd = "ffmpeg -i {} -r 25 -ss 00:00:00 -t 00:02:00 -an -loglevel quiet -y {}".format(video_in_path, front_video_path)
+ ffmpeg_cmd = "ffmpeg -i {} -r 25 -an -loglevel quiet -y {}".format(video_in_path, front_video_path)
+ os.system(ffmpeg_cmd)
+
+ # front_video_path = video_in_path
+
+ cap = cv2.VideoCapture(front_video_path)
+ vid_width = cap.get(cv2.CAP_PROP_FRAME_WIDTH) # 宽度
+ vid_height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT) # 高度
+ frames = cap.get(cv2.CAP_PROP_FRAME_COUNT)
+ cap.release()
+
+
+ ffmpeg_cmd = "ffmpeg -i {} -vf reverse -y {}".format(front_video_path, back_video_path)
+ os.system(ffmpeg_cmd)
+ ffmpeg_cmd = "ffmpeg -f concat -i {} -c:v copy -y {}".format("video_concat.txt", video_out_path)
+ os.system(ffmpeg_cmd)
+ # exit()
+ print("正向视频帧数:", frames)
+ pts_3d = ExtractFromVideo(front_video_path)
+ if type(pts_3d) is np.ndarray and len(pts_3d) == frames:
+ print("关键点已提取")
+ pts_3d = np.concatenate([pts_3d, pts_3d[::-1]], axis=0)
+ Path_output_pkl = "{}/keypoint_rotate.pkl".format(os.path.dirname(video_out_path))
+ with open(Path_output_pkl, "wb") as f:
+ pickle.dump(pts_3d, f)
+
+ if export_imgs:
+ # 计算整个视频中人脸的范围
+ x_min, y_min, x_max, y_max = np.min(pts_3d[:, :, 0]), np.min(
+ pts_3d[:, :, 1]), np.max(
+ pts_3d[:, :, 0]), np.max(pts_3d[:, :, 1])
+ new_w = int((x_max - x_min) * 0.55) * 2
+ new_h = int((y_max - y_min) * 0.6) * 2
+ center_x = int((x_max + x_min) / 2.)
+ center_y = int(y_min + (y_max - y_min) * 0.6)
+ size = max(new_h, new_w)
+ x_min, y_min, x_max, y_max = int(center_x - size // 2), int(center_y - size // 2), int(
+ center_x + size // 2), int(center_y + size // 2)
+
+ # 确定裁剪区域上边top和左边left坐标
+ top = y_min
+ left = x_min
+ # 裁剪区域与原图的重合区域
+ top_coincidence = int(max(top, 0))
+ bottom_coincidence = int(min(y_max, vid_height))
+ left_coincidence = int(max(left, 0))
+ right_coincidence = int(min(x_max, vid_width))
+ print("人脸活动范围:{}:{}, {}:{}".format(top_coincidence, bottom_coincidence, left_coincidence, right_coincidence))
+ np.savetxt("{}/face_rect.txt".format(os.path.dirname(video_out_path)),
+ np.array([top_coincidence, bottom_coincidence, left_coincidence, right_coincidence]))
+ os.makedirs("{}/image".format(os.path.dirname(video_out_path)))
+ ffmpeg_cmd = "ffmpeg -i {} -vf crop={}:{}:{}:{},scale=512:512:flags=neighbor -loglevel quiet -y {}/image/%06d.png".format(
+ front_video_path,
+ right_coincidence - left_coincidence,
+ bottom_coincidence - top_coincidence,
+ left_coincidence,
+ top_coincidence,
+ os.path.dirname(video_out_path)
+ )
+ os.system(ffmpeg_cmd)
+
+ cap = cv2.VideoCapture(video_out_path)
+ frames = cap.get(cv2.CAP_PROP_FRAME_COUNT)
+ cap.release()
+ print("循环视频帧数:", frames)
+
+
+def main():
+ # 检查命令行参数的数量
+ if len(sys.argv) != 2:
+ print("Usage: python data_preparation.py ")
+ sys.exit(1) # 参数数量不正确时退出程序
+
+ # 获取video_name参数
+ video_name = sys.argv[1]
+ print(f"Video name is set to: {video_name}")
+
+ new_data_path = "video_data/{}".format(uuid.uuid1())
+ os.makedirs(new_data_path, exist_ok=True)
+ video_out_path = "{}/circle.mp4".format(new_data_path)
+ CirculateVideo(video_name, video_out_path, export_imgs=False)
+
+if __name__ == "__main__":
+ main()
diff --git a/data_preparation_web.py b/data_preparation_web.py
new file mode 100644
index 0000000..3a99855
--- /dev/null
+++ b/data_preparation_web.py
@@ -0,0 +1,291 @@
+import uuid
+import tqdm
+import numpy as np
+import cv2
+import sys
+import os
+import math
+from talkingface.data.few_shot_dataset import get_image
+import torch
+import mediapipe as mp
+from talkingface.utils import crop_mouth, main_keypoints_index, smooth_array
+import json
+from mini_live.obj.wrap_utils import index_wrap, index_edge_wrap
+
+mp_face_mesh = mp.solutions.face_mesh
+mp_face_detection = mp.solutions.face_detection
+
+def detect_face(frame):
+ # 剔除掉多个人脸、大角度侧脸(鼻子不在两个眼之间)、部分人脸框在画面外、人脸像素低于80*80的
+ with mp_face_detection.FaceDetection(
+ model_selection=1, min_detection_confidence=0.5) as face_detection:
+ results = face_detection.process(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
+ if not results.detections or len(results.detections) > 1:
+ return -1, None
+ rect = results.detections[0].location_data.relative_bounding_box
+ out_rect = [rect.xmin, rect.xmin + rect.width, rect.ymin, rect.ymin + rect.height]
+ nose_ = mp_face_detection.get_key_point(
+ results.detections[0], mp_face_detection.FaceKeyPoint.NOSE_TIP)
+ l_eye_ = mp_face_detection.get_key_point(
+ results.detections[0], mp_face_detection.FaceKeyPoint.LEFT_EYE)
+ r_eye_ = mp_face_detection.get_key_point(
+ results.detections[0], mp_face_detection.FaceKeyPoint.RIGHT_EYE)
+ # print(nose_, l_eye_, r_eye_)
+ if nose_.x > l_eye_.x or nose_.x < r_eye_.x:
+ return -2, out_rect
+
+ h, w = frame.shape[:2]
+ # print(frame.shape)
+ if rect.xmin < 0 or rect.ymin < 0 or rect.xmin + rect.width > w or rect.ymin + rect.height > h:
+ return -3, out_rect
+ if rect.width * w < 100 or rect.height * h < 100:
+ return -4, out_rect
+ return 1, out_rect
+
+
+def calc_face_interact(face0, face1):
+ x_min = min(face0[0], face1[0])
+ x_max = max(face0[1], face1[1])
+ y_min = min(face0[2], face1[2])
+ y_max = max(face0[3], face1[3])
+ tmp0 = ((face0[1] - face0[0]) * (face0[3] - face0[2])) / ((x_max - x_min) * (y_max - y_min))
+ tmp1 = ((face1[1] - face1[0]) * (face1[3] - face1[2])) / ((x_max - x_min) * (y_max - y_min))
+ return min(tmp0, tmp1)
+
+
+def detect_face_mesh(frame):
+ with mp_face_mesh.FaceMesh(
+ static_image_mode=True,
+ max_num_faces=1,
+ refine_landmarks=True,
+ min_detection_confidence=0.5) as face_mesh:
+ results = face_mesh.process(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
+ pts_3d = np.zeros([478, 3])
+ if not results.multi_face_landmarks:
+ print("****** WARNING! No face detected! ******")
+ else:
+ image_height, image_width = frame.shape[:2]
+ for face_landmarks in results.multi_face_landmarks:
+ for index_, i in enumerate(face_landmarks.landmark):
+ x_px = min(math.floor(i.x * image_width), image_width - 1)
+ y_px = min(math.floor(i.y * image_height), image_height - 1)
+ z_px = min(math.floor(i.z * image_width), image_width - 1)
+ pts_3d[index_] = np.array([x_px, y_px, z_px])
+ return pts_3d
+
+
+def ExtractFromVideo(video_path):
+ cap = cv2.VideoCapture(video_path)
+ if not cap.isOpened():
+ return 0
+
+ dir_path = os.path.dirname(video_path)
+ vid_width = cap.get(cv2.CAP_PROP_FRAME_WIDTH) # 宽度
+ vid_height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT) # 高度
+
+ totalFrames = cap.get(cv2.CAP_PROP_FRAME_COUNT) # 总帧数
+ totalFrames = int(totalFrames)
+ pts_3d = np.zeros([totalFrames, 478, 3])
+ frame_index = 0
+ face_rect_list = []
+ ms_list = []
+ model_name = os.path.basename(video_path)[:-4]
+
+ # os.makedirs("../preparation/{}/image".format(model_name))
+ for frame_index in tqdm.tqdm(range(totalFrames)):
+ ret, frame = cap.read() # 按帧读取视频
+ ms = cap.get(cv2.CAP_PROP_POS_MSEC)
+ ms_list.append(ms)
+ # #到视频结尾时终止
+ if ret is False:
+ break
+ # cv2.imwrite("../preparation/{}/image/{:0>6d}.png".format(model_name, frame_index), frame)
+ tag_, rect = detect_face(frame)
+ if frame_index == 0 and tag_ != 1:
+ print("第一帧人脸检测异常,请剔除掉多个人脸、大角度侧脸(鼻子不在两个眼之间)、部分人脸框在画面外、人脸像素低于80*80")
+ pts_3d = -1
+ break
+ elif tag_ == -1: # 有时候人脸检测会失败,就用上一帧的结果替代这一帧的结果
+ rect = face_rect_list[-1]
+ elif tag_ != 1:
+ print("第{}帧人脸检测异常,请剔除掉多个人脸、大角度侧脸(鼻子不在两个眼之间)、部分人脸框在画面外、人脸像素低于80*80, tag: {}".format(frame_index, tag_))
+ # exit()
+ if len(face_rect_list) > 0:
+ face_area_inter = calc_face_interact(face_rect_list[-1], rect)
+ # print(frame_index, face_area_inter)
+ if face_area_inter < 0.6:
+ print("人脸区域变化幅度太大,请复查,超出值为{}, frame_num: {}".format(face_area_inter, frame_index))
+ pts_3d = -2
+ break
+
+ face_rect_list.append(rect)
+
+ x_min = rect[0] * vid_width
+ y_min = rect[2] * vid_height
+ x_max = rect[1] * vid_width
+ y_max = rect[3] * vid_height
+ seq_w, seq_h = x_max - x_min, y_max - y_min
+ x_mid, y_mid = (x_min + x_max) / 2, (y_min + y_max) / 2
+ # x_min = int(max(0, x_mid - seq_w * 0.65))
+ # y_min = int(max(0, y_mid - seq_h * 0.4))
+ # x_max = int(min(vid_width, x_mid + seq_w * 0.65))
+ # y_max = int(min(vid_height, y_mid + seq_h * 0.8))
+ crop_size = int(max(seq_w * 1.35, seq_h * 1.35))
+ x_min = int(max(0, x_mid - crop_size * 0.5))
+ y_min = int(max(0, y_mid - crop_size * 0.45))
+ x_max = int(min(vid_width, x_min + crop_size))
+ y_max = int(min(vid_height, y_min + crop_size))
+
+ frame_face = frame[y_min:y_max, x_min:x_max]
+ print(y_min, y_max, x_min, x_max)
+ # cv2.imshow("s", frame_face)
+ # cv2.waitKey(20)
+ frame_kps = detect_face_mesh(frame_face)
+ pts_3d[frame_index] = frame_kps + np.array([x_min, y_min, 0])
+ cap.release() # 释放视频对象
+ return pts_3d,ms_list
+
+
+def step0_keypoints(video_in_path, out_path):
+ video_out_path = os.path.join(out_path, "01.mp4")
+ # 1 视频转换为25FPS
+ ffmpeg_cmd = "ffmpeg -i {} -r 25 -an -y {}".format(video_in_path, video_out_path)
+ os.system(ffmpeg_cmd)
+
+ # front_video_path = video_in_path
+
+ cap = cv2.VideoCapture(video_out_path)
+ vid_width = cap.get(cv2.CAP_PROP_FRAME_WIDTH) # 宽度
+ vid_height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT) # 高度
+ frames = cap.get(cv2.CAP_PROP_FRAME_COUNT)
+ cap.release()
+
+ print("正向视频帧数:", frames)
+ pts_3d,_ = ExtractFromVideo(video_out_path)
+ if type(pts_3d) is np.ndarray and len(pts_3d) == frames:
+ print("关键点已提取")
+
+ pts_3d = pts_3d.reshape(len(pts_3d), -1)
+ smooth_array_ = smooth_array(pts_3d, weight=[0.03, 0.06, 0.11, 0.6, 0.11, 0.06, 0.03])
+ pts_3d = smooth_array_.reshape(len(pts_3d), 478, 3)
+ return pts_3d,vid_width,vid_height
+
+def step1_crop_mouth(pts_3d, vid_width, vid_height):
+ list_source_crop_rect = [crop_mouth(source_pts[main_keypoints_index], vid_width, vid_height) for source_pts in
+ pts_3d]
+ list_source_crop_rect = np.array(list_source_crop_rect).reshape(len(pts_3d), -1)
+ face_size = (list_source_crop_rect[:,2] - list_source_crop_rect[:,0]).mean()/2.0 + (list_source_crop_rect[:,3] - list_source_crop_rect[:,1]).mean()/2.0
+ face_size = int(face_size)//2 * 2
+ face_mid = (list_source_crop_rect[:,2:] + list_source_crop_rect[:,0:2])/2.
+ # step 1: Smooth Cropping Rectangle Transition
+ # Since HTML video playback can have inconsistent frame rates and may not align precisely from frame to frame, adjust the cropping rectangle to transition smoothly, compensating for potential misalignment.
+ face_mid = smooth_array(face_mid, weight=[0.20, 0.20, 0.20, 0.20, 0.20])
+ face_mid = face_mid.astype(int)
+ if face_mid[:, 0].max() + face_size / 2 > vid_width or face_mid[:, 1].max() + face_size / 2 > vid_height:
+ raise ValueError("人脸范围超出了视频,请保证视频合格后再重试")
+
+ list_source_crop_rect = np.concatenate([face_mid - face_size // 2, face_mid + face_size // 2], axis = 1)
+
+ standard_size = 128
+ list_standard_v = []
+ for frame_index in range(len(list_source_crop_rect)):
+ source_pts = pts_3d[frame_index]
+ source_crop_rect = list_source_crop_rect[frame_index]
+ print(source_crop_rect)
+ standard_v = get_image(source_pts, source_crop_rect, input_type="mediapipe", resize=standard_size)
+
+ list_standard_v.append(standard_v)
+
+ return list_source_crop_rect, list_standard_v
+
+def step2_generate_obj(list_source_crop_rect, list_standard_v, out_path):
+ from mini_live.obj.obj_utils import generateRenderInfo, generateWrapModel
+ render_verts, render_face = generateRenderInfo()
+ face_pts_mean = render_verts[:478, :3].copy()
+
+ wrapModel_verts, wrapModel_face = generateWrapModel()
+ # 求平均人脸
+ from talkingface.run_utils import calc_face_mat
+ mat_list, _, face_pts_mean_personal_primer = calc_face_mat(np.array(list_standard_v), face_pts_mean)
+ from mini_live.obj.wrap_utils import newWrapModel
+
+ face_wrap_entity = newWrapModel(wrapModel_verts, face_pts_mean_personal_primer)
+
+ with open(os.path.join(out_path,"face3D.obj"), "w") as f:
+ for i in face_wrap_entity:
+ f.write("v {:.3f} {:.3f} {:.3f} {:.02f} {:.0f}\n".format(i[0], i[1], i[2], i[3], i[4]))
+ for i in range(len(wrapModel_face) // 3):
+ f.write("f {0} {1} {2}\n".format(wrapModel_face[3 * i] + 1, wrapModel_face[3 * i + 1] + 1,
+ wrapModel_face[3 * i + 2] + 1))
+ json_data = []
+ for frame_index in range(len(list_source_crop_rect)):
+ source_crop_rect = list_source_crop_rect[frame_index]
+ standard_v = list_standard_v[frame_index]
+
+ standard_v = standard_v[index_wrap, :2].flatten().tolist()
+ mat = mat_list[frame_index].T.flatten().tolist()
+ # 将 standard_v 中所有元素四舍五入到两位小数
+ standard_v_rounded = [round(i, 5) for i in mat] + [round(i, 1) for i in standard_v]
+ print(len(standard_v_rounded), 16 + 209 * 2)
+ json_data.append({"rect": source_crop_rect.tolist(), "points": standard_v_rounded})
+ # print(json_data)
+ # break
+ with open(os.path.join(out_path, "json_data.json"), "w") as f:
+ json.dump(json_data, f)
+
+def step3_generate_ref_tensor(list_source_crop_rect, list_standard_v, out_path):
+ from talkingface.render_model_mini import RenderModel_Mini
+ renderModel_mini = RenderModel_Mini()
+ renderModel_mini.loadModel("checkpoint/DINet_mini/epoch_40.pth")
+
+ from talkingface.data.few_shot_dataset import select_ref_index
+ from talkingface.utils import draw_mouth_maps
+
+ driven_keypoints = np.array(list_standard_v)[:,main_keypoints_index]
+ ref_img_index_list = select_ref_index(driven_keypoints, n_ref=3, ratio=0.33) # 从当前视频选n_ref个图片
+ ref_img_list = []
+
+ video_path = os.path.join(out_path, "01.mp4")
+ cap_input = cv2.VideoCapture(video_path)
+ for index in ref_img_index_list:
+ cap_input.set(cv2.CAP_PROP_POS_FRAMES, index) # 设置要获取的帧号
+ ret, frame = cap_input.read()
+
+ ref_face_edge = draw_mouth_maps(driven_keypoints[index], size=(128, 128))
+ frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
+
+ ref_img = get_image(frame, list_source_crop_rect[index], input_type="image", resize=128)
+
+ ref_face_edge = cv2.resize(ref_face_edge, (128, 128))
+ ref_img = cv2.resize(ref_img, (128, 128))
+ w_pad = int((128 - 72) / 2)
+ h_pad = int((128 - 56) / 2)
+
+ ref_img = np.concatenate([ref_img[h_pad:-h_pad, w_pad:-w_pad], ref_face_edge[h_pad:-h_pad, w_pad:-w_pad, :1]],
+ axis=2)
+ # cv2.imshow("ss", ref_img[:,:,::-1])
+ # cv2.waitKey(-1)
+ ref_img_list.append(ref_img)
+ ref_img = np.concatenate(ref_img_list, axis=2)
+
+ ref_tensor = torch.from_numpy(ref_img / 255.).float().permute(2, 0, 1).unsqueeze(0).cuda()
+
+ renderModel_mini.net.ref_input(ref_tensor)
+
+ ref_in_feature = renderModel_mini.net.infer_model.ref_in_feature
+ print(1111, ref_in_feature.size())
+ ref_in_feature = ref_in_feature.detach().squeeze(0).cpu().float().numpy().flatten()
+ print(1111, ref_in_feature.shape)
+
+ np.savetxt(os.path.join(out_path, 'ref_data.txt'), ref_in_feature, fmt='%.8f')
+
+def main():
+ video_in_path = r"E:\data\video\video/5.mp4"
+ out_path = "web_demo/static/assets"
+ pts_3d, vid_width,vid_height = step0_keypoints(video_in_path, out_path)
+ list_source_crop_rect, list_standard_v = step1_crop_mouth(pts_3d, vid_width, vid_height)
+ step2_generate_obj(list_source_crop_rect, list_standard_v, out_path)
+ step3_generate_ref_tensor(list_source_crop_rect, list_standard_v, out_path)
+
+if __name__ == "__main__":
+ main()
diff --git a/demo.py b/demo.py
new file mode 100644
index 0000000..defe411
--- /dev/null
+++ b/demo.py
@@ -0,0 +1,69 @@
+import time
+import os
+import numpy as np
+import uuid
+import cv2
+import tqdm
+import shutil
+import sys
+from talkingface.audio_model import AudioModel
+from talkingface.render_model import RenderModel
+
+def main():
+ # 检查命令行参数的数量
+ if len(sys.argv) < 5:
+ print("Usage: python demo.py ")
+ sys.exit(1) # 参数数量不正确时退出程序
+
+ # 获取video_name参数
+ video_path = sys.argv[1]
+ print(f"Video path is set to: {video_path}")
+ audio_path = sys.argv[2]
+ print(f"Audio path is set to: {audio_path}")
+ output_video_name = sys.argv[3]
+ print(f"output video name is set to: {output_video_name}")
+ try:
+ model_name = sys.argv[4]
+ print(f"model_name: {model_name}")
+ except Exception:
+ model_name = "render.pth"
+
+
+ audioModel = AudioModel()
+ audioModel.loadModel("checkpoint/audio.pkl")
+
+ renderModel = RenderModel()
+ renderModel.loadModel(f"checkpoint/{model_name}")
+ pkl_path = "{}/keypoint_rotate.pkl".format(video_path)
+ video_path = "{}/circle.mp4".format(video_path)
+ renderModel.reset_charactor(video_path, pkl_path)
+
+ # wavpath = "video_data/audio0.wav"
+ wavpath = audio_path
+ mouth_frame = audioModel.interface_wav(wavpath)
+ cap_input = cv2.VideoCapture(video_path)
+ vid_width = cap_input.get(cv2.CAP_PROP_FRAME_WIDTH) # 宽度
+ vid_height = cap_input.get(cv2.CAP_PROP_FRAME_HEIGHT) # 高度
+ cap_input.release()
+ task_id = str(uuid.uuid1())
+ os.makedirs("output/{}".format(task_id), exist_ok=True)
+ fourcc = cv2.VideoWriter_fourcc(*'mp4v')
+ save_path = "output/{}/silence.mp4".format(task_id)
+ videoWriter = cv2.VideoWriter(save_path, fourcc, 25, (int(vid_width) * 1, int(vid_height)))
+ for frame in tqdm.tqdm(mouth_frame):
+ frame = renderModel.interface(frame)
+ # cv2.imshow("s", frame)
+ # cv2.waitKey(40)
+
+ videoWriter.write(frame)
+
+ videoWriter.release()
+ val_video = "../output/{}.mp4".format(task_id)
+ os.system(
+ "ffmpeg -y -i {} -i {} -c:v libx264 -pix_fmt yuv420p -loglevel quiet {}".format(save_path, wavpath, output_video_name))
+ shutil.rmtree("output/{}".format(task_id))
+
+
+
+if __name__ == "__main__":
+ main()
diff --git a/demo_avatar.py b/demo_avatar.py
new file mode 100644
index 0000000..fa3c706
--- /dev/null
+++ b/demo_avatar.py
@@ -0,0 +1,38 @@
+import time
+import os
+import numpy as np
+from scipy.io import wavfile
+import cv2
+import glob
+from talkingface.audio_model import AudioModel
+from talkingface.render_model import RenderModel
+
+audioModel = AudioModel()
+audioModel.loadModel("checkpoint/audio.pkl")
+
+renderModel = RenderModel()
+renderModel.loadModel("checkpoint/render.pth")
+test_video = "test"
+pkl_path = "video_data/{}/keypoint_rotate.pkl".format(test_video)
+video_path = "video_data/{}/circle.mp4".format(test_video)
+renderModel.reset_charactor(video_path, pkl_path)
+
+wavpath = "video_data/audio0.wav"
+rate, wav = wavfile.read(wavpath, mmap=False)
+index_ = 0
+frame_index__ = 0
+import sounddevice as sd
+sample_rate = 16000
+samples_per_read = int(0.04 * sample_rate)
+with sd.InputStream(
+ channels=1, dtype="float32", samplerate=sample_rate
+) as s:
+ while True:
+ samples, _ = s.read(samples_per_read) # a blocking read
+ pcm_data = samples.reshape(-1)
+ print(pcm_data.shape)
+ mouth_frame = audioModel.interface_frame(pcm_data)
+ frame = renderModel.interface(mouth_frame)
+ cv2.imshow("s", frame)
+ cv2.waitKey(10)
+ index_ += 1
diff --git a/demo_mini.py b/demo_mini.py
new file mode 100644
index 0000000..ee19840
--- /dev/null
+++ b/demo_mini.py
@@ -0,0 +1,152 @@
+import os
+os.environ["kmp_duplicate_lib_ok"] = "true"
+import os
+from mini_live.obj.wrap_utils import index_wrap, index_edge_wrap
+current_dir = os.path.dirname(os.path.abspath(__file__))
+from mini_live.render import create_render_model
+import pickle
+import cv2
+import time
+import numpy as np
+import glob
+import random
+import os
+import sys
+import torch
+from talkingface.model_utils import LoadAudioModel, Audio2bs
+from talkingface.data.few_shot_dataset import get_image
+
+def run(video_path, pkl_path, wav_path, output_video_path):
+ Audio2FeatureModel = LoadAudioModel(r'checkpoint/lstm/lstm_model_epoch_325.pkl')
+
+ from talkingface.render_model_mini import RenderModel_Mini
+ renderModel_mini = RenderModel_Mini()
+ renderModel_mini.loadModel("checkpoint/DINet_mini/epoch_40.pth")
+
+ standard_size = 256
+ crop_rotio = [0.5, 0.5, 0.5, 0.5]
+ out_w = int(standard_size * (crop_rotio[0] + crop_rotio[1]))
+ out_h = int(standard_size * (crop_rotio[2] + crop_rotio[3]))
+ out_size = (out_w, out_h)
+ renderModel_gl = create_render_model((out_w, out_h), floor=20)
+
+ from mini_live.obj.obj_utils import generateWrapModel
+ from talkingface.utils import crop_mouth, main_keypoints_index
+ wrapModel, wrapModel_face = generateWrapModel()
+
+ with open(pkl_path, "rb") as f:
+ images_info = pickle.load(f)
+
+ images_info = np.concatenate([images_info, images_info[::-1]], axis=0)
+
+ cap = cv2.VideoCapture(video_path)
+ vid_frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
+ vid_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
+ vid_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
+
+ list_source_crop_rect = []
+ list_video_img = []
+ list_standard_img = []
+ list_standard_v = []
+ list_standard_vt = []
+ for frame_index in range(min(vid_frame_count, len(images_info))):
+ ret, frame = cap.read()
+ frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA)
+ source_pts = images_info[frame_index]
+ source_crop_rect = crop_mouth(source_pts[main_keypoints_index], vid_width, vid_height)
+
+ standard_img = get_image(frame, source_crop_rect, input_type="image", resize=standard_size)
+ standard_v = get_image(source_pts, source_crop_rect, input_type="mediapipe", resize=standard_size)
+ standard_vt = standard_v[:, :2] / standard_size
+
+ list_video_img.append(frame)
+ list_source_crop_rect.append(source_crop_rect)
+ list_standard_img.append(standard_img)
+ list_standard_v.append(standard_v)
+ list_standard_vt.append(standard_vt)
+ cap.release()
+
+ renderModel_mini.reset_charactor(list_standard_img, np.array(list_standard_v)[:, main_keypoints_index])
+ from talkingface.run_utils import calc_face_mat
+ mat_list, _, face_pts_mean_personal_primer = calc_face_mat(np.array(list_standard_v), renderModel_gl.face_pts_mean)
+ from mini_live.obj.wrap_utils import newWrapModel
+ face_wrap_entity = newWrapModel(wrapModel, face_pts_mean_personal_primer)
+
+ renderModel_gl.GenVBO(face_wrap_entity)
+
+ bs_array = Audio2bs(wav_path, Audio2FeatureModel)[5:] * 0.5
+ import uuid
+ task_id = str(uuid.uuid1())
+ fourcc = cv2.VideoWriter_fourcc(*'mp4v')
+ save_path = "{}.mp4".format(task_id)
+ videoWriter = cv2.VideoWriter(save_path, fourcc, 25, (int(vid_width), int(vid_height)))
+
+ for frame_index in range(len(mat_list)):
+ if frame_index >= len(bs_array):
+ continue
+ bs = np.zeros([12], dtype=np.float32)
+ bs[:6] = bs_array[frame_index, :6]
+ # bs[2] = frame_index* 5
+
+ verts_frame_buffer = np.array(list_standard_vt)[frame_index, index_wrap, :2].copy() * 2 - 1
+
+ rgba = renderModel_gl.render2cv(verts_frame_buffer, out_size=out_size, mat_world=mat_list[frame_index].T,
+ bs_array=bs)
+ # rgb = cv2.cvtColor(rgba, cv2.COLOR_RGBA2RGB)
+ # rgba = cv2.resize(rgba, (128, 128))
+ rgba = rgba[::2, ::2, :]
+
+ gl_tensor = torch.from_numpy(rgba / 255.).float().permute(2, 0, 1).unsqueeze(0)
+ source_tensor = cv2.resize(list_standard_img[frame_index], (128, 128))
+ source_tensor = torch.from_numpy(source_tensor / 255.).float().permute(2, 0, 1).unsqueeze(0)
+
+ warped_img = renderModel_mini.interface(source_tensor.cuda(), gl_tensor.cuda())
+
+ image_numpy = warped_img.detach().squeeze(0).cpu().float().numpy()
+ image_numpy = np.transpose(image_numpy, (1, 2, 0)) * 255.0
+ image_numpy = image_numpy.clip(0, 255)
+ image_numpy = image_numpy.astype(np.uint8)
+
+ x_min, y_min, x_max, y_max = list_source_crop_rect[frame_index]
+
+ img_face = cv2.resize(image_numpy, (x_max - x_min, y_max - y_min))
+ img_bg = list_video_img[frame_index][:, :, :3]
+ img_bg[y_min:y_max, x_min:x_max, :3] = img_face[:, :, :3]
+ # cv2.imshow('scene', img_bg[:,:,::-1])
+ # cv2.waitKey(10)
+ # print(time.time())
+
+ videoWriter.write(img_bg[:, :, ::-1])
+ videoWriter.release()
+
+ os.system(
+ "ffmpeg -i {} -i {} -c:v libx264 -pix_fmt yuv420p {}".format(save_path, wav_path, output_video_path))
+ os.remove(save_path)
+
+ cv2.destroyAllWindows()
+
+def main():
+ # 检查命令行参数的数量
+ if len(sys.argv) < 4:
+ print("Usage: python demo_mini.py ")
+ sys.exit(1) # 参数数量不正确时退出程序
+
+ # 获取video_name参数
+ video_path = sys.argv[1]
+ print(f"Video path is set to: {video_path}")
+ wav_path = sys.argv[2]
+ print(f"Audio path is set to: {wav_path}")
+ output_video_name = sys.argv[3]
+ print(f"output video name is set to: {output_video_name}")
+
+ pkl_path = "{}/keypoint_rotate.pkl".format(video_path)
+ video_path = "{}/circle.mp4".format(video_path)
+
+ run(video_path, pkl_path, wav_path, output_video_name)
+
+# 示例使用
+if __name__ == "__main__":
+ main()
+
+
+
diff --git a/mini_live/bs_texture.png b/mini_live/bs_texture.png
new file mode 100644
index 0000000..c19b628
Binary files /dev/null and b/mini_live/bs_texture.png differ
diff --git a/mini_live/bs_texture_halfFace.png b/mini_live/bs_texture_halfFace.png
new file mode 100644
index 0000000..f28a247
Binary files /dev/null and b/mini_live/bs_texture_halfFace.png differ
diff --git a/mini_live/face_fusion_mask.png b/mini_live/face_fusion_mask.png
new file mode 100644
index 0000000..8d56c6e
Binary files /dev/null and b/mini_live/face_fusion_mask.png differ
diff --git a/mini_live/generate_fusion_mask.py b/mini_live/generate_fusion_mask.py
new file mode 100644
index 0000000..df0234f
--- /dev/null
+++ b/mini_live/generate_fusion_mask.py
@@ -0,0 +1,16 @@
+import numpy as np
+import cv2
+import os
+
+face_fusion_mask = np.zeros([128, 128], dtype = np.uint8)
+for i in range(8):
+ face_fusion_mask[i:-i,i:-i] = min(255, i*40)
+
+cv2.imwrite("face_fusion_mask.png", face_fusion_mask)
+
+
+from mini_live.obj.wrap_utils import index_wrap
+image2 = cv2.imread("bs_texture.png")
+image3 = np.zeros([12, 256, 3], dtype=np.uint8)
+image3[:, :len(index_wrap)] = image2[:, index_wrap]
+cv2.imwrite("bs_texture_halfFace.png", image3)
\ No newline at end of file
diff --git a/mini_live/mouth_fusion_mask.png b/mini_live/mouth_fusion_mask.png
new file mode 100644
index 0000000..65bd4d5
Binary files /dev/null and b/mini_live/mouth_fusion_mask.png differ
diff --git a/mini_live/obj/image_utils.py b/mini_live/obj/image_utils.py
new file mode 100644
index 0000000..788fc56
--- /dev/null
+++ b/mini_live/obj/image_utils.py
@@ -0,0 +1,135 @@
+import numpy as np
+import cv2
+import os
+current_dir = os.path.dirname(os.path.abspath(__file__))
+
+def get_standard_image_(img, kps, crop_coords, resize = (256, 256)):
+ h = img.shape[0]
+ w = img.shape[1]
+ c = img.shape[2]
+ (x_min, y_min, x_max, y_max) = [int(ii) for ii in crop_coords]
+ new_w = x_max - x_min
+ new_h = y_max - y_min
+ img_new = np.zeros([new_h, new_w, c], dtype=np.uint8)
+
+ # 确定裁剪区域上边top和左边left坐标
+ top = int(y_min)
+ left = int(x_min)
+ # 裁剪区域与原图的重合区域
+ top_coincidence = int(max(top, 0))
+ bottom_coincidence = int(min(y_max, h))
+ left_coincidence = int(max(left, 0))
+ right_coincidence = int(min(x_max, w))
+ img_new[top_coincidence - top:bottom_coincidence - top, left_coincidence - left:right_coincidence - left, :] = img[
+ top_coincidence:bottom_coincidence,
+ left_coincidence:right_coincidence,
+ :]
+
+ img_new = cv2.resize(img_new, resize)
+ kps = kps - np.array([left, top, 0])
+
+ factor = resize[0]/new_w
+ kps = kps * factor
+ return img_new, kps
+
+def get_standard_image(img_rgba, source_pts, source_crop_rect, out_size):
+ '''
+ 将输入的RGBA图像和关键点点集转换为标准图像和标准顶点集。
+
+ 参数:
+ img_rgba (numpy.ndarray): 输入的RGBA图像,形状为 (H, W, 4)。
+ source_pts (numpy.ndarray): 源点集,形状为 (N, 3),其中N是点的数量,每个点有三个坐标 (x, y, z)。
+ source_crop_rect (tuple): 源图像的裁剪矩形,格式为 (x, y, width, height)。
+ out_size (int): 输出图像的大小,格式为 (width, height)。
+
+ 返回:
+ standard_img (numpy.ndarray): 标准化的图像,形状为 (out_size, out_size, 4)。
+ standard_v (numpy.ndarray): 标准化的顶点集,形状为 (N, 3)。
+ standard_vt (numpy.ndarray): 标准化的顶点集的纹理坐标,形状为 (N, 2)。
+ '''
+ source_pts[:, 2] = source_pts[:, 2] - np.max(source_pts[:, 2])
+ standard_img, standard_v = get_standard_image_(img_rgba, source_pts, source_crop_rect, resize=out_size)
+
+ standard_vt = standard_v.copy()
+ standard_vt = standard_vt[:,:2]/ out_size
+ return standard_img, standard_v, standard_vt
+
+def crop_face_from_several_images(pts_array_origin, img_w, img_h):
+ x_min, y_min, x_max, y_max = np.min(pts_array_origin[:, :, 0]), np.min(
+ pts_array_origin[:, :, 1]), np.max(
+ pts_array_origin[:, :, 0]), np.max(pts_array_origin[:, :, 1])
+ new_w = (x_max - x_min) * 2
+ new_h = (y_max - y_min) * 2
+ center_x = (x_max + x_min) / 2.
+ center_y = y_min + (y_max - y_min) * 0.25
+ x_min, y_min, x_max, y_max = int(center_x - new_w / 2), int(center_y - new_h / 2), int(
+ center_x + new_w / 2), int(center_y + new_h / 2)
+ x_min = max(0, x_min)
+ y_min = max(0, y_min)
+ x_max = min(x_max, img_w)
+ y_max = min(y_max, img_h)
+ new_size = min((x_max + x_min) / 2., (y_max + y_min) / 2.)
+ center_x = (x_max + x_min) / 2.
+ center_y = (y_max + y_min) / 2.
+ x_min, y_min, x_max, y_max = int(center_x - new_size), int(center_y - new_size), int(
+ center_x + new_size), int(center_y + new_size)
+ return np.array([x_min, y_min, x_max, y_max])
+
+def crop_face_from_image(kps, crop_rotio = [0.6,0.6,0.65,1.35]):
+ '''
+ 只为了裁剪图片
+ :param kps:
+ :param crop_rotio:
+ :param standard_size:
+ :return:
+ '''
+ x2d = kps[:, 0]
+ y2d = kps[:, 1]
+ w_span = x2d.max() - x2d.min()
+ h_span = y2d.max() - y2d.min()
+ crop_size = int(2*max(h_span, w_span))
+ center_x = (x2d.max() + x2d.min()) / 2.
+ center_y = (y2d.max() + y2d.min()) / 2.
+ # 确定裁剪区域上边top和左边left坐标,中心点是(x2d.max() + x2d.min()/2, y2d.max() + y2d.min()/2)
+ y_min = int(center_y - crop_size*crop_rotio[2])
+ y_max = int(center_y + crop_size*crop_rotio[3])
+ x_min = int(center_x - crop_size*crop_rotio[0])
+ x_max = int(center_x + crop_size*crop_rotio[1])
+ return np.array([x_min, y_min, x_max, y_max])
+
+def check_keypoint(img, pts_):
+ point_size = 1
+ point_color = (0, 0, 255) # BGR
+ thickness = 4 # 0 、4、8
+ for coor in pts_:
+ # coor = (coor +1 )/2.
+ cv2.circle(img, (int(coor[0]), int(coor[1])), point_size, point_color, thickness)
+ cv2.imshow("a", img)
+ cv2.waitKey(-1)
+
+if __name__ == "__main__":
+ from talkingface.mediapipe_utils import detect_face_mesh
+ import glob
+
+ image_list = glob.glob(r"F:\C\AI\CV\TalkingFace\OpenGLRender_0830\face_rgba/*.png")
+ image_list.sort()
+ for index, img_path in enumerate(image_list):
+ img_primer_rgba = cv2.imread(img_path, cv2.IMREAD_UNCHANGED)
+ source_pts = detect_face_mesh([img_primer_rgba[:, :, :3]])[0]
+ img_primer_rgba = cv2.cvtColor(img_primer_rgba, cv2.COLOR_BGRA2RGBA)
+
+ source_crop_rect = crop_face_from_image(source_pts, crop_rotio=[0.75, 0.75, 0.65, 1.35])
+ standard_img, standard_v, standard_vt = get_standard_image(img_primer_rgba, source_pts, source_crop_rect,
+ out_size=(750, 1000))
+ print(np.max(standard_vt[:, 0]))
+ print(np.max(standard_vt[:, 1]))
+ point_size = 1
+ point_color = (0, 0, 255) # BGR
+ thickness = 4 # 0 、4、8
+ pts_ = standard_v
+ img = standard_img
+ for coor in pts_:
+ # coor = (coor +1 )/2.
+ cv2.circle(img, (int(coor[0]), int(coor[1])), point_size, point_color, thickness)
+ cv2.imshow("a", img)
+ cv2.waitKey(-1)
\ No newline at end of file
diff --git a/mini_live/obj/obj_mediapipe/face3D.obj b/mini_live/obj/obj_mediapipe/face3D.obj
new file mode 100644
index 0000000..f62b07a
--- /dev/null
+++ b/mini_live/obj/obj_mediapipe/face3D.obj
@@ -0,0 +1,1817 @@
+v 500.271 739.284 -238.683
+v 500.271 677.808 -282.308
+v 500.271 697.341 -236.893
+v 485.187 614.107 -257.349
+v 500.271 657.949 -288.222
+v 500.271 632.339 -280.626
+v 500.271 570.049 -230.870
+v 373.630 562.453 -160.007
+v 500.271 519.208 -218.065
+v 500.271 492.784 -221.212
+v 500.271 400.977 -200.539
+v 500.271 746.772 -236.622
+v 500.271 754.693 -230.707
+v 500.271 759.957 -222.134
+v 500.271 781.823 -216.166
+v 500.271 791.210 -218.390
+v 500.271 802.767 -221.375
+v 500.271 814.324 -217.197
+v 500.271 829.517 -198.532
+v 500.271 688.063 -273.247
+v 484.211 687.900 -248.667
+v 305.046 490.613 -72.433
+v 422.463 578.785 -179.052
+v 405.209 580.304 -177.696
+v 388.280 579.816 -172.541
+v 365.762 569.615 -157.349
+v 437.113 574.607 -176.991
+v 396.853 522.843 -185.021
+v 417.037 525.231 -184.967
+v 377.971 526.316 -178.944
+v 365.762 534.455 -171.510
+v 350.461 582.420 -148.450
+v 433.749 850.515 -178.347
+v 367.119 557.786 -153.930
+v 296.907 574.824 -67.332
+v 330.277 568.150 -129.785
+v 410.255 662.344 -197.175
+v 479.056 735.865 -236.025
+v 481.443 754.531 -227.940
+v 458.275 744.167 -225.119
+v 445.144 752.903 -210.903
+v 465.600 756.810 -220.398
+v 453.663 760.445 -207.267
+v 419.099 787.737 -180.300
+v 485.676 677.428 -280.680
+v 483.234 658.329 -286.052
+v 340.532 516.061 -165.162
+v 446.826 613.131 -199.128
+v 445.252 672.816 -236.350
+v 443.625 662.507 -230.816
+v 356.213 660.445 -174.332
+v 484.048 634.455 -274.983
+v 382.203 493.163 -196.361
+v 357.569 500.814 -182.037
+v 323.060 455.724 -107.756
+v 460.988 510.635 -212.530
+v 434.292 533.858 -179.812
+v 406.620 767.119 -177.316
+v 320.022 757.027 -21.320
+v 459.034 683.885 -229.568
+v 472.925 689.582 -231.358
+v 430.982 768.747 -179.595
+v 435.703 768.747 -184.695
+v 347.911 488.226 -173.192
+v 444.710 681.498 -226.475
+v 415.627 494.520 -206.942
+v 412.697 478.622 -210.469
+v 396.039 410.418 -177.425
+v 335.540 473.576 -145.249
+v 406.565 445.958 -195.005
+v 329.843 507.596 -149.373
+v 316.929 501.736 -113.507
+v 479.707 745.903 -234.071
+v 461.801 750.950 -223.654
+v 449.105 756.810 -210.686
+v 463.158 687.466 -225.715
+v 433.424 768.747 -182.308
+v 440.260 776.614 -192.075
+v 438.036 768.692 -185.184
+v 467.010 677.320 -254.419
+v 457.244 762.615 -204.174
+v 468.855 760.282 -213.019
+v 483.234 759.468 -219.855
+v 475.203 827.889 -197.935
+v 477.482 811.829 -216.112
+v 478.676 800.326 -219.313
+v 480.629 788.931 -216.057
+v 482.963 780.521 -213.887
+v 457.135 775.529 -199.617
+v 453.120 779.164 -201.896
+v 448.508 784.590 -204.174
+v 444.818 790.667 -200.702
+v 425.990 732.393 -204.826
+v 297.938 660.336 6.352
+v 500.271 692.621 -249.644
+v 448.508 772.762 -190.718
+v 444.384 774.444 -192.237
+v 477.862 696.961 -232.118
+v 450.624 692.892 -213.290
+v 475.529 693.435 -232.172
+v 427.672 624.471 -193.106
+v 397.938 637.547 -187.897
+v 440.695 671.297 -220.669
+v 351.763 428.215 -145.140
+v 363.918 454.042 -171.836
+v 375.909 477.916 -193.051
+v 432.881 803.310 -187.788
+v 455.562 484.156 -219.204
+v 450.461 445.469 -208.244
+v 443.896 402.496 -196.144
+v 374.010 576.397 -164.674
+v 331.199 596.310 -138.521
+v 446.826 570.049 -174.495
+v 348.237 543.082 -155.667
+v 459.577 600.380 -205.585
+v 455.670 665.328 -253.930
+v 311.394 611.774 -118.662
+v 343.245 610.147 -155.233
+v 366.196 617.363 -172.107
+v 400.705 614.107 -180.083
+v 425.827 605.969 -184.099
+v 444.547 597.016 -188.819
+v 483.288 574.661 -223.979
+v 314.596 652.849 -124.305
+v 334.129 540.206 -146.822
+v 491.536 687.466 -272.161
+v 448.508 632.339 -207.322
+v 291.970 573.250 -6.345
+v 458.709 586.652 -191.424
+v 438.958 672.545 -202.384
+v 358.654 557.895 -150.403
+v 454.639 652.794 -246.985
+v 305.643 707.434 -2.547
+v 446.663 563.375 -169.828
+v 468.909 641.400 -264.294
+v 359.685 804.178 -115.569
+v 360.608 825.393 -83.719
+v 298.209 657.461 -59.356
+v 337.113 777.808 -94.136
+v 306.186 535.648 -85.129
+v 430.602 868.421 -168.309
+v 493.435 691.915 -248.450
+v 432.230 646.772 -200.810
+v 315.030 571.948 -111.554
+v 390.450 567.878 -171.022
+v 404.992 569.072 -175.471
+v 436.517 779.327 -189.145
+v 319.479 692.241 -119.096
+v 462.724 895.008 -162.937
+v 409.712 867.716 -128.754
+v 387.141 850.353 -109.166
+v 500.271 446.555 -212.259
+v 500.271 899.186 -167.875
+v 419.316 568.041 -176.285
+v 432.881 565.817 -173.789
+v 441.997 564.677 -170.100
+v 321.324 536.408 -128.320
+v 431.253 551.329 -176.556
+v 416.224 546.663 -179.595
+v 401.194 545.849 -178.673
+v 386.272 548.291 -174.115
+v 376.994 552.143 -168.201
+v 295.442 527.781 -35.211
+v 380.575 565.383 -165.162
+v 500.271 712.751 -232.878
+v 442.865 720.944 -214.701
+v 458.980 680.575 -236.187
+v 475.746 714.053 -231.087
+v 500.271 544.981 -217.577
+v 383.342 829.300 -131.847
+v 406.077 848.671 -148.938
+v 461.856 883.234 -185.184
+v 339.338 796.744 -51.489
+v 441.780 558.492 -172.596
+v 471.677 605.589 -230.327
+v 500.271 887.086 -189.362
+v 433.966 883.397 -149.318
+v 305.426 700.705 -62.666
+v 468.692 778.188 -207.484
+v 464.786 784.428 -209.817
+v 461.259 793.109 -212.313
+v 458.654 803.201 -209.275
+v 451.112 817.580 -195.113
+v 444.004 764.460 -195.276
+v 439.718 762.778 -195.222
+v 436.137 760.716 -195.222
+v 413.402 748.074 -191.369
+v 343.950 702.767 -155.450
+v 471.731 586.110 -213.507
+v 460.336 547.043 -182.742
+v 449.267 550.190 -175.743
+v 447.857 765.383 -193.431
+v 344.059 750.081 -128.103
+v 476.886 545.958 -205.639
+v 441.725 833.098 -185.184
+v 500.271 611.177 -263.426
+v 484.048 595.442 -242.319
+v 500.271 591.427 -246.443
+v 459.360 636.191 -230.762
+v 500.271 869.126 -198.423
+v 500.271 847.802 -197.989
+v 469.778 845.415 -194.571
+v 402.713 794.520 -169.448
+v 423.983 688.280 -197.609
+v 420.130 816.224 -176.502
+v 382.583 685.730 -189.741
+v 407.705 708.085 -194.191
+v 369.072 717.417 -175.363
+v 464.189 865.871 -193.811
+v 448.833 647.314 -218.065
+v 388.171 808.519 -152.465
+v 410.635 830.440 -163.046
+v 389.094 769.235 -168.743
+v 325.990 725.719 -112.693
+v 366.902 772.056 -151.109
+v 316.983 740.912 -70.696
+v 394.900 733.478 -185.238
+v 460.499 618.665 -217.956
+v 461.530 674.010 -257.891
+v 451.112 679.164 -238.466
+v 468.475 660.879 -270.588
+v 446.066 527.292 -188.005
+v 416.820 513.945 -190.827
+v 391.047 511.720 -189.307
+v 369.723 516.332 -181.711
+v 355.128 526.479 -170.371
+v 346.446 562.778 -143.078
+v 294.954 615.735 -62.449
+v 360.119 590.667 -157.946
+v 378.405 596.256 -168.852
+v 402.279 595.822 -176.339
+v 424.525 591.319 -179.866
+v 441.725 585.187 -180.300
+v 453.717 579.002 -181.494
+v 294.194 616.386 6.189
+v 451.546 684.428 -229.514
+v 471.568 623.114 -244.869
+v 473.467 674.878 -271.944
+v 482.908 684.590 -264.836
+v 473.793 678.351 -263.263
+v 456.267 690.179 -223.382
+v 486.110 686.272 -269.666
+v 488.063 690.722 -248.450
+v 453.174 563.755 -172.650
+v 463.104 568.150 -183.610
+v 469.343 571.351 -196.253
+v 371.460 555.128 -161.961
+v 358.220 544.384 -160.984
+v 515.355 614.107 -257.349
+v 626.967 562.453 -160.007
+v 516.332 687.900 -248.667
+v 695.496 490.613 -72.433
+v 578.133 578.785 -179.052
+v 595.334 580.304 -177.696
+v 612.263 579.816 -172.541
+v 634.780 569.615 -157.349
+v 563.429 574.607 -176.991
+v 603.635 522.843 -185.021
+v 583.505 525.231 -184.967
+v 622.572 526.316 -178.944
+v 634.835 534.455 -171.510
+v 650.081 582.420 -148.450
+v 566.739 850.515 -178.347
+v 633.424 557.786 -153.930
+v 703.635 574.824 -67.332
+v 670.266 568.150 -129.785
+v 590.288 662.344 -197.175
+v 521.487 735.865 -236.025
+v 519.099 754.531 -227.940
+v 542.268 744.167 -225.119
+v 555.399 752.903 -210.903
+v 534.943 756.810 -220.398
+v 546.934 760.445 -207.267
+v 581.443 787.737 -180.300
+v 514.867 677.428 -280.680
+v 517.309 658.329 -286.052
+v 660.065 516.061 -165.162
+v 553.717 613.131 -199.128
+v 555.290 672.816 -236.350
+v 556.918 662.507 -230.816
+v 644.330 660.445 -174.332
+v 516.495 634.455 -274.983
+v 618.340 493.163 -196.361
+v 642.973 500.814 -182.037
+v 677.482 455.724 -107.756
+v 539.609 510.635 -212.530
+v 566.251 533.858 -179.812
+v 593.923 767.119 -177.316
+v 680.521 757.027 -21.320
+v 541.508 683.885 -229.568
+v 527.672 689.582 -231.358
+v 569.560 768.747 -179.595
+v 564.840 768.747 -184.695
+v 652.632 488.226 -173.192
+v 555.887 681.498 -226.475
+v 584.916 494.520 -206.942
+v 587.846 478.622 -210.469
+v 604.449 410.418 -177.425
+v 664.948 473.576 -145.249
+v 593.977 445.958 -195.005
+v 670.700 507.596 -149.373
+v 683.614 501.736 -113.507
+v 520.836 745.903 -234.071
+v 538.795 750.950 -223.654
+v 551.438 756.810 -210.686
+v 537.385 687.466 -225.715
+v 567.119 768.747 -182.308
+v 560.282 776.614 -192.075
+v 562.507 768.692 -185.184
+v 533.532 677.320 -254.419
+v 543.299 762.615 -204.174
+v 531.742 760.282 -213.019
+v 517.363 759.468 -219.855
+v 525.339 827.889 -197.935
+v 523.060 811.829 -216.112
+v 521.867 800.326 -219.313
+v 519.913 788.931 -216.057
+v 517.580 780.521 -213.887
+v 543.407 775.529 -199.617
+v 547.423 779.164 -201.896
+v 552.035 784.590 -204.174
+v 555.724 790.667 -200.702
+v 574.552 732.393 -204.826
+v 702.604 660.336 6.352
+v 552.035 772.762 -190.718
+v 556.158 774.444 -192.237
+v 522.680 696.961 -232.118
+v 549.919 692.892 -213.290
+v 525.014 693.435 -232.172
+v 572.870 624.471 -193.106
+v 602.604 637.547 -187.897
+v 559.848 671.297 -220.669
+v 648.779 428.215 -145.140
+v 636.625 454.042 -171.836
+v 624.634 477.916 -193.051
+v 567.661 803.310 -187.788
+v 544.981 484.156 -219.204
+v 550.081 445.469 -208.244
+v 556.701 402.496 -196.144
+v 626.533 576.397 -164.674
+v 669.343 596.310 -138.521
+v 553.717 570.049 -174.495
+v 652.306 543.082 -155.667
+v 540.966 600.380 -205.585
+v 544.872 665.328 -253.930
+v 689.148 611.774 -118.662
+v 657.298 610.147 -155.233
+v 634.292 617.363 -172.107
+v 599.837 614.107 -180.083
+v 574.715 605.969 -184.099
+v 555.996 597.016 -188.819
+v 517.254 574.661 -223.979
+v 685.947 652.849 -124.305
+v 666.413 540.206 -146.822
+v 509.007 687.466 -272.161
+v 552.089 632.339 -207.322
+v 708.573 573.250 -6.345
+v 541.834 586.652 -191.424
+v 561.584 672.545 -202.384
+v 641.888 557.895 -150.403
+v 545.849 652.794 -246.985
+v 694.900 707.434 -2.547
+v 553.880 563.375 -169.828
+v 531.633 641.400 -264.294
+v 640.857 804.178 -115.569
+v 639.935 825.393 -83.719
+v 702.333 657.461 -59.356
+v 663.429 777.808 -94.136
+v 694.357 535.648 -85.129
+v 569.940 868.421 -168.309
+v 507.108 691.915 -248.450
+v 568.313 646.772 -200.810
+v 685.567 571.948 -111.554
+v 610.147 567.878 -171.022
+v 595.551 569.072 -175.471
+v 564.026 779.327 -189.145
+v 681.063 692.241 -119.096
+v 537.819 895.008 -162.937
+v 590.830 867.716 -128.754
+v 613.402 850.353 -109.166
+v 581.226 568.041 -176.285
+v 567.661 565.817 -173.789
+v 558.600 564.677 -170.100
+v 679.219 536.408 -128.320
+v 569.289 551.329 -176.556
+v 584.319 546.663 -179.595
+v 599.349 545.849 -178.673
+v 614.216 548.291 -174.115
+v 623.549 552.143 -168.201
+v 705.100 527.781 -35.211
+v 619.967 565.383 -165.162
+v 557.678 720.944 -214.701
+v 541.508 680.575 -236.187
+v 524.797 714.053 -231.087
+v 617.200 829.300 -131.847
+v 594.466 848.671 -148.938
+v 538.687 883.234 -185.184
+v 661.205 796.744 -51.489
+v 558.763 558.492 -172.596
+v 528.866 605.589 -230.327
+v 566.576 883.397 -149.318
+v 695.062 700.705 -62.666
+v 531.850 778.188 -207.484
+v 535.757 784.428 -209.817
+v 539.338 793.109 -212.313
+v 541.888 803.201 -209.275
+v 549.430 817.580 -195.113
+v 556.538 764.460 -195.276
+v 560.770 762.778 -195.222
+v 564.406 760.716 -195.222
+v 587.141 748.074 -191.369
+v 656.593 702.767 -155.450
+v 528.812 586.110 -213.507
+v 540.206 547.043 -182.742
+v 551.275 550.190 -175.743
+v 552.686 765.383 -193.431
+v 656.484 750.081 -128.103
+v 523.603 545.958 -205.639
+v 558.817 833.098 -185.184
+v 516.495 595.442 -242.319
+v 541.237 636.191 -230.762
+v 530.765 845.415 -194.571
+v 597.830 794.520 -169.448
+v 576.560 688.280 -197.609
+v 580.412 816.224 -176.502
+v 618.014 685.730 -189.741
+v 592.838 708.085 -194.191
+v 631.470 717.417 -175.363
+v 536.354 865.871 -193.811
+v 551.709 647.314 -218.065
+v 612.317 808.519 -152.465
+v 589.908 830.440 -163.046
+v 611.503 769.235 -168.743
+v 674.552 725.719 -112.693
+v 633.641 772.056 -151.109
+v 683.559 740.912 -70.696
+v 605.643 733.478 -185.238
+v 540.043 618.665 -217.956
+v 539.067 674.010 -257.891
+v 549.376 679.164 -238.466
+v 532.013 660.879 -270.588
+v 554.476 527.292 -188.005
+v 583.722 513.945 -190.827
+v 609.495 511.720 -189.307
+v 630.819 516.332 -181.711
+v 645.415 526.479 -170.371
+v 654.097 562.778 -143.078
+v 705.643 615.735 -62.449
+v 640.423 590.667 -157.946
+v 622.084 596.256 -168.852
+v 598.264 595.822 -176.339
+v 576.017 591.319 -179.866
+v 558.817 585.187 -180.300
+v 546.826 579.002 -181.494
+v 706.348 616.386 6.189
+v 548.996 684.428 -229.514
+v 528.974 623.114 -244.869
+v 527.075 674.878 -271.944
+v 517.634 684.590 -264.836
+v 526.750 678.351 -263.263
+v 544.276 690.179 -223.382
+v 514.433 686.272 -269.666
+v 512.480 690.722 -248.450
+v 547.368 563.755 -172.650
+v 537.439 568.150 -183.610
+v 531.199 571.351 -196.253
+v 629.083 555.128 -161.961
+v 642.322 544.384 -160.984
+v 407.379 555.724 -170.479
+v 425.122 555.507 -170.479
+v 407.271 539.609 -170.479
+v 389.419 555.887 -170.479
+v 407.379 571.839 -170.479
+v 593.163 555.724 -170.479
+v 611.123 555.887 -170.479
+v 593.272 539.609 -170.479
+v 575.421 555.507 -170.479
+v 593.163 571.839 -170.479
+vt 0.500 0.347
+vt 0.500 0.453
+vt 0.500 0.398
+vt 0.482 0.528
+vt 0.500 0.473
+vt 0.500 0.502
+vt 0.500 0.599
+vt 0.290 0.619
+vt 0.500 0.688
+vt 0.500 0.730
+vt 0.500 0.893
+vt 0.500 0.334
+vt 0.500 0.321
+vt 0.500 0.308
+vt 0.500 0.305
+vt 0.500 0.294
+vt 0.500 0.281
+vt 0.500 0.263
+vt 0.500 0.219
+vt 0.500 0.437
+vt 0.474 0.426
+vt 0.105 0.746
+vt 0.366 0.590
+vt 0.339 0.587
+vt 0.311 0.591
+vt 0.275 0.611
+vt 0.393 0.596
+vt 0.345 0.656
+vt 0.370 0.654
+vt 0.319 0.653
+vt 0.298 0.646
+vt 0.248 0.589
+vt 0.397 0.157
+vt 0.280 0.624
+vt 0.106 0.600
+vt 0.210 0.609
+vt 0.356 0.466
+vt 0.472 0.350
+vt 0.474 0.320
+vt 0.440 0.343
+vt 0.415 0.333
+vt 0.450 0.319
+vt 0.429 0.317
+vt 0.375 0.272
+vt 0.487 0.452
+vt 0.485 0.473
+vt 0.258 0.686
+vt 0.401 0.545
+vt 0.430 0.451
+vt 0.421 0.466
+vt 0.277 0.468
+vt 0.483 0.500
+vt 0.337 0.717
+vt 0.296 0.707
+vt 0.169 0.806
+vt 0.448 0.697
+vt 0.392 0.646
+vt 0.354 0.303
+vt 0.067 0.270
+vt 0.443 0.427
+vt 0.457 0.415
+vt 0.382 0.305
+vt 0.392 0.306
+vt 0.277 0.728
+vt 0.423 0.437
+vt 0.386 0.719
+vt 0.383 0.744
+vt 0.331 0.880
+vt 0.230 0.768
+vt 0.365 0.811
+vt 0.230 0.700
+vt 0.173 0.721
+vt 0.473 0.334
+vt 0.447 0.331
+vt 0.423 0.326
+vt 0.445 0.420
+vt 0.388 0.306
+vt 0.403 0.293
+vt 0.404 0.306
+vt 0.460 0.443
+vt 0.431 0.308
+vt 0.452 0.308
+vt 0.475 0.308
+vt 0.466 0.221
+vt 0.472 0.264
+vt 0.473 0.282
+vt 0.473 0.295
+vt 0.473 0.305
+vt 0.428 0.305
+vt 0.426 0.296
+vt 0.423 0.288
+vt 0.418 0.280
+vt 0.390 0.360
+vt 0.014 0.440
+vt 0.500 0.420
+vt 0.413 0.305
+vt 0.410 0.298
+vt 0.468 0.398
+vt 0.423 0.414
+vt 0.463 0.406
+vt 0.372 0.527
+vt 0.335 0.504
+vt 0.412 0.453
+vt 0.242 0.852
+vt 0.291 0.799
+vt 0.327 0.743
+vt 0.400 0.251
+vt 0.442 0.738
+vt 0.430 0.812
+vt 0.412 0.891
+vt 0.289 0.601
+vt 0.219 0.565
+vt 0.413 0.601
+vt 0.257 0.645
+vt 0.428 0.562
+vt 0.448 0.463
+vt 0.179 0.542
+vt 0.247 0.543
+vt 0.286 0.532
+vt 0.333 0.539
+vt 0.369 0.553
+vt 0.399 0.567
+vt 0.476 0.594
+vt 0.189 0.476
+vt 0.229 0.651
+vt 0.491 0.438
+vt 0.405 0.515
+vt 0.019 0.598
+vt 0.426 0.580
+vt 0.397 0.451
+vt 0.266 0.623
+vt 0.439 0.481
+vt 0.032 0.356
+vt 0.419 0.613
+vt 0.463 0.494
+vt 0.239 0.220
+vt 0.198 0.168
+vt 0.108 0.459
+vt 0.184 0.260
+vt 0.134 0.666
+vt 0.386 0.117
+vt 0.491 0.421
+vt 0.382 0.491
+vt 0.174 0.602
+vt 0.319 0.604
+vt 0.343 0.599
+vt 0.396 0.290
+vt 0.188 0.411
+vt 0.431 0.056
+vt 0.319 0.102
+vt 0.266 0.130
+vt 0.500 0.809
+vt 0.500 0.046
+vt 0.366 0.601
+vt 0.393 0.604
+vt 0.410 0.609
+vt 0.195 0.658
+vt 0.389 0.638
+vt 0.366 0.644
+vt 0.343 0.645
+vt 0.319 0.642
+vt 0.301 0.637
+vt 0.058 0.681
+vt 0.301 0.613
+vt 0.500 0.382
+vt 0.416 0.376
+vt 0.446 0.434
+vt 0.466 0.379
+vt 0.500 0.648
+vt 0.289 0.180
+vt 0.335 0.147
+vt 0.441 0.098
+vt 0.128 0.208
+vt 0.409 0.626
+vt 0.456 0.548
+vt 0.500 0.091
+vt 0.375 0.076
+vt 0.114 0.385
+vt 0.449 0.305
+vt 0.448 0.295
+vt 0.447 0.284
+vt 0.445 0.269
+vt 0.430 0.233
+vt 0.407 0.314
+vt 0.401 0.319
+vt 0.392 0.322
+vt 0.368 0.336
+vt 0.248 0.399
+vt 0.453 0.579
+vt 0.436 0.640
+vt 0.416 0.631
+vt 0.413 0.308
+vt 0.228 0.316
+vt 0.468 0.647
+vt 0.411 0.196
+vt 0.500 0.530
+vt 0.479 0.557
+vt 0.500 0.560
+vt 0.432 0.506
+vt 0.500 0.133
+vt 0.500 0.178
+vt 0.457 0.181
+vt 0.345 0.255
+vt 0.379 0.426
+vt 0.374 0.220
+vt 0.320 0.429
+vt 0.357 0.396
+vt 0.295 0.378
+vt 0.448 0.138
+vt 0.411 0.491
+vt 0.314 0.225
+vt 0.354 0.187
+vt 0.325 0.296
+vt 0.189 0.354
+vt 0.280 0.285
+vt 0.134 0.317
+vt 0.337 0.355
+vt 0.430 0.533
+vt 0.456 0.451
+vt 0.437 0.441
+vt 0.467 0.470
+vt 0.415 0.665
+vt 0.377 0.677
+vt 0.344 0.680
+vt 0.313 0.678
+vt 0.284 0.667
+vt 0.241 0.617
+vt 0.103 0.531
+vt 0.268 0.575
+vt 0.298 0.567
+vt 0.333 0.566
+vt 0.366 0.574
+vt 0.396 0.583
+vt 0.420 0.590
+vt 0.008 0.519
+vt 0.433 0.430
+vt 0.459 0.521
+vt 0.473 0.454
+vt 0.476 0.436
+vt 0.468 0.445
+vt 0.434 0.418
+vt 0.484 0.437
+vt 0.482 0.422
+vt 0.426 0.610
+vt 0.439 0.604
+vt 0.450 0.600
+vt 0.290 0.632
+vt 0.277 0.637
+vt 0.518 0.528
+vt 0.710 0.619
+vt 0.526 0.426
+vt 0.895 0.746
+vt 0.634 0.590
+vt 0.661 0.587
+vt 0.689 0.591
+vt 0.725 0.611
+vt 0.607 0.596
+vt 0.655 0.656
+vt 0.630 0.654
+vt 0.681 0.653
+vt 0.702 0.646
+vt 0.752 0.589
+vt 0.603 0.157
+vt 0.720 0.624
+vt 0.894 0.600
+vt 0.790 0.609
+vt 0.644 0.466
+vt 0.528 0.350
+vt 0.526 0.320
+vt 0.560 0.343
+vt 0.585 0.333
+vt 0.550 0.319
+vt 0.571 0.317
+vt 0.625 0.272
+vt 0.513 0.453
+vt 0.515 0.473
+vt 0.742 0.685
+vt 0.599 0.545
+vt 0.570 0.451
+vt 0.579 0.466
+vt 0.723 0.468
+vt 0.516 0.500
+vt 0.663 0.717
+vt 0.704 0.707
+vt 0.831 0.806
+vt 0.552 0.697
+vt 0.608 0.646
+vt 0.645 0.303
+vt 0.933 0.270
+vt 0.557 0.427
+vt 0.543 0.415
+vt 0.618 0.305
+vt 0.608 0.306
+vt 0.723 0.728
+vt 0.577 0.437
+vt 0.614 0.719
+vt 0.617 0.744
+vt 0.669 0.880
+vt 0.770 0.768
+vt 0.636 0.811
+vt 0.770 0.700
+vt 0.827 0.721
+vt 0.527 0.334
+vt 0.553 0.331
+vt 0.577 0.326
+vt 0.555 0.420
+vt 0.612 0.306
+vt 0.597 0.293
+vt 0.596 0.306
+vt 0.540 0.443
+vt 0.569 0.308
+vt 0.548 0.308
+vt 0.525 0.308
+vt 0.534 0.221
+vt 0.528 0.264
+vt 0.527 0.282
+vt 0.527 0.295
+vt 0.527 0.305
+vt 0.572 0.305
+vt 0.574 0.296
+vt 0.577 0.288
+vt 0.582 0.280
+vt 0.610 0.360
+vt 0.986 0.440
+vt 0.587 0.305
+vt 0.590 0.298
+vt 0.532 0.398
+vt 0.577 0.414
+vt 0.537 0.406
+vt 0.628 0.527
+vt 0.666 0.504
+vt 0.588 0.453
+vt 0.758 0.852
+vt 0.709 0.798
+vt 0.673 0.743
+vt 0.600 0.251
+vt 0.558 0.738
+vt 0.570 0.812
+vt 0.588 0.891
+vt 0.711 0.601
+vt 0.781 0.565
+vt 0.587 0.601
+vt 0.743 0.645
+vt 0.572 0.562
+vt 0.552 0.463
+vt 0.821 0.542
+vt 0.753 0.543
+vt 0.714 0.532
+vt 0.667 0.539
+vt 0.631 0.553
+vt 0.601 0.568
+vt 0.523 0.594
+vt 0.811 0.476
+vt 0.771 0.651
+vt 0.509 0.437
+vt 0.595 0.515
+vt 0.981 0.598
+vt 0.574 0.580
+vt 0.603 0.451
+vt 0.734 0.623
+vt 0.561 0.481
+vt 0.968 0.356
+vt 0.581 0.613
+vt 0.538 0.495
+vt 0.761 0.220
+vt 0.802 0.168
+vt 0.892 0.459
+vt 0.816 0.260
+vt 0.866 0.666
+vt 0.614 0.117
+vt 0.509 0.421
+vt 0.618 0.492
+vt 0.826 0.602
+vt 0.681 0.604
+vt 0.657 0.599
+vt 0.604 0.290
+vt 0.812 0.411
+vt 0.568 0.055
+vt 0.681 0.102
+vt 0.734 0.130
+vt 0.634 0.601
+vt 0.607 0.604
+vt 0.590 0.609
+vt 0.805 0.658
+vt 0.611 0.638
+vt 0.634 0.644
+vt 0.657 0.645
+vt 0.681 0.642
+vt 0.699 0.637
+vt 0.942 0.681
+vt 0.699 0.613
+vt 0.584 0.376
+vt 0.554 0.434
+vt 0.534 0.379
+vt 0.711 0.180
+vt 0.665 0.147
+vt 0.559 0.097
+vt 0.872 0.208
+vt 0.591 0.626
+vt 0.544 0.548
+vt 0.625 0.076
+vt 0.886 0.385
+vt 0.551 0.305
+vt 0.552 0.295
+vt 0.553 0.284
+vt 0.555 0.269
+vt 0.570 0.233
+vt 0.593 0.314
+vt 0.599 0.319
+vt 0.608 0.322
+vt 0.632 0.337
+vt 0.752 0.399
+vt 0.547 0.580
+vt 0.564 0.640
+vt 0.584 0.631
+vt 0.587 0.308
+vt 0.772 0.316
+vt 0.532 0.648
+vt 0.588 0.196
+vt 0.521 0.557
+vt 0.568 0.507
+vt 0.543 0.181
+vt 0.655 0.254
+vt 0.621 0.426
+vt 0.626 0.220
+vt 0.680 0.429
+vt 0.643 0.396
+vt 0.705 0.378
+vt 0.552 0.137
+vt 0.589 0.491
+vt 0.686 0.225
+vt 0.646 0.187
+vt 0.675 0.296
+vt 0.811 0.354
+vt 0.720 0.285
+vt 0.866 0.317
+vt 0.663 0.355
+vt 0.570 0.534
+vt 0.545 0.452
+vt 0.563 0.441
+vt 0.532 0.470
+vt 0.585 0.665
+vt 0.623 0.677
+vt 0.656 0.680
+vt 0.687 0.678
+vt 0.716 0.667
+vt 0.759 0.617
+vt 0.897 0.531
+vt 0.732 0.575
+vt 0.702 0.567
+vt 0.667 0.566
+vt 0.634 0.574
+vt 0.604 0.583
+vt 0.580 0.590
+vt 0.992 0.519
+vt 0.567 0.431
+vt 0.541 0.521
+vt 0.527 0.454
+vt 0.524 0.436
+vt 0.532 0.445
+vt 0.566 0.418
+vt 0.516 0.437
+vt 0.517 0.422
+vt 0.574 0.610
+vt 0.561 0.605
+vt 0.550 0.600
+vt 0.710 0.632
+vt 0.723 0.637
+vt 0 0
+vt 0 0
+vt 0 0
+vt 0 0
+vt 0 0
+vt 0 0
+vt 0 0
+vt 0 0
+vt 0 0
+vt 0 0
+f 357/357 390/390 265/265
+f 128/128 35/35 163/163
+f 369/369 265/265 390/390
+f 140/140 163/163 35/35
+f 268/268 1/1 303/303
+f 38/38 73/73 1/1
+f 12/12 303/303 1/1
+f 12/12 1/1 73/73
+f 350/350 452/452 351/351
+f 121/121 122/122 232/232
+f 453/453 351/351 452/452
+f 233/233 232/232 122/122
+f 268/268 303/303 270/270
+f 38/38 40/40 73/73
+f 304/304 270/270 303/303
+f 74/74 73/73 40/40
+f 358/358 344/344 351/351
+f 129/129 122/122 115/115
+f 278/278 351/351 344/344
+f 48/48 115/115 122/122
+f 351/351 453/453 358/358
+f 122/122 129/129 233/233
+f 454/454 358/358 453/453
+f 234/234 233/233 129/129
+f 300/300 334/334 298/298
+f 70/70 68/68 105/105
+f 333/333 298/298 334/334
+f 104/104 105/105 68/68
+f 176/176 153/153 397/397
+f 176/176 172/172 153/153
+f 378/378 397/397 153/153
+f 149/149 153/153 172/172
+f 281/281 348/348 331/331
+f 51/51 102/102 119/119
+f 349/349 331/331 348/348
+f 120/120 119/119 102/102
+f 270/270 304/304 271/271
+f 40/40 41/41 74/74
+f 305/305 271/271 304/304
+f 75/75 74/74 41/41
+f 10/10 337/337 152/152
+f 10/10 152/152 108/108
+f 338/338 152/152 337/337
+f 109/109 108/108 152/152
+f 345/345 279/279 361/361
+f 116/116 132/132 49/49
+f 280/280 361/361 279/279
+f 50/50 49/49 132/132
+f 263/263 432/432 419/419
+f 33/33 195/195 212/212
+f 425/425 419/419 432/432
+f 205/205 212/212 195/195
+f 305/305 409/409 271/271
+f 75/75 41/41 185/185
+f 410/410 271/271 409/409
+f 186/186 185/185 41/41
+f 273/273 311/311 408/408
+f 43/43 184/184 81/81
+f 416/416 408/408 311/311
+f 192/192 81/81 184/184
+f 323/323 271/271 411/411
+f 93/93 187/187 41/41
+f 410/410 411/411 271/271
+f 186/186 41/41 187/187
+f 348/348 450/450 349/349
+f 119/119 120/120 230/230
+f 451/451 349/349 450/450
+f 231/231 230/230 120/120
+f 435/435 433/433 431/431
+f 215/215 211/211 213/213
+f 423/423 431/431 433/433
+f 203/203 213/213 211/211
+f 314/314 315/315 19/19
+f 84/84 19/19 85/85
+f 18/18 19/19 315/315
+f 18/18 85/85 19/19
+f 308/308 376/376 307/307
+f 78/78 77/77 147/147
+f 292/292 307/307 376/376
+f 62/62 147/147 77/77
+f 260/260 388/388 261/261
+f 30/30 31/31 161/161
+f 389/389 261/261 388/388
+f 162/162 161/161 31/31
+f 287/287 415/415 385/385
+f 57/57 158/158 191/191
+f 399/399 385/385 415/415
+f 174/174 191/191 158/158
+f 419/419 425/425 407/407
+f 195/195 183/183 205/205
+f 336/336 407/407 425/425
+f 107/107 205/205 183/183
+f 368/368 417/417 365/365
+f 139/139 136/136 193/193
+f 435/435 365/365 417/417
+f 215/215 193/193 136/136
+f 392/392 424/424 328/328
+f 166/166 99/99 204/204
+f 359/359 328/328 424/424
+f 130/130 204/204 99/99
+f 299/299 302/302 285/285
+f 69/69 55/55 72/72
+f 252/252 285/285 302/302
+f 22/22 72/72 55/55
+f 5/5 276/276 6/6
+f 5/5 6/6 46/46
+f 282/282 6/6 276/276
+f 52/52 46/46 6/6
+f 255/255 374/374 254/254
+f 25/25 24/24 145/145
+f 375/375 254/254 374/374
+f 146/146 145/145 24/24
+f 321/321 322/322 308/308
+f 91/91 78/78 92/92
+f 376/376 308/308 322/322
+f 147/147 92/92 78/78
+f 281/281 426/426 412/412
+f 51/51 188/188 206/206
+f 428/428 412/412 426/426
+f 208/208 206/206 188/188
+f 422/422 314/314 201/201
+f 202/202 201/201 84/84
+f 19/19 201/201 314/314
+f 19/19 84/84 201/201
+f 336/336 322/322 407/407
+f 107/107 183/183 92/92
+f 406/406 407/407 322/322
+f 182/182 92/92 183/183
+f 406/406 322/322 405/405
+f 182/182 181/181 92/92
+f 321/321 405/405 322/322
+f 91/91 92/92 181/181
+f 18/18 315/315 17/17
+f 18/18 17/17 85/85
+f 316/316 17/17 315/315
+f 86/86 85/85 17/17
+f 426/426 267/267 427/427
+f 206/206 207/207 37/37
+f 424/424 427/427 267/267
+f 204/204 37/37 207/207
+f 370/370 397/397 401/401
+f 141/141 177/177 172/172
+f 378/378 401/401 397/397
+f 149/149 172/172 177/177
+f 392/392 270/270 323/323
+f 166/166 93/93 40/40
+f 271/271 323/323 270/270
+f 41/41 40/40 93/93
+f 418/418 466/466 414/414
+f 194/194 190/190 246/246
+f 465/465 414/414 466/466
+f 245/245 246/246 190/190
+f 258/258 259/259 387/387
+f 28/28 160/160 29/29
+f 386/386 387/387 259/259
+f 159/159 29/29 160/160
+f 261/261 389/389 468/468
+f 31/31 248/248 162/162
+f 467/467 468/468 389/389
+f 247/247 162/162 248/248
+f 249/249 457/457 420/420
+f 4/4 197/197 237/237
+f 400/400 420/420 457/457
+f 175/175 237/237 197/197
+f 334/334 299/299 333/333
+f 105/105 104/104 69/69
+f 285/285 333/333 299/299
+f 55/55 69/69 104/104
+f 286/286 9/9 418/418
+f 56/56 194/194 9/9
+f 169/169 418/418 9/9
+f 169/169 9/9 194/194
+f 341/341 262/262 347/347
+f 112/112 118/118 32/32
+f 449/449 347/347 262/262
+f 229/229 32/32 118/118
+f 286/286 418/418 442/442
+f 56/56 222/222 194/194
+f 414/414 442/442 418/418
+f 190/190 194/194 222/222
+f 328/328 461/461 327/327
+f 99/99 98/98 241/241
+f 329/329 327/327 461/461
+f 100/100 241/241 98/98
+f 278/278 356/356 330/330
+f 48/48 101/101 127/127
+f 372/372 330/330 356/356
+f 143/143 127/127 101/101
+f 310/310 393/393 439/439
+f 80/80 219/219 167/167
+f 440/440 439/439 393/393
+f 220/220 167/167 219/219
+f 382/382 383/383 257/257
+f 155/155 27/27 156/156
+f 342/342 257/257 383/383
+f 113/113 156/156 27/27
+f 361/361 280/280 421/421
+f 132/132 199/199 50/50
+f 430/430 421/421 280/280
+f 210/210 50/50 199/199
+f 366/366 365/365 380/380
+f 137/137 151/151 136/136
+f 395/395 380/380 365/365
+f 170/170 136/136 151/151
+f 356/356 278/278 438/438
+f 127/127 218/218 48/48
+f 344/344 438/438 278/278
+f 115/115 48/48 218/218
+f 444/444 445/445 283/283
+f 224/224 53/53 225/225
+f 284/284 283/283 445/445
+f 54/54 225/225 53/53
+f 282/282 276/276 364/364
+f 52/52 135/135 46/46
+f 441/441 364/364 276/276
+f 221/221 46/46 135/135
+f 432/432 263/263 396/396
+f 212/212 171/171 33/33
+f 370/370 396/396 263/263
+f 141/141 33/33 171/171
+f 338/338 300/300 339/339
+f 109/109 110/110 70/70
+f 298/298 339/339 300/300
+f 68/68 70/70 110/110
+f 336/336 274/274 322/322
+f 107/107 92/92 44/44
+f 376/376 322/322 274/274
+f 147/147 44/44 92/92
+f 349/349 451/451 350/350
+f 120/120 121/121 231/231
+f 452/452 350/350 451/451
+f 232/232 231/231 121/121
+f 468/468 360/360 343/343
+f 248/248 114/114 131/131
+f 447/447 343/343 360/360
+f 227/227 131/131 114/114
+f 283/283 284/284 335/335
+f 53/53 106/106 54/54
+f 294/294 335/335 284/284
+f 64/64 54/54 106/106
+f 251/251 459/459 463/463
+f 21/21 243/243 239/239
+f 462/462 463/463 459/459
+f 242/242 239/239 243/243
+f 277/277 354/354 301/301
+f 47/47 71/71 125/125
+f 384/384 301/301 354/354
+f 157/157 125/125 71/71
+f 326/326 293/293 325/325
+f 97/97 96/96 63/63
+f 309/309 325/325 293/293
+f 79/79 63/63 96/96
+f 284/284 277/277 294/294
+f 54/54 64/64 47/47
+f 301/301 294/294 277/277
+f 71/71 47/47 64/64
+f 448/448 265/265 346/346
+f 228/228 117/117 35/35
+f 373/373 346/346 265/265
+f 144/144 35/35 117/117
+f 353/353 346/346 347/347
+f 124/124 118/118 117/117
+f 341/341 347/347 346/346
+f 112/112 117/117 118/118
+f 2/2 20/20 275/275
+f 2/2 45/45 20/20
+f 355/355 275/275 20/20
+f 126/126 20/20 45/45
+f 249/249 282/282 457/457
+f 4/4 237/237 52/52
+f 364/364 457/457 282/282
+f 135/135 52/52 237/237
+f 426/426 427/427 428/428
+f 206/206 208/208 207/207
+f 437/437 428/428 427/427
+f 217/217 207/207 208/208
+f 381/381 382/382 253/253
+f 154/154 23/23 155/155
+f 257/257 253/253 382/382
+f 27/27 155/155 23/23
+f 392/392 394/394 270/270
+f 166/166 40/40 168/168
+f 268/268 270/270 394/394
+f 38/38 168/168 40/40
+f 200/200 429/429 201/201
+f 200/200 201/201 209/209
+f 422/422 201/201 429/429
+f 202/202 209/209 201/201
+f 331/331 330/330 267/267
+f 102/102 37/37 101/101
+f 372/372 267/267 330/330
+f 143/143 101/101 37/37
+f 423/423 433/433 274/274
+f 203/203 44/44 213/213
+f 288/288 274/274 433/433
+f 58/58 213/213 44/44
+f 291/291 251/251 329/329
+f 61/61 100/100 21/21
+f 463/463 329/329 251/251
+f 243/243 21/21 100/100
+f 259/259 287/287 386/386
+f 29/29 159/159 57/57
+f 385/385 386/386 287/287
+f 158/158 57/57 159/159
+f 343/343 447/447 354/354
+f 114/114 125/125 227/227
+f 266/266 354/354 447/447
+f 36/36 227/227 125/125
+f 258/258 387/387 260/260
+f 28/28 30/30 160/160
+f 388/388 260/260 387/387
+f 161/161 160/160 30/30
+f 431/431 423/423 432/432
+f 211/211 212/212 203/203
+f 425/425 432/432 423/423
+f 205/205 203/203 212/212
+f 446/446 343/343 277/277
+f 226/226 47/47 114/114
+f 354/354 277/277 343/343
+f 125/125 114/114 47/47
+f 425/425 423/423 336/336
+f 205/205 107/107 203/203
+f 274/274 336/336 423/423
+f 44/44 203/203 107/107
+f 307/307 293/293 308/308
+f 77/77 78/78 63/63
+f 326/326 308/308 293/293
+f 97/97 63/63 78/78
+f 367/367 448/448 353/353
+f 138/138 124/124 228/228
+f 346/346 353/353 448/448
+f 117/117 228/228 124/124
+f 303/303 269/269 304/304
+f 73/73 74/74 39/39
+f 272/272 304/304 269/269
+f 42/42 39/39 74/74
+f 372/372 359/359 267/267
+f 143/143 37/37 130/130
+f 424/424 267/267 359/359
+f 204/204 130/130 37/37
+f 328/328 295/295 461/461
+f 99/99 241/241 65/65
+f 456/456 461/461 295/295
+f 236/236 65/65 241/241
+f 295/295 332/332 279/279
+f 65/65 49/49 103/103
+f 280/280 279/279 332/332
+f 50/50 103/103 49/49
+f 304/304 272/272 305/305
+f 74/74 75/75 42/42
+f 273/273 305/305 272/272
+f 43/43 42/42 75/75
+f 428/428 437/437 435/435
+f 208/208 215/215 217/217
+f 433/433 435/435 437/437
+f 213/213 217/217 215/215
+f 305/305 273/273 409/409
+f 75/75 185/185 43/43
+f 408/408 409/409 273/273
+f 184/184 43/43 185/185
+f 395/395 431/431 396/396
+f 170/170 171/171 211/211
+f 432/432 396/396 431/431
+f 212/212 211/211 171/171
+f 396/396 370/370 379/379
+f 171/171 150/150 141/141
+f 401/401 379/379 370/370
+f 177/177 141/141 150/150
+f 297/297 335/335 300/300
+f 67/67 70/70 106/106
+f 334/334 300/300 335/335
+f 105/105 106/106 70/70
+f 418/418 169/169 352/352
+f 194/194 123/123 169/169
+f 7/7 352/352 169/169
+f 7/7 169/169 123/123
+f 281/281 412/412 353/353
+f 51/51 124/124 188/188
+f 377/377 353/353 412/412
+f 148/148 188/188 124/124
+f 320/320 321/321 326/326
+f 90/90 97/97 91/91
+f 308/308 326/326 321/321
+f 78/78 91/91 97/97
+f 286/286 296/296 337/337
+f 56/56 108/108 66/66
+f 297/297 337/337 296/296
+f 67/67 66/66 108/108
+f 405/405 321/321 404/404
+f 181/181 180/180 91/91
+f 320/320 404/404 321/321
+f 90/90 91/91 180/180
+f 331/331 349/349 330/330
+f 102/102 101/101 120/120
+f 350/350 330/330 349/349
+f 121/121 120/120 101/101
+f 335/335 294/294 334/334
+f 106/106 105/105 64/64
+f 299/299 334/334 294/294
+f 69/69 64/64 105/105
+f 324/324 455/455 367/367
+f 94/94 138/138 235/235
+f 448/448 367/367 455/455
+f 228/228 235/235 138/138
+f 17/17 316/316 16/16
+f 17/17 16/16 86/86
+f 317/317 16/16 316/316
+f 87/87 86/86 16/16
+f 430/430 280/280 359/359
+f 210/210 130/130 50/50
+f 332/332 359/359 280/280
+f 103/103 50/50 130/130
+f 16/16 317/317 15/15
+f 16/16 15/15 87/87
+f 318/318 15/15 317/317
+f 88/88 87/87 15/15
+f 9/9 286/286 10/10
+f 9/9 10/10 56/56
+f 337/337 10/10 286/286
+f 108/108 56/56 10/10
+f 330/330 350/350 278/278
+f 101/101 48/48 121/121
+f 351/351 278/278 350/350
+f 122/122 121/121 48/48
+f 253/253 254/254 381/381
+f 23/23 154/154 24/24
+f 375/375 381/381 254/254
+f 146/146 24/24 154/154
+f 403/403 404/404 319/319
+f 179/179 89/89 180/180
+f 320/320 319/319 404/404
+f 90/90 180/180 89/89
+f 352/352 7/7 420/420
+f 123/123 197/197 7/7
+f 198/198 420/420 7/7
+f 198/198 7/7 197/197
+f 325/325 319/319 326/326
+f 96/96 97/97 89/89
+f 320/320 326/326 319/319
+f 90/90 89/89 97/97
+f 398/398 368/368 366/366
+f 173/173 137/137 139/139
+f 365/365 366/366 368/368
+f 136/136 139/139 137/137
+f 289/289 436/436 398/398
+f 59/59 173/173 216/216
+f 368/368 398/398 436/436
+f 139/139 216/216 173/173
+f 439/439 440/440 345/345
+f 219/219 116/116 220/220
+f 279/279 345/345 440/440
+f 49/49 220/220 116/116
+f 272/272 312/312 273/273
+f 42/42 43/43 82/82
+f 311/311 273/273 312/312
+f 81/81 82/82 43/43
+f 6/6 282/282 196/196
+f 6/6 196/196 52/52
+f 249/249 196/196 282/282
+f 4/4 52/52 196/196
+f 274/274 288/288 376/376
+f 44/44 147/147 58/58
+f 292/292 376/376 288/288
+f 62/62 58/58 147/147
+f 397/397 429/429 176/176
+f 172/172 176/176 209/209
+f 200/200 176/176 429/429
+f 200/200 209/209 176/176
+f 269/269 313/313 272/272
+f 39/39 42/42 83/83
+f 312/312 272/272 313/313
+f 82/82 83/83 42/42
+f 445/445 446/446 284/284
+f 225/225 54/54 226/226
+f 277/277 284/284 446/446
+f 47/47 226/226 54/54
+f 255/255 340/340 374/374
+f 25/25 145/145 111/111
+f 391/391 374/374 340/340
+f 164/164 111/111 145/145
+f 296/296 283/283 297/297
+f 66/66 67/67 53/53
+f 335/335 297/297 283/283
+f 106/106 53/53 67/67
+f 347/347 449/449 348/348
+f 118/118 119/119 229/229
+f 450/450 348/348 449/449
+f 230/230 229/229 119/119
+f 455/455 357/357 448/448
+f 235/235 228/228 128/128
+f 265/265 448/448 357/357
+f 35/35 128/128 228/228
+f 337/337 297/297 338/338
+f 108/108 109/109 67/67
+f 300/300 338/338 297/297
+f 70/70 67/67 109/109
+f 152/152 338/338 11/11
+f 152/152 11/11 109/109
+f 339/339 11/11 338/338
+f 110/110 109/109 11/11
+f 279/279 440/440 295/295
+f 49/49 65/65 220/220
+f 456/456 295/295 440/440
+f 236/236 220/220 65/65
+f 408/408 416/416 293/293
+f 184/184 63/63 192/192
+f 309/309 293/293 416/416
+f 79/79 192/192 63/63
+f 359/359 372/372 430/430
+f 130/130 210/210 143/143
+f 356/356 430/430 372/372
+f 127/127 143/143 210/210
+f 346/346 373/373 341/341
+f 117/117 112/112 144/144
+f 266/266 341/341 373/373
+f 36/36 144/144 112/112
+f 353/353 347/347 281/281
+f 124/124 51/51 118/118
+f 348/348 281/281 347/347
+f 119/119 118/118 51/51
+f 296/296 443/443 283/283
+f 66/66 53/53 223/223
+f 444/444 283/283 443/443
+f 224/224 223/223 53/53
+f 20/20 95/95 355/355
+f 20/20 126/126 95/95
+f 371/371 355/355 95/95
+f 142/142 95/95 126/126
+f 296/296 286/286 443/443
+f 66/66 223/223 56/56
+f 442/442 443/443 286/286
+f 222/222 56/56 223/223
+f 420/420 198/198 249/249
+f 197/197 4/4 198/198
+f 196/196 249/249 198/198
+f 196/196 198/198 4/4
+f 360/360 264/264 256/256
+f 131/131 26/26 34/34
+f 250/250 256/256 264/264
+f 8/8 34/34 26/26
+f 276/276 275/275 441/441
+f 46/46 221/221 45/45
+f 458/458 441/441 275/275
+f 238/238 45/45 221/221
+f 301/301 384/384 302/302
+f 71/71 72/72 157/157
+f 369/369 302/302 384/384
+f 140/140 157/157 72/72
+f 418/418 352/352 466/466
+f 194/194 246/246 123/123
+f 413/413 466/466 352/352
+f 189/189 123/123 246/246
+f 467/467 264/264 468/468
+f 247/247 248/248 34/34
+f 360/360 468/468 264/264
+f 131/131 34/34 248/248
+f 390/390 252/252 369/369
+f 163/163 140/140 22/22
+f 302/302 369/369 252/252
+f 72/72 22/22 140/140
+f 380/380 395/395 379/379
+f 151/151 150/150 170/170
+f 396/396 379/379 395/395
+f 171/171 170/170 150/150
+f 352/352 420/420 413/413
+f 123/123 189/189 197/197
+f 400/400 413/413 420/420
+f 175/175 197/197 189/189
+f 427/427 323/323 437/437
+f 207/207 217/217 93/93
+f 411/411 437/437 323/323
+f 187/187 93/93 217/217
+f 394/394 327/327 165/165
+f 168/168 165/165 98/98
+f 3/3 165/165 327/327
+f 3/3 98/98 165/165
+f 355/355 371/371 462/462
+f 126/126 242/242 142/142
+f 463/463 462/462 371/371
+f 243/243 142/142 242/242
+f 1/1 268/268 165/165
+f 1/1 165/165 38/38
+f 394/394 165/165 268/268
+f 168/168 38/38 165/165
+f 12/12 13/13 303/303
+f 12/12 73/73 13/13
+f 269/269 303/303 13/13
+f 39/39 13/13 73/73
+f 13/13 14/14 269/269
+f 13/13 39/39 14/14
+f 313/313 269/269 14/14
+f 83/83 14/14 39/39
+f 294/294 301/301 299/299
+f 64/64 69/69 71/71
+f 302/302 299/299 301/301
+f 72/72 71/71 69/69
+f 341/341 266/266 262/262
+f 112/112 32/32 36/36
+f 447/447 262/262 266/266
+f 227/227 36/36 32/32
+f 281/281 331/331 426/426
+f 51/51 206/206 102/102
+f 267/267 426/426 331/331
+f 37/37 102/102 206/206
+f 424/424 392/392 427/427
+f 204/204 207/207 166/166
+f 323/323 427/427 392/392
+f 93/93 166/166 207/207
+f 430/430 356/356 421/421
+f 210/210 199/199 127/127
+f 438/438 421/421 356/356
+f 218/218 127/127 199/199
+f 392/392 328/328 394/394
+f 166/166 168/168 99/99
+f 327/327 394/394 328/328
+f 98/98 99/99 168/168
+f 458/458 439/439 441/441
+f 238/238 221/221 219/219
+f 345/345 441/441 439/439
+f 116/116 219/219 221/221
+f 383/383 363/363 342/342
+f 156/156 113/113 134/134
+f 464/464 342/342 363/363
+f 244/244 134/134 113/113
+f 458/458 462/462 460/460
+f 238/238 240/240 242/242
+f 459/459 460/460 462/462
+f 239/239 242/242 240/240
+f 435/435 431/431 365/365
+f 215/215 136/136 211/211
+f 395/395 365/365 431/431
+f 170/170 211/211 136/136
+f 415/415 464/464 399/399
+f 191/191 174/174 244/244
+f 363/363 399/399 464/464
+f 134/134 244/244 174/174
+f 263/263 429/429 370/370
+f 33/33 141/141 209/209
+f 397/397 370/370 429/429
+f 172/172 209/209 141/141
+f 458/458 275/275 462/462
+f 238/238 242/242 45/45
+f 355/355 462/462 275/275
+f 126/126 45/45 242/242
+f 317/317 404/404 318/318
+f 87/87 88/88 180/180
+f 403/403 318/318 404/404
+f 179/179 180/180 88/88
+f 316/316 405/405 317/317
+f 86/86 87/87 181/181
+f 404/404 317/317 405/405
+f 180/180 181/181 87/87
+f 315/315 406/406 316/316
+f 85/85 86/86 182/182
+f 405/405 316/316 406/406
+f 181/181 182/182 86/86
+f 314/314 407/407 315/315
+f 84/84 85/85 183/183
+f 406/406 315/315 407/407
+f 182/182 183/183 85/85
+f 419/419 407/407 422/422
+f 195/195 202/202 183/183
+f 314/314 422/422 407/407
+f 84/84 183/183 202/202
+f 367/367 402/402 324/324
+f 138/138 94/94 178/178
+f 362/362 324/324 402/402
+f 133/133 178/178 94/94
+f 409/409 408/408 307/307
+f 185/185 77/77 184/184
+f 293/293 307/307 408/408
+f 63/63 184/184 77/77
+f 409/409 307/307 410/410
+f 185/185 186/186 77/77
+f 292/292 410/410 307/307
+f 62/62 77/77 186/186
+f 411/411 410/410 288/288
+f 187/187 58/58 186/186
+f 292/292 288/288 410/410
+f 62/62 186/186 58/58
+f 437/437 411/411 433/433
+f 217/217 213/213 187/187
+f 288/288 433/433 411/411
+f 58/58 187/187 213/213
+f 435/435 417/417 428/428
+f 215/215 208/208 193/193
+f 412/412 428/428 417/417
+f 188/188 193/193 208/208
+f 265/265 369/369 373/373
+f 35/35 144/144 140/140
+f 384/384 373/373 369/369
+f 157/157 140/140 144/144
+f 458/458 460/460 439/439
+f 238/238 219/219 240/240
+f 310/310 439/439 460/460
+f 80/80 240/240 219/219
+f 353/353 377/377 367/367
+f 124/124 138/138 148/148
+f 402/402 367/367 377/377
+f 178/178 148/148 138/138
+f 5/5 2/2 276/276
+f 5/5 46/46 2/2
+f 275/275 276/276 2/2
+f 45/45 2/2 46/46
+f 429/429 263/263 422/422
+f 209/209 202/202 33/33
+f 419/419 422/422 263/263
+f 195/195 33/33 202/202
+f 328/328 359/359 295/295
+f 99/99 65/65 130/130
+f 332/332 295/295 359/359
+f 103/103 130/130 65/65
+f 368/368 436/436 417/417
+f 139/139 193/193 216/216
+f 434/434 417/417 436/436
+f 214/214 216/216 193/193
+f 456/456 440/440 290/290
+f 236/236 60/60 220/220
+f 393/393 290/290 440/440
+f 167/167 220/220 60/60
+f 329/329 463/463 327/327
+f 100/100 98/98 243/243
+f 371/371 327/327 463/463
+f 142/142 243/243 98/98
+f 327/327 371/371 3/3
+f 98/98 3/3 142/142
+f 95/95 3/3 371/371
+f 95/95 142/142 3/3
+f 461/461 456/456 306/306
+f 241/241 76/76 236/236
+f 290/290 306/306 456/456
+f 60/60 236/236 76/76
+f 449/449 340/340 450/450
+f 229/229 230/230 111/111
+f 255/255 450/450 340/340
+f 25/25 111/111 230/230
+f 262/262 447/447 256/256
+f 32/32 26/26 227/227
+f 360/360 256/256 447/447
+f 131/131 227/227 26/26
+f 450/450 255/255 451/451
+f 230/230 231/231 25/25
+f 254/254 451/451 255/255
+f 24/24 25/25 231/231
+f 451/451 254/254 452/452
+f 231/231 232/232 24/24
+f 253/253 452/452 254/254
+f 23/23 24/24 232/232
+f 452/452 253/253 453/453
+f 232/232 233/233 23/23
+f 257/257 453/453 253/253
+f 27/27 23/23 233/233
+f 257/257 342/342 453/453
+f 27/27 233/233 113/113
+f 454/454 453/453 342/342
+f 234/234 113/113 233/233
+f 414/414 465/465 415/415
+f 190/190 191/191 245/245
+f 464/464 415/415 465/465
+f 244/244 245/245 191/191
+f 442/442 414/414 287/287
+f 222/222 57/57 190/190
+f 415/415 287/287 414/414
+f 191/191 190/190 57/57
+f 442/442 287/287 443/443
+f 222/222 223/223 57/57
+f 259/259 443/443 287/287
+f 29/29 57/57 223/223
+f 443/443 259/259 444/444
+f 223/223 224/224 29/29
+f 258/258 444/444 259/259
+f 28/28 29/29 224/224
+f 445/445 444/444 260/260
+f 225/225 30/30 224/224
+f 258/258 260/260 444/444
+f 28/28 224/224 30/30
+f 260/260 261/261 445/445
+f 30/30 225/225 31/31
+f 446/446 445/445 261/261
+f 226/226 31/31 225/225
+f 261/261 468/468 446/446
+f 31/31 226/226 248/248
+f 343/343 446/446 468/468
+f 114/114 248/248 226/226
+f 251/251 310/310 459/459
+f 21/21 239/239 80/80
+f 460/460 459/459 310/310
+f 240/240 80/80 239/239
+f 291/291 306/306 393/393
+f 61/61 167/167 76/76
+f 290/290 393/393 306/306
+f 60/60 76/76 167/167
+f 461/461 306/306 329/329
+f 241/241 100/100 76/76
+f 291/291 329/329 306/306
+f 61/61 76/76 100/100
+f 377/377 434/434 402/402
+f 148/148 178/178 214/214
+f 436/436 402/402 434/434
+f 216/216 214/214 178/178
+f 251/251 291/291 310/310
+f 21/21 80/80 61/61
+f 393/393 310/310 291/291
+f 167/167 61/61 80/80
+f 412/412 417/417 377/377
+f 188/188 148/148 193/193
+f 434/434 377/377 417/417
+f 214/214 193/193 148/148
+f 342/342 464/464 454/454
+f 113/113 234/234 244/244
+f 465/465 454/454 464/464
+f 245/245 244/244 234/234
+f 454/454 465/465 358/358
+f 234/234 129/129 245/245
+f 466/466 358/358 465/465
+f 246/246 245/245 129/129
+f 413/413 344/344 466/466
+f 189/189 246/246 115/115
+f 358/358 466/466 344/344
+f 129/129 115/115 246/246
+f 438/438 344/344 400/400
+f 218/218 175/175 115/115
+f 413/413 400/400 344/344
+f 189/189 115/115 175/175
+f 364/364 441/441 361/361
+f 135/135 132/132 221/221
+f 345/345 361/361 441/441
+f 116/116 221/221 132/132
+f 457/457 421/421 400/400
+f 237/237 175/175 199/199
+f 438/438 400/400 421/421
+f 218/218 199/199 175/175
+f 457/457 364/364 421/421
+f 237/237 199/199 135/135
+f 361/361 421/421 364/364
+f 132/132 135/135 199/199
+f 362/362 402/402 289/289
+f 133/133 59/59 178/178
+f 436/436 289/289 402/402
+f 216/216 178/178 59/59
+f 354/354 266/266 384/384
+f 125/125 157/157 36/36
+f 373/373 384/384 266/266
+f 144/144 36/36 157/157
+f 256/256 250/250 340/340
+f 26/26 111/111 8/8
+f 391/391 340/340 250/250
+f 164/164 8/8 111/111
+f 262/262 256/256 449/449
+f 32/32 229/229 26/26
+f 340/340 449/449 256/256
+f 111/111 26/26 229/229
+f 469/469 470/470 471/471
+f 469/469 471/471 472/472
+f 469/469 472/472 473/473
+f 469/469 473/473 470/470
+f 474/474 475/475 476/476
+f 474/474 476/476 477/477
+f 474/474 477/477 478/478
+f 474/474 478/478 475/475
+
diff --git a/mini_live/obj/obj_mediapipe/face_wrap_entity.obj b/mini_live/obj/obj_mediapipe/face_wrap_entity.obj
new file mode 100644
index 0000000..75ef296
--- /dev/null
+++ b/mini_live/obj/obj_mediapipe/face_wrap_entity.obj
@@ -0,0 +1,697 @@
+v 500.271 739.284 -238.683 2.00 0
+v 500.271 697.341 -236.893 -1.00 1
+v 500.271 746.772 -236.622 2.00 2
+v 500.271 754.693 -230.707 2.00 3
+v 500.271 759.957 -222.134 2.00 4
+v 500.271 781.823 -216.166 2.01 5
+v 500.271 791.210 -218.390 2.01 6
+v 500.271 802.767 -221.375 2.01 7
+v 500.271 814.324 -217.197 2.01 8
+v 500.271 829.517 -198.532 0.00 9
+v 433.749 850.515 -178.347 0.00 10
+v 410.255 662.344 -197.175 0.00 11
+v 479.056 735.865 -236.025 2.00 12
+v 481.443 754.531 -227.940 2.00 13
+v 458.275 744.167 -225.119 2.00 14
+v 445.144 752.903 -210.903 2.00 15
+v 465.600 756.810 -220.398 2.00 16
+v 453.663 760.445 -207.267 2.00 17
+v 419.099 787.737 -180.300 0.00 18
+v 356.213 660.445 -174.332 0.00 19
+v 406.620 767.119 -177.316 0.00 20
+v 320.022 757.027 -21.320 0.00 21
+v 430.982 768.747 -179.595 2.00 22
+v 435.703 768.747 -184.695 2.00 23
+v 479.707 745.903 -234.071 2.00 24
+v 461.801 750.950 -223.654 2.00 25
+v 449.105 756.810 -210.686 2.00 26
+v 433.424 768.747 -182.308 2.00 27
+v 440.260 776.614 -192.075 2.01 28
+v 438.036 768.692 -185.184 2.00 29
+v 457.244 762.615 -204.174 2.00 30
+v 468.855 760.282 -213.019 2.00 31
+v 483.234 759.468 -219.855 2.00 32
+v 475.203 827.889 -197.935 0.00 33
+v 477.482 811.829 -216.112 2.01 34
+v 478.676 800.326 -219.313 2.01 35
+v 480.629 788.931 -216.057 2.01 36
+v 482.963 780.521 -213.887 2.01 37
+v 457.135 775.529 -199.617 2.01 38
+v 453.120 779.164 -201.896 2.01 39
+v 448.508 784.590 -204.174 2.01 40
+v 444.818 790.667 -200.702 2.01 41
+v 425.990 732.393 -204.826 0.00 42
+v 297.938 660.336 6.352 0.00 43
+v 448.508 772.762 -190.718 2.01 44
+v 444.384 774.444 -192.237 2.01 45
+v 477.862 696.961 -232.118 -1.00 46
+v 450.624 692.892 -213.290 -1.00 47
+v 427.672 624.471 -193.106 -1.00 48
+v 397.938 637.547 -187.897 0.00 49
+v 432.881 803.310 -187.788 0.00 50
+v 311.394 611.774 -118.662 -1.00 51
+v 343.245 610.147 -155.233 -1.00 52
+v 366.196 617.363 -172.107 -1.00 53
+v 400.705 614.107 -180.083 -1.00 54
+v 314.596 652.849 -124.305 0.00 55
+v 438.958 672.545 -202.384 -1.00 56
+v 305.643 707.434 -2.547 0.00 57
+v 359.685 804.178 -115.569 0.00 58
+v 360.608 825.393 -83.719 0.00 59
+v 298.209 657.461 -59.356 0.00 60
+v 337.113 777.808 -94.136 0.00 61
+v 430.602 868.421 -168.309 0.00 62
+v 432.230 646.772 -200.810 -1.00 63
+v 436.517 779.327 -189.145 2.01 64
+v 319.479 692.241 -119.096 0.00 65
+v 462.724 895.008 -162.937 0.00 66
+v 409.712 867.716 -128.754 0.00 67
+v 387.141 850.353 -109.166 0.00 68
+v 500.271 899.186 -167.875 0.00 69
+v 500.271 712.751 -232.878 0.00 70
+v 442.865 720.944 -214.701 0.00 71
+v 475.746 714.053 -231.087 0.00 72
+v 383.342 829.300 -131.847 0.00 73
+v 406.077 848.671 -148.938 0.00 74
+v 461.856 883.234 -185.184 0.00 75
+v 339.338 796.744 -51.489 0.00 76
+v 500.271 887.086 -189.362 0.00 77
+v 433.966 883.397 -149.318 0.00 78
+v 305.426 700.705 -62.666 0.00 79
+v 468.692 778.188 -207.484 2.01 80
+v 464.786 784.428 -209.817 2.01 81
+v 461.259 793.109 -212.313 2.01 82
+v 458.654 803.201 -209.275 2.01 83
+v 451.112 817.580 -195.113 0.00 84
+v 444.004 764.460 -195.276 2.00 85
+v 439.718 762.778 -195.222 2.00 86
+v 436.137 760.716 -195.222 2.00 87
+v 413.402 748.074 -191.369 0.00 88
+v 343.950 702.767 -155.450 0.00 89
+v 447.857 765.383 -193.431 2.00 90
+v 344.059 750.081 -128.103 0.00 91
+v 441.725 833.098 -185.184 0.00 92
+v 500.271 869.126 -198.423 0.00 93
+v 500.271 847.802 -197.989 0.00 94
+v 469.778 845.415 -194.571 0.00 95
+v 402.713 794.520 -169.448 0.00 96
+v 423.983 688.280 -197.609 0.00 97
+v 420.130 816.224 -176.502 0.00 98
+v 382.583 685.730 -189.741 0.00 99
+v 407.705 708.085 -194.191 0.00 100
+v 369.072 717.417 -175.363 0.00 101
+v 464.189 865.871 -193.811 0.00 102
+v 388.171 808.519 -152.465 0.00 103
+v 410.635 830.440 -163.046 0.00 104
+v 389.094 769.235 -168.743 0.00 105
+v 325.990 725.719 -112.693 0.00 106
+v 366.902 772.056 -151.109 0.00 107
+v 316.983 740.912 -70.696 0.00 108
+v 394.900 733.478 -185.238 0.00 109
+v 294.954 615.735 -62.449 -1.00 110
+v 294.194 616.386 6.189 -1.00 111
+v 566.739 850.515 -178.347 0.00 112
+v 590.288 662.344 -197.175 0.00 113
+v 521.487 735.865 -236.025 2.00 114
+v 519.099 754.531 -227.940 2.00 115
+v 542.268 744.167 -225.119 2.00 116
+v 555.399 752.903 -210.903 2.00 117
+v 534.943 756.810 -220.398 2.00 118
+v 546.934 760.445 -207.267 2.00 119
+v 581.443 787.737 -180.300 0.00 120
+v 644.330 660.445 -174.332 0.00 121
+v 593.923 767.119 -177.316 0.00 122
+v 680.521 757.027 -21.320 0.00 123
+v 569.560 768.747 -179.595 2.00 124
+v 564.840 768.747 -184.695 2.00 125
+v 520.836 745.903 -234.071 2.00 126
+v 538.795 750.950 -223.654 2.00 127
+v 551.438 756.810 -210.686 2.00 128
+v 567.119 768.747 -182.308 2.00 129
+v 560.282 776.614 -192.075 2.01 130
+v 562.507 768.692 -185.184 2.00 131
+v 543.299 762.615 -204.174 2.00 132
+v 531.742 760.282 -213.019 2.00 133
+v 517.363 759.468 -219.855 2.00 134
+v 525.339 827.889 -197.935 0.00 135
+v 523.060 811.829 -216.112 2.01 136
+v 521.867 800.326 -219.313 2.01 137
+v 519.913 788.931 -216.057 2.01 138
+v 517.580 780.521 -213.887 2.01 139
+v 543.407 775.529 -199.617 2.01 140
+v 547.423 779.164 -201.896 2.01 141
+v 552.035 784.590 -204.174 2.01 142
+v 555.724 790.667 -200.702 2.01 143
+v 574.552 732.393 -204.826 0.00 144
+v 702.604 660.336 6.352 0.00 145
+v 552.035 772.762 -190.718 2.01 146
+v 556.158 774.444 -192.237 2.01 147
+v 522.680 696.961 -232.118 -1.00 148
+v 549.919 692.892 -213.290 -1.00 149
+v 572.870 624.471 -193.106 -1.00 150
+v 602.604 637.547 -187.897 0.00 151
+v 567.661 803.310 -187.788 0.00 152
+v 689.148 611.774 -118.662 -1.00 153
+v 657.298 610.147 -155.233 -1.00 154
+v 634.292 617.363 -172.107 -1.00 155
+v 599.837 614.107 -180.083 -1.00 156
+v 685.947 652.849 -124.305 0.00 157
+v 561.584 672.545 -202.384 -1.00 158
+v 694.900 707.434 -2.547 0.00 159
+v 640.857 804.178 -115.569 0.00 160
+v 639.935 825.393 -83.719 0.00 161
+v 702.333 657.461 -59.356 0.00 162
+v 663.429 777.808 -94.136 0.00 163
+v 569.940 868.421 -168.309 0.00 164
+v 568.313 646.772 -200.810 -1.00 165
+v 564.026 779.327 -189.145 2.01 166
+v 681.063 692.241 -119.096 0.00 167
+v 537.819 895.008 -162.937 0.00 168
+v 590.830 867.716 -128.754 0.00 169
+v 613.402 850.353 -109.166 0.00 170
+v 557.678 720.944 -214.701 0.00 171
+v 524.797 714.053 -231.087 0.00 172
+v 617.200 829.300 -131.847 0.00 173
+v 594.466 848.671 -148.938 0.00 174
+v 538.687 883.234 -185.184 0.00 175
+v 661.205 796.744 -51.489 0.00 176
+v 566.576 883.397 -149.318 0.00 177
+v 695.062 700.705 -62.666 0.00 178
+v 531.850 778.188 -207.484 2.01 179
+v 535.757 784.428 -209.817 2.01 180
+v 539.338 793.109 -212.313 2.01 181
+v 541.888 803.201 -209.275 2.01 182
+v 549.430 817.580 -195.113 0.00 183
+v 556.538 764.460 -195.276 2.00 184
+v 560.770 762.778 -195.222 2.00 185
+v 564.406 760.716 -195.222 2.00 186
+v 587.141 748.074 -191.369 0.00 187
+v 656.593 702.767 -155.450 0.00 188
+v 552.686 765.383 -193.431 2.00 189
+v 656.484 750.081 -128.103 0.00 190
+v 558.817 833.098 -185.184 0.00 191
+v 530.765 845.415 -194.571 0.00 192
+v 597.830 794.520 -169.448 0.00 193
+v 576.560 688.280 -197.609 0.00 194
+v 580.412 816.224 -176.502 0.00 195
+v 618.014 685.730 -189.741 0.00 196
+v 592.838 708.085 -194.191 0.00 197
+v 631.470 717.417 -175.363 0.00 198
+v 536.354 865.871 -193.811 0.00 199
+v 612.317 808.519 -152.465 0.00 200
+v 589.908 830.440 -163.046 0.00 201
+v 611.503 769.235 -168.743 0.00 202
+v 674.552 725.719 -112.693 0.00 203
+v 633.641 772.056 -151.109 0.00 204
+v 683.559 740.912 -70.696 0.00 205
+v 605.643 733.478 -185.238 0.00 206
+v 705.643 615.735 -62.449 -1.00 207
+v 706.348 616.386 6.189 -1.00 208
+v 232.371 595.713 8.895 -1.00 209
+v 237.238 652.848 9.107 -1.00 210
+v 247.255 714.076 -2.462 -1.00 211
+v 265.947 778.546 -26.867 -1.00 212
+v 291.058 830.179 -66.086 -1.00 213
+v 318.709 867.422 -107.985 -1.00 214
+v 353.202 899.870 -141.066 -1.00 215
+v 382.544 922.442 -166.531 -1.00 216
+v 414.074 942.827 -193.264 -1.00 217
+v 451.460 957.922 -210.969 -1.00 218
+v 500.271 963.353 -217.388 -1.00 219
+v 549.083 957.922 -210.969 -1.00 220
+v 586.467 942.827 -193.264 -1.00 221
+v 617.998 922.442 -166.531 -1.00 222
+v 647.341 899.870 -141.066 -1.00 223
+v 681.834 867.422 -107.985 -1.00 224
+v 709.485 830.179 -66.086 -1.00 225
+v 734.596 778.546 -26.867 -1.00 226
+v 753.289 714.076 -2.462 -1.00 227
+v 763.304 652.848 9.107 -1.00 228
+v 768.171 595.713 8.895 -1.00 229
+v 443.796 765.169 -176.353 3.00 230
+v 540.991 741.596 -196.660 3.00 231
+v 522.947 768.277 -210.566 3.00 232
+v 477.800 741.572 -210.944 3.00 233
+v 522.885 741.454 -210.641 3.00 234
+v 434.232 764.718 -155.439 3.00 235
+v 565.570 764.568 -155.357 3.00 236
+v 557.126 765.104 -176.335 3.00 237
+v 458.400 741.521 -195.760 3.00 238
+v 565.995 741.692 -155.788 3.00 239
+v 478.100 768.462 -210.878 3.00 240
+v 458.383 766.575 -195.789 3.00 241
+v 541.328 766.458 -196.421 3.00 242
+v 443.662 740.885 -176.518 3.00 243
+v 500.255 741.521 -215.260 3.00 244
+v 500.232 769.100 -215.251 3.00 245
+v 434.873 741.719 -155.636 3.00 246
+v 557.206 740.845 -176.471 3.00 247
+v 448.236 792.164 -175.130 4.00 248
+v 536.374 770.330 -192.046 4.00 249
+v 519.147 793.500 -200.416 4.00 250
+v 481.246 771.634 -200.768 4.00 251
+v 518.879 771.609 -200.837 4.00 252
+v 437.317 790.634 -154.143 4.00 253
+v 564.105 790.996 -154.157 4.00 254
+v 553.047 792.095 -175.253 4.00 255
+v 464.154 770.374 -191.749 4.00 256
+v 564.112 766.823 -154.555 4.00 257
+v 481.376 793.642 -200.737 4.00 258
+v 464.157 792.896 -191.987 4.00 259
+v 536.171 792.828 -192.110 4.00 260
+v 448.281 768.492 -175.249 4.00 261
+v 500.248 772.331 -205.285 4.00 262
+v 500.202 793.315 -205.249 4.00 263
+v 437.177 766.886 -154.378 4.00 264
+v 553.153 768.487 -175.145 4.00 265
+f 115 1 127
+f 13 25 1
+f 3 127 1
+f 3 1 25
+f 115 127 117
+f 13 15 25
+f 128 117 127
+f 26 25 15
+f 78 70 176
+f 78 76 70
+f 169 176 70
+f 67 70 76
+f 122 156 152
+f 20 50 54
+f 157 152 156
+f 55 54 50
+f 117 128 118
+f 15 16 26
+f 129 118 128
+f 27 26 16
+f 113 202 192
+f 11 93 105
+f 196 192 202
+f 99 105 93
+f 129 186 118
+f 27 16 87
+f 187 118 186
+f 88 87 16
+f 120 133 185
+f 18 86 31
+f 190 185 133
+f 91 31 86
+f 145 118 188
+f 43 89 16
+f 187 188 118
+f 88 16 89
+f 205 203 201
+f 108 104 106
+f 194 201 203
+f 97 106 104
+f 136 137 10
+f 34 10 35
+f 9 10 137
+f 9 35 10
+f 131 167 130
+f 29 28 65
+f 125 130 167
+f 23 65 28
+f 192 196 184
+f 93 85 99
+f 153 184 196
+f 51 99 85
+f 164 191 161
+f 62 59 92
+f 205 161 191
+f 108 92 59
+f 172 195 150
+f 72 48 98
+f 159 150 195
+f 57 98 48
+f 143 144 131
+f 41 29 42
+f 167 131 144
+f 65 42 29
+f 122 197 189
+f 20 90 100
+f 199 189 197
+f 102 100 90
+f 193 136 95
+f 96 95 34
+f 10 95 136
+f 10 34 95
+f 153 144 184
+f 51 85 42
+f 183 184 144
+f 84 42 85
+f 183 144 182
+f 84 83 42
+f 143 182 144
+f 41 42 83
+f 9 137 8
+f 9 8 35
+f 138 8 137
+f 36 35 8
+f 197 114 198
+f 100 101 12
+f 195 198 114
+f 98 12 101
+f 165 176 178
+f 63 79 76
+f 169 178 176
+f 67 76 79
+f 172 117 145
+f 72 43 15
+f 118 145 117
+f 16 15 43
+f 162 161 171
+f 60 69 59
+f 174 171 161
+f 74 59 69
+f 202 113 175
+f 105 75 11
+f 165 175 113
+f 63 11 75
+f 153 121 144
+f 51 42 19
+f 167 144 121
+f 65 19 42
+f 148 126 147
+f 46 45 24
+f 132 147 126
+f 30 24 45
+f 158 154 155
+f 56 53 52
+f 197 198 199
+f 100 102 101
+f 207 199 198
+f 110 101 102
+f 172 173 117
+f 72 15 73
+f 115 117 173
+f 13 73 15
+f 94 200 95
+f 94 95 103
+f 193 95 200
+f 96 103 95
+f 152 151 114
+f 50 12 49
+f 166 114 151
+f 64 49 12
+f 194 203 121
+f 97 19 106
+f 123 121 203
+f 21 106 19
+f 201 194 202
+f 104 105 97
+f 196 202 194
+f 99 97 105
+f 196 194 153
+f 99 51 97
+f 121 153 194
+f 19 97 51
+f 130 126 131
+f 28 29 24
+f 148 131 126
+f 46 24 29
+f 163 208 158
+f 61 56 111
+f 154 158 208
+f 52 111 56
+f 127 116 128
+f 25 26 14
+f 119 128 116
+f 17 14 26
+f 166 159 114
+f 64 12 57
+f 195 114 159
+f 98 57 12
+f 128 119 129
+f 26 27 17
+f 120 129 119
+f 18 17 27
+f 199 207 205
+f 102 108 110
+f 203 205 207
+f 106 110 108
+f 129 120 186
+f 27 87 18
+f 185 186 120
+f 86 18 87
+f 174 201 175
+f 74 75 104
+f 202 175 201
+f 105 104 75
+f 175 165 170
+f 75 68 63
+f 178 170 165
+f 79 63 68
+f 122 189 158
+f 20 56 90
+f 168 158 189
+f 66 90 56
+f 142 143 148
+f 40 46 41
+f 131 148 143
+f 29 41 46
+f 182 143 181
+f 83 82 41
+f 142 181 143
+f 40 41 82
+f 152 157 151
+f 50 49 55
+f 146 209 163
+f 44 61 112
+f 208 163 209
+f 111 112 61
+f 8 138 7
+f 8 7 36
+f 139 7 138
+f 37 36 7
+f 7 139 6
+f 7 6 37
+f 140 6 139
+f 38 37 6
+f 180 181 141
+f 81 39 82
+f 142 141 181
+f 40 82 39
+f 147 141 148
+f 45 46 39
+f 142 148 141
+f 40 39 46
+f 177 164 162
+f 77 60 62
+f 161 162 164
+f 59 62 60
+f 124 206 177
+f 22 77 109
+f 164 177 206
+f 62 109 77
+f 119 134 120
+f 17 18 32
+f 133 120 134
+f 31 32 18
+f 121 123 167
+f 19 65 21
+f 125 167 123
+f 23 21 65
+f 176 200 78
+f 76 78 103
+f 94 78 200
+f 94 103 78
+f 116 135 119
+f 14 17 33
+f 134 119 135
+f 32 33 17
+f 185 190 126
+f 86 24 91
+f 132 126 190
+f 30 91 24
+f 158 155 122
+f 56 20 53
+f 156 122 155
+f 54 53 20
+f 171 174 170
+f 69 68 74
+f 175 170 174
+f 75 74 68
+f 198 145 207
+f 101 110 43
+f 188 207 145
+f 89 43 110
+f 173 149 71
+f 73 71 47
+f 2 71 149
+f 2 47 71
+f 1 115 71
+f 1 71 13
+f 173 71 115
+f 73 13 71
+f 3 4 127
+f 3 25 4
+f 116 127 4
+f 14 4 25
+f 4 5 116
+f 4 14 5
+f 135 116 5
+f 33 5 14
+f 122 152 197
+f 20 100 50
+f 114 197 152
+f 12 50 100
+f 195 172 198
+f 98 101 72
+f 145 198 172
+f 43 72 101
+f 172 150 173
+f 72 73 48
+f 149 173 150
+f 47 48 73
+f 205 201 161
+f 108 59 104
+f 174 161 201
+f 74 104 59
+f 113 200 165
+f 11 63 103
+f 176 165 200
+f 76 103 63
+f 139 181 140
+f 37 38 82
+f 180 140 181
+f 81 82 38
+f 138 182 139
+f 36 37 83
+f 181 139 182
+f 82 83 37
+f 137 183 138
+f 35 36 84
+f 182 138 183
+f 83 84 36
+f 136 184 137
+f 34 35 85
+f 183 137 184
+f 84 85 35
+f 192 184 193
+f 93 96 85
+f 136 193 184
+f 34 85 96
+f 163 179 146
+f 61 44 80
+f 160 146 179
+f 58 80 44
+f 186 185 130
+f 87 28 86
+f 126 130 185
+f 24 86 28
+f 186 130 187
+f 87 88 28
+f 125 187 130
+f 23 28 88
+f 188 187 123
+f 89 21 88
+f 125 123 187
+f 23 88 21
+f 207 188 203
+f 110 106 89
+f 123 203 188
+f 21 89 106
+f 205 191 199
+f 108 102 92
+f 189 199 191
+f 90 92 102
+f 158 168 163
+f 56 61 66
+f 179 163 168
+f 80 66 61
+f 200 113 193
+f 103 96 11
+f 192 193 113
+f 93 11 96
+f 164 206 191
+f 62 92 109
+f 204 191 206
+f 107 109 92
+f 168 204 179
+f 66 80 107
+f 206 179 204
+f 109 107 80
+f 189 191 168
+f 90 66 92
+f 204 168 191
+f 107 92 66
+f 160 179 124
+f 58 22 80
+f 206 124 179
+f 109 80 22
+f 112 210 44
+f 44 210 211
+f 44 211 58
+f 58 211 212
+f 58 212 22
+f 22 212 213
+f 22 213 77
+f 77 213 214
+f 77 214 60
+f 60 214 215
+f 60 215 69
+f 69 215 216
+f 69 216 68
+f 68 216 217
+f 68 217 79
+f 79 217 218
+f 79 218 67
+f 67 218 219
+f 67 219 70
+f 70 219 220
+f 70 220 169
+f 169 220 221
+f 169 221 178
+f 178 221 222
+f 178 222 170
+f 170 222 223
+f 170 223 171
+f 171 223 224
+f 171 224 162
+f 162 224 225
+f 162 225 177
+f 177 225 226
+f 177 226 124
+f 124 226 227
+f 124 227 160
+f 160 227 228
+f 160 228 146
+f 146 228 229
+f 146 229 209
+f 209 229 230
+f 240 248 237
+f 237 248 238
+f 248 232 238
+f 238 232 243
+f 232 235 243
+f 243 235 233
+f 235 245 233
+f 233 245 246
+f 245 234 246
+f 246 234 241
+f 234 239 241
+f 241 239 242
+f 239 244 242
+f 242 244 231
+f 244 247 231
+f 231 247 236
+f 258 266 255
+f 255 266 256
+f 266 250 256
+f 256 250 261
+f 250 253 261
+f 261 253 251
+f 253 263 251
+f 251 263 264
+f 263 252 264
+f 264 252 259
+f 252 257 259
+f 259 257 260
+f 257 262 260
+f 260 262 249
+f 262 265 249
+f 249 265 254
+
+f 240 247 254
+f 240 254 255
diff --git a/mini_live/obj/obj_mediapipe/generate_wrap_obj.py b/mini_live/obj/obj_mediapipe/generate_wrap_obj.py
new file mode 100644
index 0000000..50b4904
--- /dev/null
+++ b/mini_live/obj/obj_mediapipe/generate_wrap_obj.py
@@ -0,0 +1,118 @@
+index_wrap = [0, 2, 11, 12, 13, 14, 15, 16, 17, 18, 32, 36, 37, 38, 39, 40, 41, 42, 43, 50, 57, 58, 61,
+ 62, 72, 73, 74, 76, 77, 78, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 95,
+ 96, 97, 98, 100, 101, 106, 116, 117, 118, 119, 123, 129, 132, 135, 136, 137, 138, 140,
+ 142, 146, 147, 148, 149, 150, 152, 164, 165, 167, 169, 170, 171, 172, 175, 176, 177,
+ 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 191, 192, 194, 199, 200, 201, 202,
+ 203, 204, 205, 206, 207, 208, 210, 211, 212, 213, 214, 215, 216, 227, 234, 262, 266,
+ 267, 268, 269, 270, 271, 272, 273, 280, 287, 288, 291, 292, 302, 303, 304, 306, 307,
+ 308, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325,
+ 326, 327, 329, 330, 335, 345, 346, 347, 348, 352, 358, 361, 364, 365, 366, 367, 369,
+ 371, 375, 376, 377, 378, 379, 391, 393, 394, 395, 396, 397, 400, 401, 402, 403, 404,
+ 405, 406, 407, 408, 409, 410, 411, 415, 416, 418, 421, 422, 423, 424, 425, 426, 427,
+ 428, 430, 431, 432, 433, 434, 435, 436, 447, 454]
+
+# INDEX_MP_LIPS = [
+# 291, 409, 270, 269, 267, 0, 37, 39, 40, 185, 61,
+# 146, 91, 181, 84, 17, 314, 405, 321, 375,
+# 306, 408, 304, 303, 302, 11, 72, 73, 74, 184, 76,
+# 77, 90, 180, 85, 16, 315, 404, 320, 307,
+# 292, 407, 272, 271, 268, 12, 38, 41, 42, 183, 62,
+# 96, 89, 179, 86, 15, 316, 403, 319, 325,
+# 308, 415, 310, 311, 312, 13, 82, 81, 80, 191, 78,
+# 95, 88, 178, 87, 14, 317, 402, 318, 324,
+# ]
+INDEX_MP_LIPS_LOWER = [
+146, 91, 181, 84, 17, 314, 405, 321, 375,
+77, 90, 180, 85, 16, 315, 404, 320, 307,
+96, 89, 179, 86, 15, 316, 403, 319, 325,
+95, 88, 178, 87, 14, 317, 402, 318, 324,
+]
+INDEX_MP_LIPS_UPPER = [
+291, 409, 270, 269, 267, 0, 37, 39, 40, 185, 61,
+306, 408, 304, 303, 302, 11, 72, 73, 74, 184, 76,
+292, 407, 272, 271, 268, 12, 38, 41, 42, 183, 62,
+308, 415, 310, 311, 312, 13, 82, 81, 80, 191, 78,
+]
+index_lips_upper_wrap = []
+for i in INDEX_MP_LIPS_UPPER:
+ for j in range(len(index_wrap)):
+ if index_wrap[j] == i:
+ index_lips_upper_wrap.append(j)
+index_lips_lower_wrap = []
+for i in INDEX_MP_LIPS_LOWER:
+ for j in range(len(index_wrap)):
+ if index_wrap[j] == i:
+ index_lips_lower_wrap.append(j)
+# print(index_lips_wrap)
+# exit(-1)
+
+index_edge_wrap = [111,43,57,21,76,59,68,67,78,66,69,168,177,169,170,161,176,123,159,145,208]
+index_edge_wrap_upper = [111, 110, 51, 52, 53, 54, 48, 63, 56, 47, 46, 1, 148, 149, 158, 165, 150, 156, 155, 154, 153, 207, 208]
+import numpy as np
+def readObjFile(filepath):
+ v_ = []
+ face = []
+ with open(filepath) as f:
+ # with open(r"face3D.obj") as f:
+ content = f.readlines()
+ for i in content:
+ if i[:2] == "v ":
+ v0,v1,v2 = i[2:-1].split(" ")
+ v_.append(float(v0))
+ v_.append(float(v1))
+ v_.append(float(v2))
+ if i[:2] == "f ":
+ tmp = i[2:-1].split(" ")
+ for ii in tmp:
+ a = ii.split("/")[0]
+ a = int(a) - 1
+ face.append(a)
+ return v_, face
+
+verts_wrap,faces_wrap = readObjFile(r"wrap.obj")
+verts_wrap = np.array(verts_wrap).reshape(-1,3)
+vert_mid = verts_wrap[index_edge_wrap[:4] + index_edge_wrap[-4:]].mean(axis = 0)
+
+face_verts_num = len(verts_wrap)
+index_new_edge = []
+new_vert_list = []
+for i in range(len(index_edge_wrap)):
+ index = index_edge_wrap[i]
+ new_vert = verts_wrap[index] + (verts_wrap[index] - vert_mid) * 0.3
+ new_vert_list.append(new_vert)
+ index_new_edge.append(len(index_wrap) + i)
+for i in range(len(index_edge_wrap) - 1):
+ faces_wrap.extend([index_edge_wrap[i], face_verts_num + i, index_edge_wrap[(i+1)%len(index_edge_wrap)]])
+ faces_wrap.extend([index_edge_wrap[(i + 1) % len(index_edge_wrap)], face_verts_num + i, face_verts_num + (i+1)%len(index_edge_wrap)])
+
+verts_wrap = np.concatenate([verts_wrap, np.array(new_vert_list).reshape(-1,3)], axis = 0)
+
+v_teeth, face_teeth = readObjFile("modified_teeth_upper.obj")
+v_teeth2, face_teeth2 = readObjFile("modified_teeth_lower.obj")
+
+
+faces_wrap = faces_wrap + [i + len(verts_wrap) for i in face_teeth] + [i + len(verts_wrap) + len(v_teeth) // 3 for i in
+ face_teeth2]
+
+verts_wrap = np.concatenate([verts_wrap, np.array(v_teeth).reshape(-1,3)], axis = 0)
+verts_wrap = np.concatenate([verts_wrap, np.array(v_teeth2).reshape(-1,3)], axis = 0)
+
+# 边缘-1 正常0 上嘴唇2 下嘴唇2.01 上牙3 下牙4
+verts_wrap2 = np.zeros([len(verts_wrap), 5])
+verts_wrap2[:,:3] = verts_wrap
+verts_wrap2[index_lips_upper_wrap, 3] = 2.0
+verts_wrap2[index_lips_lower_wrap, 3] = 2.01
+verts_wrap2[-36:-18, 3] = 3
+verts_wrap2[-18:, 3] = 4
+verts_wrap2[index_edge_wrap_upper, 3] = -1
+verts_wrap2[index_new_edge, 3] = -1
+verts_wrap2[:, 4] = range(len(verts_wrap2))
+
+with open("face_wrap_entity.obj", "w") as f:
+ for i in verts_wrap2:
+ f.write("v {:.3f} {:.3f} {:.3f} {:.02f} {:.0f}\n".format(i[0], i[1], i[2], i[3], i[4]))
+ for i in range(len(faces_wrap)//3):
+ f.write("f {0} {1} {2}\n".format(faces_wrap[3*i]+1, faces_wrap[3*i+1]+1,faces_wrap[3*i+2]+1))
+
+# f 240 247 254
+# f 240 254 255
\ No newline at end of file
diff --git a/mini_live/obj/obj_mediapipe/modified_obj.py b/mini_live/obj/obj_mediapipe/modified_obj.py
new file mode 100644
index 0000000..8abeb24
--- /dev/null
+++ b/mini_live/obj/obj_mediapipe/modified_obj.py
@@ -0,0 +1,79 @@
+import numpy as np
+
+def ModifyObjFile(path):
+ with_vn = False
+ verts = []
+ vt = []
+ vn = []
+ face = []
+ map_face = {}
+ with open(path) as f:
+ content = f.readlines()
+ for i in content:
+ if i[:2] == "v ":
+ verts.append(i)
+ if i[:3] == "vt ":
+ vt.append(i)
+ if i[:3] == "vn ":
+ with_vn = True
+ vn.append(i)
+ if i[:2] == "f ":
+ tmp = i[2:-1].split(" ")
+ face.extend(tmp)
+ print(len(verts),len(vt),len(vn),len(face),len(set(face)))
+ set_face = set(face)
+ print(len(set_face))
+ for index,i in enumerate(set_face):
+ map_face[i] = index
+
+
+
+ with open("modified_" + path, "w") as f:
+ for i in set_face:
+ index = int(i.split("/")[0]) - 1
+ f.write(verts[index])
+ for i in set_face:
+ index = int(i.split("/")[1]) - 1
+ f.write(vt[index])
+ if with_vn:
+ for i in set_face:
+ index = int(i.split("/")[2]) - 1
+ f.write(vn[index])
+ for i in range(len(face) // 3):
+ f.write("f {0}/{0}/{0} {1}/{1}/{1} {2}/{2}/{2}\n".format(map_face[face[3 * i]] + 1,
+ map_face[face[3 * i + 1]] + 1,
+ map_face[face[3 * i + 2]] + 1))
+ else:
+ for i in range(len(face) // 3):
+ f.write("f {0}/{0} {1}/{1} {2}/{2}\n".format(map_face[face[3 * i]] + 1,
+ map_face[face[3 * i + 1]] + 1,
+ map_face[face[3 * i + 2]] + 1))
+
+
+ModifyObjFile("teeth_lower.obj")
+ModifyObjFile("teeth_upper.obj")
+
+# ModifyObjFile("teeth_new.obj")
+#
+# import cv2
+# import numpy as np
+# img0 = cv2.imread(r"texture/Std_Lower_Teeth_diffuse.jpg")
+# img1 = cv2.imread(r"texture/Std_Tongue_diffuse.jpg")
+# img2 = cv2.imread(r"texture/Std_Upper_Teeth_diffuse.jpg")
+# img = np.concatenate([img0, img1, img2], axis = 1)
+# cv2.imwrite("teeth.png", cv2.resize(img, (256*3,256)))
+#
+# img0 = cv2.imread(r"texture/Std_Lower_Teeth_normal.png")
+# img1 = cv2.imread(r"texture/Std_Tongue_normal.jpg")
+# img2 = cv2.imread(r"texture/Std_Upper_Teeth_normal.png")
+# img = np.concatenate([img0, img1, img2], axis = 1)
+# cv2.imwrite("teeth_normal.png", cv2.resize(img, (256*3,256)))
+# print(img[:100,:100])
+# img0 = cv2.imread(r"teeth.png").astype(float)
+# img1 = cv2.imread(r"teeth_ao.png", cv2.IMREAD_GRAYSCALE).astype(float)/255.
+#
+# img0[:,:,0] = img0[:,:,0]*img1
+# img0[:,:,1] = img0[:,:,1]*img1
+# img0[:,:,2] = img0[:,:,2]*img1
+#
+# cv2.imwrite("teeth_.png", img0.astype(np.uint8))
\ No newline at end of file
diff --git a/mini_live/obj/obj_mediapipe/modified_teeth_lower.obj b/mini_live/obj/obj_mediapipe/modified_teeth_lower.obj
new file mode 100644
index 0000000..827762f
--- /dev/null
+++ b/mini_live/obj/obj_mediapipe/modified_teeth_lower.obj
@@ -0,0 +1,52 @@
+v 448.235634 792.164490 -175.129913
+v 536.373879 770.329956 -192.046249
+v 519.147438 793.500122 -200.416458
+v 481.245979 771.633850 -200.767944
+v 518.879250 771.609314 -200.837250
+v 437.316597 790.634216 -154.143127
+v 564.105385 790.995911 -154.156693
+v 553.047402 792.094604 -175.252625
+v 464.153633 770.373901 -191.748932
+v 564.111916 766.822815 -154.555496
+v 481.376473 793.641968 -200.736969
+v 464.157173 792.896423 -191.986725
+v 536.171364 792.828003 -192.110428
+v 448.281075 768.492249 -175.249176
+v 500.247933 772.330933 -205.285172
+v 500.202187 793.314880 -205.248856
+v 437.176796 766.886230 -154.378220
+v 553.153481 768.487427 -175.145020
+vt 1.000000 1.000000
+vt 0.000000 0.500000
+vt 1.000000 1.000000
+vt 1.000000 0.500000
+vt 1.000000 0.500000
+vt 0.000000 1.000000
+vt 0.000000 1.000000
+vt 1.000000 1.000000
+vt 0.000000 0.500000
+vt 0.000000 0.500000
+vt 1.000000 1.000000
+vt 0.000000 1.000000
+vt 0.000000 1.000000
+vt 1.000000 0.500000
+vt 0.000000 0.500000
+vt 0.000000 1.000000
+vt 0.000000 0.500000
+vt 1.000000 0.500000
+f 10/10 18/18 7/7
+f 7/7 18/18 8/8
+f 18/18 2/2 8/8
+f 8/8 2/2 13/13
+f 2/2 5/5 13/13
+f 13/13 5/5 3/3
+f 5/5 15/15 3/3
+f 3/3 15/15 16/16
+f 15/15 4/4 16/16
+f 16/16 4/4 11/11
+f 4/4 9/9 11/11
+f 11/11 9/9 12/12
+f 9/9 14/14 12/12
+f 12/12 14/14 1/1
+f 14/14 17/17 1/1
+f 1/1 17/17 6/6
diff --git a/mini_live/obj/obj_mediapipe/modified_teeth_upper.obj b/mini_live/obj/obj_mediapipe/modified_teeth_upper.obj
new file mode 100644
index 0000000..37491a9
--- /dev/null
+++ b/mini_live/obj/obj_mediapipe/modified_teeth_upper.obj
@@ -0,0 +1,52 @@
+v 443.795746 765.168640 -176.353269
+v 540.990906 741.596375 -196.660321
+v 522.946716 768.276550 -210.566007
+v 477.799988 741.571777 -210.943952
+v 522.885315 741.454102 -210.641004
+v 434.232269 764.718140 -155.438794
+v 565.570435 764.567688 -155.356763
+v 557.125732 765.103882 -176.335141
+v 458.399994 741.520996 -195.760328
+v 565.995178 741.692261 -155.788221
+v 478.100006 768.462036 -210.878370
+v 458.383057 766.574890 -195.788663
+v 541.328491 766.458435 -196.421415
+v 443.661713 740.884888 -176.518079
+v 500.255157 741.520996 -215.260328
+v 500.232025 769.099976 -215.250638
+v 434.873383 741.719055 -155.635678
+v 557.205872 740.844971 -176.471311
+vt 1.000000 0.500000
+vt 0.000000 0.000000
+vt 1.000000 0.500000
+vt 1.000000 0.000000
+vt 1.000000 0.000000
+vt 0.000000 0.500000
+vt 0.000000 0.500000
+vt 1.000000 0.500000
+vt 0.000000 0.000000
+vt 0.000000 0.000000
+vt 1.000000 0.500000
+vt 0.000000 0.500000
+vt 0.000000 0.500000
+vt 1.000000 0.000000
+vt 0.000000 0.000000
+vt 0.000000 0.500000
+vt 0.000000 0.000000
+vt 1.000000 0.000000
+f 10/10 18/18 7/7
+f 7/7 18/18 8/8
+f 18/18 2/2 8/8
+f 8/8 2/2 13/13
+f 2/2 5/5 13/13
+f 13/13 5/5 3/3
+f 5/5 15/15 3/3
+f 3/3 15/15 16/16
+f 15/15 4/4 16/16
+f 16/16 4/4 11/11
+f 4/4 9/9 11/11
+f 11/11 9/9 12/12
+f 9/9 14/14 12/12
+f 12/12 14/14 1/1
+f 14/14 17/17 1/1
+f 1/1 17/17 6/6
diff --git a/mini_live/obj/obj_mediapipe/teeth_lower.obj b/mini_live/obj/obj_mediapipe/teeth_lower.obj
new file mode 100644
index 0000000..b75181a
--- /dev/null
+++ b/mini_live/obj/obj_mediapipe/teeth_lower.obj
@@ -0,0 +1,56 @@
+# This file uses centimeters as units for non-parametric coordinates.
+
+mtllib teeth_lower.mtl
+v 437.176796 766.886230 -154.378220
+v 448.235634 792.164490 -175.129913
+v 518.879250 771.609314 -200.837250
+v 536.171364 792.828003 -192.110428
+v 464.153633 770.373901 -191.748932
+v 500.247933 772.330933 -205.285172
+v 564.111916 766.822815 -154.555496
+v 564.105385 790.995911 -154.156693
+v 500.202187 793.314880 -205.248856
+v 481.376473 793.641968 -200.736969
+v 464.157173 792.896423 -191.986725
+v 448.281075 768.492249 -175.249176
+v 519.147438 793.500122 -200.416458
+v 553.153481 768.487427 -175.145020
+v 437.316597 790.634216 -154.143127
+v 553.047402 792.094604 -175.252625
+v 481.245979 771.633850 -200.767944
+v 536.373879 770.329956 -192.046249
+vt 0.000000 0.500000
+vt 1.000000 0.500000
+vt 0.000000 1.000000
+vt 1.000000 1.000000
+vt 0.000000 0.500000
+vt 0.000000 1.000000
+vt 1.000000 0.500000
+vt 1.000000 1.000000
+vt 0.000000 0.500000
+vt 0.000000 1.000000
+vt 1.000000 0.500000
+vt 1.000000 1.000000
+vt 0.000000 0.500000
+vt 0.000000 1.000000
+vt 1.000000 0.500000
+vt 1.000000 1.000000
+vt 0.000000 0.500000
+vt 0.000000 1.000000
+usemtl initialShadingGroup
+f 7/1 14/2 8/3
+f 8/3 14/2 16/4
+f 14/2 18/5 16/4
+f 16/4 18/5 4/6
+f 18/5 3/7 4/6
+f 4/6 3/7 13/8
+f 3/7 6/9 13/8
+f 13/8 6/9 9/10
+f 6/9 17/11 9/10
+f 9/10 17/11 10/12
+f 17/11 5/13 10/12
+f 10/12 5/13 11/14
+f 5/13 12/15 11/14
+f 11/14 12/15 2/16
+f 12/15 1/17 2/16
+f 2/16 1/17 15/18
diff --git a/mini_live/obj/obj_mediapipe/teeth_upper.obj b/mini_live/obj/obj_mediapipe/teeth_upper.obj
new file mode 100644
index 0000000..0ac4666
--- /dev/null
+++ b/mini_live/obj/obj_mediapipe/teeth_upper.obj
@@ -0,0 +1,56 @@
+# This file uses centimeters as units for non-parametric coordinates.
+
+mtllib teeth_upper.mtl
+v 434.873383 741.719055 -155.635678
+v 443.795746 765.168640 -176.353269
+v 522.885315 741.454102 -210.641004
+v 541.328491 766.458435 -196.421415
+v 458.399994 741.520996 -195.760328
+v 500.255157 741.520996 -215.260328
+v 565.995178 741.692261 -155.788221
+v 565.570435 764.567688 -155.356763
+v 500.232025 769.099976 -215.250638
+v 478.100006 768.462036 -210.878370
+v 458.383057 766.574890 -195.788663
+v 443.661713 740.884888 -176.518079
+v 522.946716 768.276550 -210.566007
+v 557.205872 740.844971 -176.471311
+v 434.232269 764.718140 -155.438794
+v 557.125732 765.103882 -176.335141
+v 477.799988 741.571777 -210.943952
+v 540.990906 741.596375 -196.660321
+vt 0.000000 0.000000
+vt 1.000000 0.000000
+vt 0.000000 0.500000
+vt 1.000000 0.500000
+vt 0.000000 0.000000
+vt 0.000000 0.500000
+vt 1.000000 0.000000
+vt 1.000000 0.500000
+vt 0.000000 0.000000
+vt 0.000000 0.500000
+vt 1.000000 0.000000
+vt 1.000000 0.500000
+vt 0.000000 0.000000
+vt 0.000000 0.500000
+vt 1.000000 0.000000
+vt 1.000000 0.500000
+vt 0.000000 0.000000
+vt 0.000000 0.500000
+usemtl initialShadingGroup
+f 7/1 14/2 8/3
+f 8/3 14/2 16/4
+f 14/2 18/5 16/4
+f 16/4 18/5 4/6
+f 18/5 3/7 4/6
+f 4/6 3/7 13/8
+f 3/7 6/9 13/8
+f 13/8 6/9 9/10
+f 6/9 17/11 9/10
+f 9/10 17/11 10/12
+f 17/11 5/13 10/12
+f 10/12 5/13 11/14
+f 5/13 12/15 11/14
+f 11/14 12/15 2/16
+f 12/15 1/17 2/16
+f 2/16 1/17 15/18
diff --git a/mini_live/obj/obj_mediapipe/wrap.obj b/mini_live/obj/obj_mediapipe/wrap.obj
new file mode 100644
index 0000000..83d5348
--- /dev/null
+++ b/mini_live/obj/obj_mediapipe/wrap.obj
@@ -0,0 +1,776 @@
+# This file uses centimeters as units for non-parametric coordinates.
+
+v 500.270996 739.283997 -238.682999
+v 500.270996 697.341003 -236.893005
+v 500.270996 746.771973 -236.621994
+v 500.270996 754.692993 -230.707001
+v 500.270996 759.956970 -222.134003
+v 500.270996 781.822998 -216.166000
+v 500.270996 791.210022 -218.389999
+v 500.270996 802.767029 -221.375000
+v 500.270996 814.323975 -217.197006
+v 500.270996 829.517029 -198.531998
+v 433.748993 850.515015 -178.347000
+v 410.255005 662.343994 -197.175003
+v 479.056000 735.864990 -236.024994
+v 481.442993 754.531006 -227.940002
+v 458.274994 744.166992 -225.119003
+v 445.144012 752.903015 -210.903000
+v 465.600006 756.809998 -220.397995
+v 453.662994 760.445007 -207.266998
+v 419.098999 787.737000 -180.300003
+v 356.213013 660.445007 -174.332001
+v 406.619995 767.119019 -177.315994
+v 320.022003 757.026978 -21.320000
+v 430.981995 768.747009 -179.595001
+v 435.703003 768.747009 -184.695007
+v 479.707001 745.903015 -234.070999
+v 461.800995 750.950012 -223.654007
+v 449.105011 756.809998 -210.686005
+v 433.424011 768.747009 -182.307999
+v 440.260010 776.614014 -192.074997
+v 438.036011 768.692017 -185.184006
+v 457.243988 762.614990 -204.173996
+v 468.855011 760.281982 -213.018997
+v 483.234009 759.468018 -219.854996
+v 475.203003 827.888977 -197.934998
+v 477.481995 811.828979 -216.112000
+v 478.675995 800.325989 -219.313004
+v 480.628998 788.931030 -216.057007
+v 482.963013 780.520996 -213.886993
+v 457.135010 775.528992 -199.617004
+v 453.119995 779.164001 -201.895996
+v 448.507996 784.590027 -204.173996
+v 444.817993 790.666992 -200.701996
+v 425.989990 732.393005 -204.826004
+v 297.937988 660.335999 6.352000
+v 448.507996 772.762024 -190.718002
+v 444.384003 774.443970 -192.237000
+v 477.862000 696.960999 -232.117996
+v 450.623993 692.892029 -213.289993
+v 427.671997 624.471008 -193.106003
+v 397.937988 637.546997 -187.897003
+v 432.881012 803.309998 -187.787994
+v 311.394012 611.773987 -118.662003
+v 343.244995 610.146973 -155.233002
+v 366.196014 617.362976 -172.106995
+v 400.704987 614.106995 -180.082993
+v 314.596008 652.848999 -124.305000
+v 438.958008 672.544983 -202.384003
+v 305.643005 707.434021 -2.547000
+v 359.684998 804.177979 -115.569000
+v 360.608002 825.393005 -83.719002
+v 298.209015 657.460999 -59.355999
+v 337.113007 777.807983 -94.136002
+v 430.601990 868.421021 -168.309006
+v 432.230011 646.771973 -200.809998
+v 436.516998 779.327026 -189.145004
+v 319.479004 692.241028 -119.096001
+v 462.723999 895.007996 -162.936996
+v 409.712006 867.716003 -128.753998
+v 387.140991 850.353027 -109.166000
+v 500.270996 899.185974 -167.875000
+v 500.270996 712.750977 -232.878006
+v 442.864990 720.943970 -214.701004
+v 475.746002 714.052979 -231.087006
+v 383.342010 829.299988 -131.847000
+v 406.076996 848.671021 -148.938004
+v 461.855988 883.234009 -185.184006
+v 339.338013 796.744019 -51.488998
+v 500.270996 887.085999 -189.362000
+v 433.966003 883.396973 -149.317993
+v 305.425995 700.705017 -62.666000
+v 468.691986 778.187988 -207.483994
+v 464.786011 784.427979 -209.817001
+v 461.259003 793.109009 -212.313004
+v 458.653992 803.200989 -209.274994
+v 451.112000 817.580017 -195.113007
+v 444.003998 764.460022 -195.276001
+v 439.717987 762.778015 -195.222000
+v 436.136993 760.716003 -195.222000
+v 413.402008 748.073975 -191.369003
+v 343.950012 702.767029 -155.449997
+v 447.856995 765.382996 -193.431000
+v 344.058990 750.080994 -128.102997
+v 441.725006 833.098022 -185.184006
+v 500.270996 869.125977 -198.423004
+v 500.270996 847.802002 -197.988998
+v 469.778015 845.414978 -194.570999
+v 402.713013 794.520020 -169.447998
+v 423.983002 688.280029 -197.608994
+v 420.130005 816.223999 -176.501999
+v 382.583008 685.729980 -189.740997
+v 407.704987 708.085022 -194.190994
+v 369.071991 717.416992 -175.363007
+v 464.188995 865.870972 -193.811005
+v 388.170990 808.518982 -152.464996
+v 410.635010 830.440002 -163.046005
+v 389.093994 769.234985 -168.742996
+v 325.989990 725.718994 -112.693001
+v 366.902008 772.056030 -151.108994
+v 316.983002 740.911987 -70.695999
+v 394.899994 733.478027 -185.238007
+v 294.954010 615.734985 -62.449001
+v 294.194000 616.385986 6.189000
+v 566.739014 850.515015 -178.347000
+v 590.288025 662.343994 -197.175003
+v 521.487000 735.864990 -236.024994
+v 519.098999 754.531006 -227.940002
+v 542.268005 744.166992 -225.119003
+v 555.398987 752.903015 -210.903000
+v 534.942993 756.809998 -220.397995
+v 546.934021 760.445007 -207.266998
+v 581.442993 787.737000 -180.300003
+v 644.330017 660.445007 -174.332001
+v 593.922974 767.119019 -177.315994
+v 680.520996 757.026978 -21.320000
+v 569.559998 768.747009 -179.595001
+v 564.840027 768.747009 -184.695007
+v 520.835999 745.903015 -234.070999
+v 538.794983 750.950012 -223.654007
+v 551.437988 756.809998 -210.686005
+v 567.119019 768.747009 -182.307999
+v 560.281982 776.614014 -192.074997
+v 562.507019 768.692017 -185.184006
+v 543.299011 762.614990 -204.173996
+v 531.742004 760.281982 -213.018997
+v 517.362976 759.468018 -219.854996
+v 525.338989 827.888977 -197.934998
+v 523.059998 811.828979 -216.112000
+v 521.867004 800.325989 -219.313004
+v 519.913025 788.931030 -216.057007
+v 517.580017 780.520996 -213.886993
+v 543.406982 775.528992 -199.617004
+v 547.422974 779.164001 -201.895996
+v 552.034973 784.590027 -204.173996
+v 555.723999 790.666992 -200.701996
+v 574.552002 732.393005 -204.826004
+v 702.604004 660.335999 6.352000
+v 552.034973 772.762024 -190.718002
+v 556.158020 774.443970 -192.237000
+v 522.679993 696.960999 -232.117996
+v 549.919006 692.892029 -213.289993
+v 572.869995 624.471008 -193.106003
+v 602.604004 637.546997 -187.897003
+v 567.661011 803.309998 -187.787994
+v 689.148010 611.773987 -118.662003
+v 657.297974 610.146973 -155.233002
+v 634.291992 617.362976 -172.106995
+v 599.836975 614.106995 -180.082993
+v 685.947021 652.848999 -124.305000
+v 561.583984 672.544983 -202.384003
+v 694.900024 707.434021 -2.547000
+v 640.856995 804.177979 -115.569000
+v 639.934998 825.393005 -83.719002
+v 702.333008 657.460999 -59.355999
+v 663.429016 777.807983 -94.136002
+v 569.940002 868.421021 -168.309006
+v 568.312988 646.771973 -200.809998
+v 564.026001 779.327026 -189.145004
+v 681.062988 692.241028 -119.096001
+v 537.818970 895.007996 -162.936996
+v 590.830017 867.716003 -128.753998
+v 613.401978 850.353027 -109.166000
+v 557.677979 720.943970 -214.701004
+v 524.796997 714.052979 -231.087006
+v 617.200012 829.299988 -131.847000
+v 594.466003 848.671021 -148.938004
+v 538.687012 883.234009 -185.184006
+v 661.205017 796.744019 -51.488998
+v 566.575989 883.396973 -149.317993
+v 695.062012 700.705017 -62.666000
+v 531.849976 778.187988 -207.483994
+v 535.757019 784.427979 -209.817001
+v 539.338013 793.109009 -212.313004
+v 541.888000 803.200989 -209.274994
+v 549.429993 817.580017 -195.113007
+v 556.538025 764.460022 -195.276001
+v 560.770020 762.778015 -195.222000
+v 564.406006 760.716003 -195.222000
+v 587.140991 748.073975 -191.369003
+v 656.593018 702.767029 -155.449997
+v 552.685974 765.382996 -193.431000
+v 656.484009 750.080994 -128.102997
+v 558.817017 833.098022 -185.184006
+v 530.765015 845.414978 -194.570999
+v 597.830017 794.520020 -169.447998
+v 576.559998 688.280029 -197.608994
+v 580.411987 816.223999 -176.501999
+v 618.013977 685.729980 -189.740997
+v 592.838013 708.085022 -194.190994
+v 631.469971 717.416992 -175.363007
+v 536.354004 865.870972 -193.811005
+v 612.317017 808.518982 -152.464996
+v 589.908020 830.440002 -163.046005
+v 611.502991 769.234985 -168.742996
+v 674.552002 725.718994 -112.693001
+v 633.640991 772.056030 -151.108994
+v 683.559021 740.911987 -70.695999
+v 605.643005 733.478027 -185.238007
+v 705.643005 615.734985 -62.449001
+v 706.348022 616.385986 6.189000
+vt 0.528000 0.350000
+vt 0.500000 0.347000
+vt 0.527000 0.334000
+vt 0.472000 0.350000
+vt 0.473000 0.334000
+vt 0.500000 0.334000
+vt 0.560000 0.343000
+vt 0.440000 0.343000
+vt 0.553000 0.331000
+vt 0.447000 0.331000
+vt 0.500000 0.091000
+vt 0.500000 0.046000
+vt 0.559000 0.097000
+vt 0.441000 0.098000
+vt 0.568000 0.055000
+vt 0.431000 0.056000
+vt 0.723000 0.468000
+vt 0.714000 0.532000
+vt 0.666000 0.504000
+vt 0.277000 0.468000
+vt 0.335000 0.504000
+vt 0.286000 0.532000
+vt 0.667000 0.539000
+vt 0.333000 0.539000
+vt 0.585000 0.333000
+vt 0.415000 0.333000
+vt 0.577000 0.326000
+vt 0.423000 0.326000
+vt 0.603000 0.157000
+vt 0.646000 0.187000
+vt 0.588000 0.196000
+vt 0.397000 0.157000
+vt 0.411000 0.196000
+vt 0.354000 0.187000
+vt 0.626000 0.220000
+vt 0.374000 0.220000
+vt 0.599000 0.319000
+vt 0.401000 0.319000
+vt 0.608000 0.322000
+vt 0.392000 0.322000
+vt 0.571000 0.317000
+vt 0.569000 0.308000
+vt 0.593000 0.314000
+vt 0.429000 0.317000
+vt 0.407000 0.314000
+vt 0.431000 0.308000
+vt 0.587000 0.308000
+vt 0.413000 0.308000
+vt 0.610000 0.360000
+vt 0.632000 0.337000
+vt 0.390000 0.360000
+vt 0.368000 0.336000
+vt 0.720000 0.285000
+vt 0.675000 0.296000
+vt 0.686000 0.225000
+vt 0.280000 0.285000
+vt 0.314000 0.225000
+vt 0.325000 0.296000
+vt 0.655000 0.254000
+vt 0.345000 0.255000
+vt 0.534000 0.221000
+vt 0.528000 0.264000
+vt 0.500000 0.219000
+vt 0.466000 0.221000
+vt 0.472000 0.264000
+vt 0.500000 0.263000
+vt 0.597000 0.293000
+vt 0.604000 0.290000
+vt 0.612000 0.306000
+vt 0.403000 0.293000
+vt 0.388000 0.306000
+vt 0.396000 0.290000
+vt 0.618000 0.305000
+vt 0.382000 0.305000
+vt 0.570000 0.233000
+vt 0.430000 0.233000
+vt 0.600000 0.251000
+vt 0.400000 0.251000
+vt 0.816000 0.260000
+vt 0.772000 0.316000
+vt 0.761000 0.220000
+vt 0.184000 0.260000
+vt 0.239000 0.220000
+vt 0.228000 0.316000
+vt 0.584000 0.376000
+vt 0.621000 0.426000
+vt 0.577000 0.414000
+vt 0.416000 0.376000
+vt 0.423000 0.414000
+vt 0.379000 0.426000
+vt 0.603000 0.451000
+vt 0.397000 0.451000
+vt 0.577000 0.288000
+vt 0.582000 0.280000
+vt 0.423000 0.288000
+vt 0.418000 0.280000
+vt 0.680000 0.429000
+vt 0.752000 0.399000
+vt 0.248000 0.399000
+vt 0.320000 0.429000
+vt 0.705000 0.378000
+vt 0.295000 0.378000
+vt 0.543000 0.181000
+vt 0.500000 0.178000
+vt 0.457000 0.181000
+vt 0.555000 0.269000
+vt 0.445000 0.269000
+vt 0.553000 0.284000
+vt 0.447000 0.284000
+vt 0.500000 0.281000
+vt 0.527000 0.282000
+vt 0.473000 0.282000
+vt 0.644000 0.466000
+vt 0.643000 0.396000
+vt 0.357000 0.396000
+vt 0.356000 0.466000
+vt 0.614000 0.117000
+vt 0.625000 0.076000
+vt 0.386000 0.117000
+vt 0.375000 0.076000
+vt 0.753000 0.543000
+vt 0.247000 0.543000
+vt 0.532000 0.398000
+vt 0.468000 0.398000
+vt 0.628000 0.527000
+vt 0.372000 0.527000
+vt 0.618000 0.492000
+vt 0.382000 0.491000
+vt 0.802000 0.168000
+vt 0.734000 0.130000
+vt 0.198000 0.168000
+vt 0.266000 0.130000
+vt 0.711000 0.180000
+vt 0.289000 0.180000
+vt 0.665000 0.147000
+vt 0.335000 0.147000
+vt 0.625000 0.272000
+vt 0.375000 0.272000
+vt 0.590000 0.298000
+vt 0.608000 0.306000
+vt 0.587000 0.305000
+vt 0.410000 0.298000
+vt 0.413000 0.305000
+vt 0.392000 0.306000
+vt 0.596000 0.306000
+vt 0.404000 0.306000
+vt 0.897000 0.531000
+vt 0.821000 0.542000
+vt 0.103000 0.531000
+vt 0.179000 0.542000
+vt 0.811000 0.476000
+vt 0.189000 0.476000
+vt 0.663000 0.355000
+vt 0.337000 0.355000
+vt 0.534000 0.379000
+vt 0.466000 0.379000
+vt 0.500000 0.133000
+vt 0.552000 0.137000
+vt 0.448000 0.138000
+vt 0.645000 0.303000
+vt 0.354000 0.303000
+vt 0.892000 0.459000
+vt 0.108000 0.459000
+vt 0.526000 0.320000
+vt 0.474000 0.320000
+vt 0.550000 0.319000
+vt 0.450000 0.319000
+vt 0.681000 0.102000
+vt 0.319000 0.102000
+vt 0.812000 0.411000
+vt 0.188000 0.411000
+vt 0.574000 0.296000
+vt 0.426000 0.296000
+vt 0.552000 0.295000
+vt 0.448000 0.295000
+vt 0.986000 0.440000
+vt 0.992000 0.519000
+vt 0.014000 0.440000
+vt 0.008000 0.519000
+vt 0.500000 0.294000
+vt 0.527000 0.295000
+vt 0.473000 0.295000
+vt 0.500000 0.305000
+vt 0.527000 0.305000
+vt 0.473000 0.305000
+vt 0.551000 0.305000
+vt 0.572000 0.305000
+vt 0.449000 0.305000
+vt 0.428000 0.305000
+vt 0.872000 0.208000
+vt 0.128000 0.208000
+vt 0.933000 0.270000
+vt 0.866000 0.317000
+vt 0.067000 0.270000
+vt 0.134000 0.317000
+vt 0.548000 0.308000
+vt 0.452000 0.308000
+vt 0.525000 0.308000
+vt 0.475000 0.308000
+vt 0.500000 0.382000
+vt 0.500000 0.398000
+vt 0.500000 0.321000
+vt 0.500000 0.308000
+vt 0.886000 0.385000
+vt 0.114000 0.385000
+vt 0.968000 0.356000
+vt 0.032000 0.356000
+vt 0.811000 0.354000
+vt 0.189000 0.354000
+f 115/1 1/2 127/3
+f 13/4 25/5 1/2
+f 3/6 127/3 1/2
+f 3/6 1/2 25/5
+f 115/1 127/3 117/7
+f 13/4 15/8 25/5
+f 128/9 117/7 127/3
+f 26/10 25/5 15/8
+f 78/11 70/12 176/13
+f 78/11 76/14 70/12
+f 169/15 176/13 70/12
+f 67/16 70/12 76/14
+f 122/17 156/18 152/19
+f 20/20 50/21 54/22
+f 157/23 152/19 156/18
+f 55/24 54/22 50/21
+f 117/7 128/9 118/25
+f 15/8 16/26 26/10
+f 129/27 118/25 128/9
+f 27/28 26/10 16/26
+f 113/29 202/30 192/31
+f 11/32 93/33 105/34
+f 196/35 192/31 202/30
+f 99/36 105/34 93/33
+f 129/27 186/37 118/25
+f 27/28 16/26 87/38
+f 187/39 118/25 186/37
+f 88/40 87/38 16/26
+f 120/41 133/42 185/43
+f 18/44 86/45 31/46
+f 190/47 185/43 133/42
+f 91/48 31/46 86/45
+f 145/49 118/25 188/50
+f 43/51 89/52 16/26
+f 187/39 188/50 118/25
+f 88/40 16/26 89/52
+f 205/53 203/54 201/55
+f 108/56 104/57 106/58
+f 194/59 201/55 203/54
+f 97/60 106/58 104/57
+f 136/61 137/62 10/63
+f 34/64 10/63 35/65
+f 9/66 10/63 137/62
+f 9/66 35/65 10/63
+f 131/67 167/68 130/69
+f 29/70 28/71 65/72
+f 125/73 130/69 167/68
+f 23/74 65/72 28/71
+f 192/31 196/35 184/75
+f 93/33 85/76 99/36
+f 153/77 184/75 196/35
+f 51/78 99/36 85/76
+f 164/79 191/80 161/81
+f 62/82 59/83 92/84
+f 205/53 161/81 191/80
+f 108/56 92/84 59/83
+f 172/85 195/86 150/87
+f 72/88 48/89 98/90
+f 159/91 150/87 195/86
+f 57/92 98/90 48/89
+f 143/93 144/94 131/67
+f 41/95 29/70 42/96
+f 167/68 131/67 144/94
+f 65/72 42/96 29/70
+f 122/17 197/97 189/98
+f 20/20 90/99 100/100
+f 199/101 189/98 197/97
+f 102/102 100/100 90/99
+f 193/103 136/61 95/104
+f 96/105 95/104 34/64
+f 10/63 95/104 136/61
+f 10/63 34/64 95/104
+f 153/77 144/94 184/75
+f 51/78 85/76 42/96
+f 183/106 184/75 144/94
+f 84/107 42/96 85/76
+f 183/106 144/94 182/108
+f 84/107 83/109 42/96
+f 143/93 182/108 144/94
+f 41/95 42/96 83/109
+f 9/66 137/62 8/110
+f 9/66 8/110 35/65
+f 138/111 8/110 137/62
+f 36/112 35/65 8/110
+f 197/97 114/113 198/114
+f 100/100 101/115 12/116
+f 195/86 198/114 114/113
+f 98/90 12/116 101/115
+f 165/117 176/13 178/118
+f 63/119 79/120 76/14
+f 169/15 178/118 176/13
+f 67/16 76/14 79/120
+f 172/85 117/7 145/49
+f 72/88 43/51 15/8
+f 118/25 145/49 117/7
+f 16/26 15/8 43/51
+f 162/129 161/81 171/130
+f 60/131 69/132 59/83
+f 174/133 171/130 161/81
+f 74/134 59/83 69/132
+f 202/30 113/29 175/135
+f 105/34 75/136 11/32
+f 165/117 175/135 113/29
+f 63/119 11/32 75/136
+f 153/77 121/137 144/94
+f 51/78 42/96 19/138
+f 167/68 144/94 121/137
+f 65/72 19/138 42/96
+f 148/139 126/140 147/141
+f 46/142 45/143 24/144
+f 132/145 147/141 126/140
+f 30/146 24/144 45/143
+f 158/151 154/148 155/121
+f 56/152 53/122 52/150
+f 197/97 198/114 199/101
+f 100/100 102/102 101/115
+f 207/153 199/101 198/114
+f 110/154 101/115 102/102
+f 172/85 173/155 117/7
+f 72/88 15/8 73/156
+f 115/1 117/7 173/155
+f 13/4 73/156 15/8
+f 94/157 200/158 95/104
+f 94/157 95/104 103/159
+f 193/103 95/104 200/158
+f 96/105 103/159 95/104
+f 152/19 151/125 114/113
+f 50/21 12/116 49/126
+f 166/127 114/113 151/125
+f 64/128 49/126 12/116
+f 194/59 203/54 121/137
+f 97/60 19/138 106/58
+f 123/160 121/137 203/54
+f 21/161 106/58 19/138
+f 201/55 194/59 202/30
+f 104/57 105/34 97/60
+f 196/35 202/30 194/59
+f 99/36 97/60 105/34
+f 196/35 194/59 153/77
+f 99/36 51/78 97/60
+f 121/137 153/77 194/59
+f 19/138 97/60 51/78
+f 130/69 126/140 131/67
+f 28/71 29/70 24/144
+f 148/139 131/67 126/140
+f 46/142 24/144 29/70
+f 163/162 208/147 158/151
+f 61/163 56/152 111/149
+f 154/148 158/151 208/147
+f 52/150 111/149 56/152
+f 127/3 116/164 128/9
+f 25/5 26/10 14/165
+f 119/166 128/9 116/164
+f 17/167 14/165 26/10
+f 166/127 159/91 114/113
+f 64/128 12/116 57/92
+f 195/86 114/113 159/91
+f 98/90 57/92 12/116
+f 128/9 119/166 129/27
+f 26/10 27/28 17/167
+f 120/41 129/27 119/166
+f 18/44 17/167 27/28
+f 199/101 207/153 205/53
+f 102/102 108/56 110/154
+f 203/54 205/53 207/153
+f 106/58 110/154 108/56
+f 129/27 120/41 186/37
+f 27/28 87/38 18/44
+f 185/43 186/37 120/41
+f 86/45 18/44 87/38
+f 174/133 201/55 175/135
+f 74/134 75/136 104/57
+f 202/30 175/135 201/55
+f 105/34 104/57 75/136
+f 175/135 165/117 170/168
+f 75/136 68/169 63/119
+f 178/118 170/168 165/117
+f 79/120 63/119 68/169
+f 122/17 189/98 158/151
+f 20/20 56/152 90/99
+f 168/170 158/151 189/98
+f 66/171 90/99 56/152
+f 142/172 143/93 148/139
+f 40/173 46/142 41/95
+f 131/67 148/139 143/93
+f 29/70 41/95 46/142
+f 182/108 143/93 181/174
+f 83/109 82/175 41/95
+f 142/172 181/174 143/93
+f 40/173 41/95 82/175
+f 152/19 157/23 151/125
+f 50/21 49/126 55/24
+f 146/176 209/177 163/162
+f 44/178 61/163 112/179
+f 208/147 163/162 209/177
+f 111/149 112/179 61/163
+f 8/110 138/111 7/180
+f 8/110 7/180 36/112
+f 139/181 7/180 138/111
+f 37/182 36/112 7/180
+f 7/180 139/181 6/183
+f 7/180 6/183 37/182
+f 140/184 6/183 139/181
+f 38/185 37/182 6/183
+f 180/186 181/174 141/187
+f 81/188 39/189 82/175
+f 142/172 141/187 181/174
+f 40/173 82/175 39/189
+f 147/141 141/187 148/139
+f 45/143 46/142 39/189
+f 142/172 148/139 141/187
+f 40/173 39/189 46/142
+f 177/190 164/79 162/129
+f 77/191 60/131 62/82
+f 161/81 162/129 164/79
+f 59/83 62/82 60/131
+f 124/192 206/193 177/190
+f 22/194 77/191 109/195
+f 164/79 177/190 206/193
+f 62/82 109/195 77/191
+f 119/166 134/196 120/41
+f 17/167 18/44 32/197
+f 133/42 120/41 134/196
+f 31/46 32/197 18/44
+f 121/137 123/160 167/68
+f 19/138 65/72 21/161
+f 125/73 167/68 123/160
+f 23/74 21/161 65/72
+f 176/13 200/158 78/11
+f 76/14 78/11 103/159
+f 94/157 78/11 200/158
+f 94/157 103/159 78/11
+f 116/164 135/198 119/166
+f 14/165 17/167 33/199
+f 134/196 119/166 135/198
+f 32/197 33/199 17/167
+f 185/43 190/47 126/140
+f 86/45 24/144 91/48
+f 132/145 126/140 190/47
+f 30/146 91/48 24/144
+f 158/151 155/121 122/17
+f 56/152 20/20 53/122
+f 156/18 122/17 155/121
+f 54/22 53/122 20/20
+f 171/130 174/133 170/168
+f 69/132 68/169 74/134
+f 175/135 170/168 174/133
+f 75/136 74/134 68/169
+f 198/114 145/49 207/153
+f 101/115 110/154 43/51
+f 188/50 207/153 145/49
+f 89/52 43/51 110/154
+f 173/155 149/123 71/200
+f 73/156 71/200 47/124
+f 2/201 71/200 149/123
+f 2/201 47/124 71/200
+f 1/2 115/1 71/200
+f 1/2 71/200 13/4
+f 173/155 71/200 115/1
+f 73/156 13/4 71/200
+f 3/6 4/202 127/3
+f 3/6 25/5 4/202
+f 116/164 127/3 4/202
+f 14/165 4/202 25/5
+f 4/202 5/203 116/164
+f 4/202 14/165 5/203
+f 135/198 116/164 5/203
+f 33/199 5/203 14/165
+f 122/17 152/19 197/97
+f 20/20 100/100 50/21
+f 114/113 197/97 152/19
+f 12/116 50/21 100/100
+f 195/86 172/85 198/114
+f 98/90 101/115 72/88
+f 145/49 198/114 172/85
+f 43/51 72/88 101/115
+f 172/85 150/87 173/155
+f 72/88 73/156 48/89
+f 149/123 173/155 150/87
+f 47/124 48/89 73/156
+f 205/53 201/55 161/81
+f 108/56 59/83 104/57
+f 174/133 161/81 201/55
+f 74/134 104/57 59/83
+f 113/29 200/158 165/117
+f 11/32 63/119 103/159
+f 176/13 165/117 200/158
+f 76/14 103/159 63/119
+f 139/181 181/174 140/184
+f 37/182 38/185 82/175
+f 180/186 140/184 181/174
+f 81/188 82/175 38/185
+f 138/111 182/108 139/181
+f 36/112 37/182 83/109
+f 181/174 139/181 182/108
+f 82/175 83/109 37/182
+f 137/62 183/106 138/111
+f 35/65 36/112 84/107
+f 182/108 138/111 183/106
+f 83/109 84/107 36/112
+f 136/61 184/75 137/62
+f 34/64 35/65 85/76
+f 183/106 137/62 184/75
+f 84/107 85/76 35/65
+f 192/31 184/75 193/103
+f 93/33 96/105 85/76
+f 136/61 193/103 184/75
+f 34/64 85/76 96/105
+f 163/162 179/204 146/176
+f 61/163 44/178 80/205
+f 160/206 146/176 179/204
+f 58/207 80/205 44/178
+f 186/37 185/43 130/69
+f 87/38 28/71 86/45
+f 126/140 130/69 185/43
+f 24/144 86/45 28/71
+f 186/37 130/69 187/39
+f 87/38 88/40 28/71
+f 125/73 187/39 130/69
+f 23/74 28/71 88/40
+f 188/50 187/39 123/160
+f 89/52 21/161 88/40
+f 125/73 123/160 187/39
+f 23/74 88/40 21/161
+f 207/153 188/50 203/54
+f 110/154 106/58 89/52
+f 123/160 203/54 188/50
+f 21/161 89/52 106/58
+f 205/53 191/80 199/101
+f 108/56 102/102 92/84
+f 189/98 199/101 191/80
+f 90/99 92/84 102/102
+f 158/151 168/170 163/162
+f 56/152 61/163 66/171
+f 179/204 163/162 168/170
+f 80/205 66/171 61/163
+f 200/158 113/29 193/103
+f 103/159 96/105 11/32
+f 192/31 193/103 113/29
+f 93/33 11/32 96/105
+f 164/79 206/193 191/80
+f 62/82 92/84 109/195
+f 204/208 191/80 206/193
+f 107/209 109/195 92/84
+f 168/170 204/208 179/204
+f 66/171 80/205 107/209
+f 206/193 179/204 204/208
+f 109/195 107/209 80/205
+f 189/98 191/80 168/170
+f 90/99 66/171 92/84
+f 204/208 168/170 191/80
+f 107/209 92/84 66/171
+f 160/206 179/204 124/192
+f 58/207 22/194 80/205
+f 206/193 124/192 179/204
+f 109/195 80/205 22/194
diff --git a/mini_live/obj/obj_mediapipe/wrap_index.py b/mini_live/obj/obj_mediapipe/wrap_index.py
new file mode 100644
index 0000000..aa88ba1
--- /dev/null
+++ b/mini_live/obj/obj_mediapipe/wrap_index.py
@@ -0,0 +1,41 @@
+import numpy as np
+import cv2
+def readObjFile(filepath):
+ v_ = []
+ face = []
+ with open(filepath) as f:
+ # with open(r"face3D.obj") as f:
+ content = f.readlines()
+ for i in content:
+ if i[:2] == "v ":
+ v0,v1,v2 = i[2:-1].split(" ")
+ v_.append(float(v0))
+ v_.append(float(v1))
+ v_.append(float(v2))
+ if i[:2] == "f ":
+ tmp = i[2:-1].split(" ")
+ for ii in tmp:
+ a = ii.split("/")[0]
+ a = int(a) - 1
+ face.append(a)
+ return v_, face
+
+verts_face,_ = readObjFile(r"face3D.obj")
+verts_wrap,_ = readObjFile(r"wrap.obj")
+
+verts_flame = np.array(verts_face).reshape(-1, 3)
+verts_mouth = np.array(verts_wrap).reshape(-1, 3)
+index_mouthInFlame = []
+for index in range(len(verts_mouth)):
+ vert = verts_mouth[index]
+ dist_list = []
+ for i in verts_flame:
+ dist_list.append(np.linalg.norm(i - vert))
+ align_index = np.argmin(dist_list)
+ index_mouthInFlame.append(align_index)
+print(index_mouthInFlame)
+# exit()
+
+# from obj.utils import INDEX_FLAME_LIPS
+# index_mouthInFlame = np.array(index_mouthInFlame, dtype = int)[INDEX_FLAME_LIPS]
+# np.savetxt("index_mouthInFlame.txt", index_mouthInFlame)
\ No newline at end of file
diff --git a/mini_live/obj/obj_utils.py b/mini_live/obj/obj_utils.py
new file mode 100644
index 0000000..b406271
--- /dev/null
+++ b/mini_live/obj/obj_utils.py
@@ -0,0 +1,171 @@
+import numpy as np
+import cv2
+import os
+current_dir = os.path.dirname(os.path.abspath(__file__))
+
+INDEX_FACE_EDGE = [
+ 234, 127, 162, 21,
+ 54, 103, 67, 109, 10, 338, 297, 332, 284, 251,
+ 389, 356,
+ 454, 323, 361, 288, 397, 365,
+ 379, 378, 400, 377, 152, 148, 176, 149, 150,
+ 136, 172, 58, 132,
+ 93,
+]
+def readObjFile(filepath):
+ with_vn = False
+ with_vt = False
+ v_ = []
+ vt = []
+ vn = []
+ face = []
+ with open(filepath) as f:
+ # with open(r"face3D.obj") as f:
+ content = f.readlines()
+ for i in content:
+ if i[:2] == "v ":
+ v0,v1,v2 = i[2:-1].split(" ")
+ v_.append(float(v0))
+ v_.append(float(v1))
+ v_.append(float(v2))
+ if i[:3] == "vt ":
+ with_vt = True
+ vt0,vt1 = i[3:-1].split(" ")
+ vt.append(float(vt0))
+ vt.append(float(vt1))
+ if i[:3] == "vn ":
+ with_vn = True
+ vn0,vn1,vn2 = i[3:-1].split(" ")
+ vn.append(float(vn0))
+ vn.append(float(vn1))
+ vn.append(float(vn2))
+ if i[:2] == "f ":
+ tmp = i[2:-1].split(" ")
+ for ii in tmp:
+ a = ii.split("/")[0]
+ a = int(a) - 1
+ face.append(a)
+ if not with_vn:
+ vn = [0 for i in v_]
+ if not with_vt:
+ vt = [0 for i in range(len(v_)//3*2)]
+ return v_, vt, vn, face
+
+def generateRenderInfo_mediapipe():
+ v_face, vt_face, vn_face, face_face = readObjFile(os.path.join(current_dir,"../obj/obj_mediapipe/face3D.obj"))
+ v_teeth, vt_teeth, vn_teeth, face_teeth = readObjFile(os.path.join(current_dir,"../obj/obj_mediapipe/modified_teeth_upper.obj"))
+ v_teeth2, vt_teeth2, vn_teeth2, face_teeth2 = readObjFile(os.path.join(current_dir,"../obj/obj_mediapipe/modified_teeth_lower.obj"))
+
+ v_, vt, vn, face = (
+ v_face + v_teeth + v_teeth2, vt_face + vt_teeth + vt_teeth2, vn_face + vn_teeth + vn_teeth2,
+ face_face + [i + len(v_face)//3 for i in face_teeth] + [i + len(v_face)//3 + len(v_teeth)//3 for i in face_teeth2])
+ v_ = np.array(v_).reshape(-1, 3)
+
+ # v_[:, 1] = -v_[:, 1]
+
+ # 0-2: verts 3-4: vt 5:category 6: index 7-10 bone_weight 11-12 another vt
+ vertices = np.zeros([len(v_), 13])
+ # vertices = np.zeros([len(pts_array_), 6])
+
+ vertices[:, :3] = v_
+ vertices[:, 3:5] = np.array(vt).reshape(-1, 2)
+ vertices[:, 11:13] = np.array(vt).reshape(-1, 2)
+ vertices[:, 12] = 1 - vertices[:, 12]
+ # vertices[:, 5] = 0
+ # 脸部为0,眼睛1,上牙2,下牙3
+ vertices[468:478, 5] = 1.
+ vertices[478:478 + 18, 5] = 2.
+ vertices[478 + 18:478 + 36, 5] = 3.
+ vertices[:, 6] = list(range(len(v_)))
+ return vertices, face
+
+def generateRenderInfo(floor = 5):
+ v_face, vt_face, vn_face, face_face = readObjFile(os.path.join(current_dir,"../obj/obj_mediapipe/face3D.obj"))
+ v_teeth, vt_teeth, vn_teeth, face_teeth = readObjFile(os.path.join(current_dir,"../obj/obj_mediapipe/modified_teeth_upper.obj"))
+ v_teeth2, vt_teeth2, vn_teeth2, face_teeth2 = readObjFile(os.path.join(current_dir,"../obj/obj_mediapipe/modified_teeth_lower.obj"))
+ print(len(v_face), len(vt_face), len(vn_face), len(face_face))
+ print(len(v_teeth)//3, len(vt_teeth), len(vn_teeth), len(face_teeth))
+ print(len(v_face)//3 + len(v_teeth)//3 + len(v_teeth2)//3)
+
+ v_, vt, vn, face = (
+ v_face + v_teeth + v_teeth2, vt_face + vt_teeth + vt_teeth2, vn_face + vn_teeth + vn_teeth2,
+ face_face + [i + len(v_face)//3 for i in face_teeth] + [i + len(v_face)//3 + len(v_teeth)//3 for i in face_teeth2])
+ v_ = np.array(v_).reshape(-1, 3)
+
+ # v_[:, 1] = -v_[:, 1]
+
+ vertices = np.zeros([len(v_), 13])
+ # vertices = np.zeros([len(pts_array_), 6])
+
+ vertices[:, :3] = v_
+ vertices[:, 3:5] = np.array(vt).reshape(-1, 2)
+
+ # 脸部为0,眼睛1,上牙2,下牙3, 补充的为9
+ vertices[468:478, 5] = 1.
+
+ vertices[len(v_face)//3:len(v_face)//3 + len(v_teeth)//3, 5] = 2.
+ vertices[len(v_face)//3 + len(v_teeth)//3:len(v_face)//3 + len(v_teeth)//3 + len(v_teeth2)//3, 5] = 3.
+ vertices[:, 6] = list(range(len(v_)))
+ return vertices, face
+
+
+def generateWrapModel():
+ v_ = []
+ face = []
+ filepath = os.path.join(current_dir,"../obj/obj_mediapipe/face_wrap_entity.obj")
+ with open(filepath) as f:
+ # with open(r"face3D.obj") as f:
+ content = f.readlines()
+ for i in content:
+ if i[:2] == "v ":
+ v0, v1, v2, v3, v4 = i[2:-1].split(" ")
+ v_.append(float(v0))
+ v_.append(float(v1))
+ v_.append(float(v2))
+ v_.append(float(v3))
+ v_.append(float(v4))
+ if i[:2] == "f ":
+ tmp = i[2:-1].split(" ")
+ for ii in tmp:
+ a = ii.split("/")[0]
+ a = int(a) - 1
+ face.append(a)
+ return np.array(v_).reshape(-1, 5), face
+
+def NewFaceVerts(render_verts, source_crop_pts, face_pts_mean):
+ from talkingface.run_utils import calc_face_mat
+ mat_list, _, face_pts_mean_personal_primer = calc_face_mat(source_crop_pts[np.newaxis, :478, :],
+ face_pts_mean)
+
+
+
+ # print(face_pts_mean_personal_primer.shape)
+ mat_list__ = mat_list[0].T
+ # mat_list__ = np.linalg.inv(mat_list[0])
+ render_verts[:478,:3] = face_pts_mean_personal_primer
+
+ # 牙齿部分校正
+ from talkingface.utils import INDEX_LIPS,main_keypoints_index,INDEX_LIPS_UPPER,INDEX_LIPS_LOWER
+ # # 上嘴唇中点
+ # mid_upper_mouth = np.mean(face_pts_mean_personal_primer[main_keypoints_index][INDEX_LIPS],axis = 0)
+ # mid_upper_teeth = np.mean(render_verts[478:478 + 36,:3], axis=0)
+ # tmp = mid_upper_teeth - mid_upper_mouth
+ # print(tmp)
+ # render_verts[478:478 + 36, :2] = render_verts[478:478 + 36, :2] - tmp[:2]
+
+ # 上嘴唇中点
+ mid_upper_mouth = np.mean(face_pts_mean_personal_primer[main_keypoints_index][INDEX_LIPS_UPPER],axis = 0)
+ mid_upper_teeth = np.mean(render_verts[478:478 + 18,:3], axis=0)
+ tmp = mid_upper_teeth - mid_upper_mouth
+ print(tmp)
+ render_verts[478:478 + 18, :2] = render_verts[478:478 + 18, :2] - tmp[:2]
+
+ # 下嘴唇中点
+ mid_lower_mouth = np.mean(face_pts_mean_personal_primer[main_keypoints_index][INDEX_LIPS_LOWER],axis = 0)
+ mid_lower_teeth = np.mean(render_verts[478:478 + 18,:3], axis=0)
+ tmp = mid_lower_teeth - mid_lower_mouth
+ print(tmp)
+ render_verts[478 + 18:478 + 36, :2] = render_verts[478 + 18:478 + 36, :2] - tmp[:2]
+
+
+ return render_verts, mat_list__
diff --git a/mini_live/obj/utils.py b/mini_live/obj/utils.py
new file mode 100644
index 0000000..7880865
--- /dev/null
+++ b/mini_live/obj/utils.py
@@ -0,0 +1,186 @@
+import uuid
+
+import numpy as np
+import cv2
+import os
+current_dir = os.path.dirname(os.path.abspath(__file__))
+
+def translation_matrix(point):
+ """生成平移矩阵"""
+ return np.array([
+ [1, 0, 0, point[0]],
+ [0, 1, 0, point[1]],
+ [0, 0, 1, point[2]],
+ [0, 0, 0, 1]
+ ])
+def rotate_around_point(point, theta, phi, psi):
+ """围绕点P旋转"""
+ # 将点P平移到原点
+ T1 = translation_matrix(-point)
+
+ # 定义欧拉角
+ theta = np.radians(theta) # 俯仰角
+ phi = np.radians(phi) # 偏航角
+ psi = np.radians(psi) # 翻滚角
+
+ # 创建旋转矩阵
+ tmp = [theta, phi, psi]
+ matX = np.array([[1.0, 0, 0, 0],
+ [0.0, np.cos(tmp[0]), -np.sin(tmp[0]), 0],
+ [0.0, np.sin(tmp[0]), np.cos(tmp[0]), 0],
+ [0, 0, 0, 1]
+ ])
+ matY = np.array([[np.cos(tmp[1]), 0, np.sin(tmp[1]), 0],
+ [0, 1, 0, 0],
+ [-np.sin(tmp[1]),0, np.cos(tmp[1]), 0],
+ [0, 0, 0, 1]
+ ])
+ matZ = np.array([[np.cos(tmp[2]), -np.sin(tmp[2]), 0, 0],
+ [np.sin(tmp[2]), np.cos(tmp[2]), 0, 0],
+ [0, 0, 1, 0],
+ [0, 0, 0, 1]
+ ])
+
+ R = matZ @ matY @ matX
+
+ # 将点P移回其原始位置
+ T2 = translation_matrix(point)
+
+ # 总的变换矩阵
+ total_transform = T2 @ R @ T1
+
+ return total_transform
+
+def rodrigues_rotation_formula(axis, theta):
+ """Calculate the rotation matrix using Rodrigues' rotation formula."""
+ axis = np.asarray(axis) / np.linalg.norm(axis) # Normalize the axis
+ cos_theta = np.cos(theta)
+ sin_theta = np.sin(theta)
+ K = np.array([[0, -axis[2], axis[1]],
+ [axis[2], 0, -axis[0]],
+ [-axis[1], axis[0], 0]])
+ R = np.eye(3) + sin_theta * K + (1 - cos_theta) * np.dot(K, K)
+ return R
+def RotateAngle2Matrix(center, axis, theta):
+ """Rotate around a center point."""
+ # Step 1: Translate the center to the origin
+ translation_to_origin = np.eye(4)
+ translation_to_origin[:3, 3] = -center
+
+ # Step 2: Apply the rotation
+ R = rodrigues_rotation_formula(axis, theta)
+ R_ = np.eye(4)
+ R_[:3,:3] = R
+ R = R_
+
+ # Step 3: Translate back to the original position
+ translation_back = np.eye(4)
+ translation_back[:3, 3] = center
+
+ # Combine the transformations
+ rotation_matrix = translation_back @ R @ translation_to_origin
+
+ return rotation_matrix
+
+INDEX_FLAME_LIPS = [
+1,26,23,21,8,155,83,96,98,101,
+73,112,123,124,143,146,71,52,51,40,
+2,25,24,22,7,156,82,97,99,100,
+74,113,122,125,138,148,66,53,50,41,
+30,31,32,38,39,157,111,110,106,105,
+104,120,121,126,137,147,65,54,49,48,
+4,28,33,20,19,153,94,95,107,103,
+76,118,119,127,136,149,64,55,47,46,
+
+3,27,35,17,18,154,93,92,109,102,
+75,114,115,128,133,151,61,56,43,42,
+6,29, 13, 12, 11, 158, 86, 87, 88, 79,
+80,117, 116, 135, 134, 150, 62, 63, 44, 45,
+5,36,14,9,10,159,85,84,89,78,
+77,141,130,131,139,145,67,59,58,69,
+0,37,34,15,16,152,91,90,108,81,72,
+142,129,132,140,144,68,60,57,70,
+]
+
+
+def crop_mouth(mouth_pts, mat_list__):
+ """
+ x_ratio: 裁剪出一个正方形,边长根据keypoints的宽度 * x_ratio决定
+ """
+ num_ = len(mouth_pts)
+ keypoints = np.ones([4, num_])
+ keypoints[:3, :] = mouth_pts.T
+ keypoints = mat_list__.dot(keypoints).T
+ keypoints = keypoints[:, :3]
+
+ x_min, y_min, x_max, y_max = np.min(keypoints[:, 0]), np.min(keypoints[:, 1]), np.max(keypoints[:, 0]), np.max(keypoints[:, 1])
+ border_width_half = max(x_max - x_min, y_max - y_min) * 0.66
+ y_min = y_min + border_width_half * 0.3
+ center_x = (x_min + x_max) /2.
+ center_y = (y_min + y_max) /2.
+ x_min, y_min, x_max, y_max = int(center_x - border_width_half), int(center_y - border_width_half*0.75), int(
+ center_x + border_width_half), int(center_y + border_width_half*0.75)
+ print([x_min, y_min, x_max, y_max])
+
+ # pts = np.array([
+ # [x_min, y_min],
+ # [x_max, y_min],
+ # [x_max, y_max],
+ # [x_min, y_max]
+ # ])
+ return [x_min, y_min, x_max, y_max]
+
+def drawMouth(keypoints, source_texture, out_size = (700, 1400)):
+ INDEX_LIPS_INNER = [78, 95, 88, 178, 87, 14, 317, 402, 318, 324, 308, 415, 310, 311, 312, 13, 82, 81, 80, 191]
+ INDEX_LIPS_OUTER = [61, 146, 91, 181, 84, 17, 314, 405, 321, 375, 291, 409, 270, 269, 267, 0, 37, 39, 40, 185, ]
+ INDEX_LIPS_LOWWER = INDEX_LIPS_INNER[:11] + INDEX_LIPS_OUTER[:11][::-1]
+ INDEX_LIPS_UPPER = INDEX_LIPS_INNER[10:] + [INDEX_LIPS_INNER[0], INDEX_LIPS_OUTER[0]] + INDEX_LIPS_OUTER[10:][::-1]
+ INDEX_LIPS = INDEX_LIPS_INNER + INDEX_LIPS_OUTER
+ # keypoints = keypoints[INDEX_LIPS]
+ keypoints[:, 0] = keypoints[:, 0] * out_size[0]
+ keypoints[:, 1] = keypoints[:, 1] * out_size[1]
+ # pts = keypoints[20:40]
+ # pts = pts.reshape((-1, 1, 2)).astype(np.int32)
+ # cv2.fillPoly(source_texture, [pts], color=(255, 0, 0,))
+ # pts = keypoints[:20]
+ # pts = pts.reshape((-1, 1, 2)).astype(np.int32)
+ # cv2.fillPoly(source_texture, [pts], color=(0, 0, 0,))
+
+ pts = keypoints[INDEX_LIPS_OUTER]
+ pts = pts.reshape((-1, 1, 2)).astype(np.int32)
+ cv2.fillPoly(source_texture, [pts], color=(0, 0, 0))
+ pts = keypoints[INDEX_LIPS_UPPER]
+ pts = pts.reshape((-1, 1, 2)).astype(np.int32)
+ cv2.fillPoly(source_texture, [pts], color=(255, 0, 0))
+ pts = keypoints[INDEX_LIPS_LOWWER]
+ pts = pts.reshape((-1, 1, 2)).astype(np.int32)
+ cv2.fillPoly(source_texture, [pts], color=(127, 0, 0))
+
+ prompt_texture = np.zeros_like(source_texture)
+ pts = keypoints[INDEX_LIPS_UPPER]
+ pts = pts.reshape((-1, 1, 2)).astype(np.int32)
+ cv2.fillPoly(prompt_texture, [pts], color=(255, 0, 0))
+ pts = keypoints[INDEX_LIPS_LOWWER]
+ pts = pts.reshape((-1, 1, 2)).astype(np.int32)
+ cv2.fillPoly(prompt_texture, [pts], color=(127, 0, 0))
+ return source_texture, prompt_texture
+
+
+
+#
+# def draw_face_feature_maps(keypoints, mode = ["mouth", "nose", "eye", "oval"], size=(256, 256), im_edges = None):
+# w, h = size
+# # edge map for face region from keypoints
+# if im_edges is None:
+# im_edges = np.zeros((h, w, 3), np.uint8) # edge map for all edges
+# if "mouth" in mode:
+# pts = keypoints[INDEX_LIPS_OUTER]
+# pts = pts.reshape((-1, 1, 2)).astype(np.int32)
+# cv2.fillPoly(im_edges, [pts], color=(0, 0, 0))
+# pts = keypoints[INDEX_LIPS_UPPER]
+# pts = pts.reshape((-1, 1, 2)).astype(np.int32)
+# cv2.fillPoly(im_edges, [pts], color=(255, 0, 0))
+# pts = keypoints[INDEX_LIPS_LOWWER]
+# pts = pts.reshape((-1, 1, 2)).astype(np.int32)
+# cv2.fillPoly(im_edges, [pts], color=(127, 0, 0))
+# return im_edges
\ No newline at end of file
diff --git a/mini_live/obj/weights478.txt b/mini_live/obj/weights478.txt
new file mode 100644
index 0000000..3ee5f29
--- /dev/null
+++ b/mini_live/obj/weights478.txt
@@ -0,0 +1,478 @@
+1.603576002379501262e-05 9.999839642399761530e-01 0.000000000000000000e+00
+4.689841752874187837e-04 9.995310158247125987e-01 0.000000000000000000e+00
+1.177883755449854675e-04 9.998822116244551195e-01 0.000000000000000000e+00
+7.715546541585459415e-05 9.999228445345841321e-01 0.000000000000000000e+00
+1.217504999620246247e-06 9.999987824950004045e-01 0.000000000000000000e+00
+2.265921921491020376e-03 9.977340780785091123e-01 0.000000000000000000e+00
+1.694059684557588930e-03 9.983059403154425082e-01 0.000000000000000000e+00
+2.762436828579639583e-05 9.999723756317141499e-01 0.000000000000000000e+00
+4.235073234370341499e-04 9.995764926765628999e-01 0.000000000000000000e+00
+2.309988571398404885e-05 9.999769001142859715e-01 0.000000000000000000e+00
+5.051561042957611378e-06 9.999949484389570875e-01 0.000000000000000000e+00
+1.194199529976002708e-03 9.988058004700240966e-01 0.000000000000000000e+00
+1.256353189769229611e-03 9.987436468102307563e-01 0.000000000000000000e+00
+1.256353189769229611e-03 9.987436468102307563e-01 0.000000000000000000e+00
+1.133980004800896023e-02 9.886601999519909478e-01 0.000000000000000000e+00
+1.047459842417867819e-02 9.895254015758212507e-01 0.000000000000000000e+00
+9.480981818594920452e-03 9.905190181814050865e-01 0.000000000000000000e+00
+7.234555343530837609e-03 9.927654446564692092e-01 0.000000000000000000e+00
+5.324257568898899985e-03 9.946757424311010176e-01 0.000000000000000000e+00
+1.756552939339277257e-05 9.999824344706065293e-01 0.000000000000000000e+00
+4.277754116257845404e-05 9.999572224588374469e-01 0.000000000000000000e+00
+6.646913690029437093e-06 9.999933530863099884e-01 0.000000000000000000e+00
+2.391566444889592558e-05 9.999760843355510742e-01 0.000000000000000000e+00
+5.373542072833612844e-05 9.999462645792717153e-01 0.000000000000000000e+00
+1.145576926055416741e-03 9.988544230739446750e-01 0.000000000000000000e+00
+2.573042174980795255e-04 9.997426957825019667e-01 0.000000000000000000e+00
+0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00
+3.885884236195963110e-05 9.999611411576380116e-01 0.000000000000000000e+00
+1.660108862961159979e-03 9.983398911370389150e-01 0.000000000000000000e+00
+1.888611019166209148e-04 9.998111388980832626e-01 0.000000000000000000e+00
+1.462308840453861996e-04 9.998537691159546936e-01 0.000000000000000000e+00
+3.698006669704836068e-04 9.996301993330294344e-01 0.000000000000000000e+00
+1.975055228186689549e-02 9.802494477181331600e-01 0.000000000000000000e+00
+8.642764316262221806e-05 9.999135723568373102e-01 0.000000000000000000e+00
+3.269319459648477831e-03 9.967306805403516323e-01 0.000000000000000000e+00
+5.124895782506902128e-03 9.948751042174932557e-01 0.000000000000000000e+00
+3.391829552247884860e-03 9.966081704477521841e-01 0.000000000000000000e+00
+4.167783314913719658e-03 9.958322166850861468e-01 0.000000000000000000e+00
+4.457263467170646289e-03 9.955427365328293199e-01 0.000000000000000000e+00
+3.208842402105002397e-05 9.999679115759790848e-01 0.000000000000000000e+00
+7.214588421813887716e-04 9.992785411578186672e-01 0.000000000000000000e+00
+9.470189416795990020e-06 9.999905298105832285e-01 0.000000000000000000e+00
+5.883835248205166943e-03 9.941161647517947619e-01 0.000000000000000000e+00
+8.099367352902626938e-03 9.919006326470973800e-01 0.000000000000000000e+00
+5.214584176530039040e-05 9.999478541582346169e-01 0.000000000000000000e+00
+8.107850551704613631e-04 9.991892149448294846e-01 0.000000000000000000e+00
+3.625433674261936386e-04 9.996374566325737510e-01 0.000000000000000000e+00
+1.275650947932010555e-05 9.999872434905208163e-01 0.000000000000000000e+00
+8.180555219301147282e-04 9.991819444780699611e-01 0.000000000000000000e+00
+1.197488873653261305e-03 9.988025111263467704e-01 0.000000000000000000e+00
+1.631059304073572552e-03 9.983689406959264101e-01 0.000000000000000000e+00
+5.524553337866198804e-06 9.999944754466620900e-01 0.000000000000000000e+00
+1.025883183246866184e-05 9.999897411681675230e-01 0.000000000000000000e+00
+4.100087921915456066e-05 9.999589991207809003e-01 0.000000000000000000e+00
+2.050004216153473665e-04 9.997949995783846910e-01 0.000000000000000000e+00
+0.000000000000000000e+00 9.999999999999998890e-01 0.000000000000000000e+00
+1.104445355902036585e-08 9.999999889555464261e-01 0.000000000000000000e+00
+8.667255171911487227e-03 9.913327448280886411e-01 0.000000000000000000e+00
+8.213865692490673887e-02 9.178613430750933722e-01 0.000000000000000000e+00
+6.190869068061546085e-04 9.993809130931937679e-01 0.000000000000000000e+00
+8.213895824023761147e-05 9.999178610417596147e-01 0.000000000000000000e+00
+7.020884942603724047e-03 9.929791150573962222e-01 0.000000000000000000e+00
+4.360058396562804285e-03 9.956399416034371619e-01 0.000000000000000000e+00
+1.240635935524646157e-05 9.999875936406447119e-01 0.000000000000000000e+00
+2.044206416361796837e-03 9.979557935836382843e-01 0.000000000000000000e+00
+4.951563861555918986e-06 9.999950484361384007e-01 0.000000000000000000e+00
+0.000000000000000000e+00 9.999999999999998890e-01 0.000000000000000000e+00
+1.643388289322144659e-04 9.998356611710677022e-01 0.000000000000000000e+00
+1.673300474820547113e-05 9.999832669952517517e-01 0.000000000000000000e+00
+3.688574727439292172e-05 9.999631142527256600e-01 0.000000000000000000e+00
+7.452109830549256053e-04 9.992547890169450886e-01 0.000000000000000000e+00
+2.986768302029281247e-03 9.970132316979706255e-01 0.000000000000000000e+00
+0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00
+3.795418338723596102e-03 9.962045816612764559e-01 0.000000000000000000e+00
+7.214588421813887716e-04 9.992785411578186672e-01 0.000000000000000000e+00
+6.190869068061546085e-04 9.993809130931937679e-01 0.000000000000000000e+00
+4.360058396562804285e-03 9.956399416034371619e-01 0.000000000000000000e+00
+9.230149562510383751e-03 9.907698504374895521e-01 0.000000000000000000e+00
+4.616766170768345223e-03 9.953832338292317727e-01 0.000000000000000000e+00
+2.749343513143501211e-06 9.999972506564868135e-01 0.000000000000000000e+00
+2.897096460223970633e-04 9.997102903539776264e-01 0.000000000000000000e+00
+9.470189416795990020e-06 9.999905298105832285e-01 0.000000000000000000e+00
+4.457263467170646289e-03 9.955427365328293199e-01 0.000000000000000000e+00
+4.153658061491410231e-03 9.958463419385086279e-01 0.000000000000000000e+00
+8.224028945215251102e-03 9.917759710547847662e-01 0.000000000000000000e+00
+8.480428277882052363e-03 9.915195717221181315e-01 0.000000000000000000e+00
+1.524314077754073023e-02 9.847568592224593687e-01 0.000000000000000000e+00
+2.158870928359914870e-02 9.784112907164008721e-01 0.000000000000000000e+00
+1.164739640323850418e-02 9.883526035967614698e-01 0.000000000000000000e+00
+1.126876997748215217e-02 9.887312300225179484e-01 0.000000000000000000e+00
+1.084183738231402939e-02 9.891581626176859654e-01 0.000000000000000000e+00
+9.363404119088791430e-03 9.906365958809112415e-01 0.000000000000000000e+00
+7.746464657647861296e-03 9.922535353423522775e-01 0.000000000000000000e+00
+6.754691516378944979e-03 9.932453084836210255e-01 0.000000000000000000e+00
+1.733671521569815356e-05 9.999826632847843566e-01 0.000000000000000000e+00
+9.461262685225131641e-03 9.905387373147748198e-01 0.000000000000000000e+00
+9.230149562510383751e-03 9.907698504374895521e-01 0.000000000000000000e+00
+0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00
+3.691064195895708052e-03 9.963089358041041788e-01 0.000000000000000000e+00
+0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00
+5.780271445836878503e-04 9.994219728554163407e-01 0.000000000000000000e+00
+1.723709497044585964e-03 9.982762905029552991e-01 0.000000000000000000e+00
+3.438359192766725098e-03 9.965616408072333066e-01 0.000000000000000000e+00
+1.664673697954194959e-04 9.998335326302045800e-01 0.000000000000000000e+00
+0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00
+1.025883183246866184e-05 9.999897411681675230e-01 0.000000000000000000e+00
+3.644967448761139185e-03 9.963550325512390282e-01 0.000000000000000000e+00
+2.359154111301043263e-05 9.999764084588870228e-01 0.000000000000000000e+00
+4.308154316976871474e-05 9.999569184568303237e-01 0.000000000000000000e+00
+2.085492431331649802e-04 9.997914507568665954e-01 0.000000000000000000e+00
+1.246131064283435765e-04 9.998753868935716937e-01 0.000000000000000000e+00
+2.207482251241388999e-03 9.977925177487586561e-01 0.000000000000000000e+00
+3.439325999641129768e-04 9.996560674000359858e-01 0.000000000000000000e+00
+4.629045408136543693e-05 9.999537095459186675e-01 0.000000000000000000e+00
+1.778777561067166707e-05 9.999822122243893219e-01 0.000000000000000000e+00
+2.651494128289132817e-06 9.999973485058715195e-01 0.000000000000000000e+00
+4.436351701893422560e-03 9.955636482981067292e-01 0.000000000000000000e+00
+1.141850580409567873e-03 9.988581494195905019e-01 0.000000000000000000e+00
+5.990734482448808714e-04 9.994009265517550533e-01 0.000000000000000000e+00
+4.439757592686359843e-06 9.999955602424070999e-01 0.000000000000000000e+00
+2.058284380238007923e-04 9.997941715619761416e-01 0.000000000000000000e+00
+7.144360421989765883e-07 9.999992855639577849e-01 0.000000000000000000e+00
+3.037058487961669092e-06 9.999969629415120798e-01 0.000000000000000000e+00
+5.436445516681891535e-03 9.945635544833182351e-01 0.000000000000000000e+00
+2.788262222356798674e-04 9.997211737777642604e-01 0.000000000000000000e+00
+1.290946066830522734e-05 9.999870905393317688e-01 0.000000000000000000e+00
+2.786968331145947705e-04 9.997213031668853445e-01 0.000000000000000000e+00
+7.011354444232600490e-05 9.999298864555576927e-01 0.000000000000000000e+00
+4.697393766796965419e-06 9.999953026062332606e-01 0.000000000000000000e+00
+4.983448570069866010e-03 9.950165514299301739e-01 0.000000000000000000e+00
+9.114710587816609233e-04 9.990885289412183567e-01 0.000000000000000000e+00
+5.036911175051876269e-05 9.999496308882495077e-01 0.000000000000000000e+00
+6.886098481597875687e-02 9.311390151840212015e-01 0.000000000000000000e+00
+8.971667673636566862e-08 9.999999102833232456e-01 0.000000000000000000e+00
+4.486744930663781258e-04 9.995513255069335967e-01 0.000000000000000000e+00
+8.712169117688529918e-02 9.128783088231147147e-01 0.000000000000000000e+00
+1.395101410171664946e-01 8.604898589828335886e-01 0.000000000000000000e+00
+4.496470968468382554e-03 9.955035290315314978e-01 0.000000000000000000e+00
+6.444578577747166193e-02 9.355542142225283797e-01 0.000000000000000000e+00
+1.895766051517108839e-03 9.981042339484829107e-01 0.000000000000000000e+00
+4.911361772623124705e-02 9.508863822737688709e-01 0.000000000000000000e+00
+0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00
+2.479196847328871264e-04 9.997520803152670776e-01 0.000000000000000000e+00
+3.128347014848182218e-03 9.968716529851516794e-01 0.000000000000000000e+00
+1.956520420926877776e-03 9.980434795790732450e-01 0.000000000000000000e+00
+7.455919867245278947e-06 9.999925440801328280e-01 0.000000000000000000e+00
+9.461262685225131641e-03 9.905387373147748198e-01 0.000000000000000000e+00
+1.012998971242701739e-02 9.898700102875730433e-01 0.000000000000000000e+00
+3.811932004776148047e-02 9.618806799522385820e-01 0.000000000000000000e+00
+1.283369223865011011e-01 8.716630776134990377e-01 0.000000000000000000e+00
+1.367745574529904695e-01 8.632254425470093917e-01 0.000000000000000000e+00
+4.178944940598669998e-04 9.995821055059401772e-01 0.000000000000000000e+00
+3.212848295712201346e-02 9.678715170428779935e-01 0.000000000000000000e+00
+4.551931316792500576e-08 9.999999544806869034e-01 0.000000000000000000e+00
+0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00
+8.971667673636566862e-08 9.999999102833232456e-01 0.000000000000000000e+00
+5.605446889904702051e-03 9.943945531100951696e-01 0.000000000000000000e+00
+1.218137286435184858e-07 9.999998781862714514e-01 0.000000000000000000e+00
+8.819517640519075304e-04 9.991180482359481863e-01 0.000000000000000000e+00
+3.072331846036408767e-05 9.999692766815395650e-01 0.000000000000000000e+00
+5.831629526739262566e-07 9.999994168370472947e-01 0.000000000000000000e+00
+8.815191012222841228e-04 9.991184808987777499e-01 0.000000000000000000e+00
+1.720932269414817071e-05 9.999827906773059993e-01 0.000000000000000000e+00
+1.145576926055416741e-03 9.988544230739446750e-01 0.000000000000000000e+00
+2.197117022052190590e-06 9.999978028829779042e-01 0.000000000000000000e+00
+5.567867475631336181e-03 9.944321325243686838e-01 0.000000000000000000e+00
+6.761828090372602523e-04 9.993238171909627487e-01 0.000000000000000000e+00
+1.147682909364828360e-03 9.988523170906351556e-01 0.000000000000000000e+00
+5.892477973871260459e-04 9.994107522026127732e-01 0.000000000000000000e+00
+9.333579474553128918e-02 9.066642052544686692e-01 0.000000000000000000e+00
+5.466435806965890681e-02 9.453356419303410307e-01 0.000000000000000000e+00
+3.217215741244473792e-02 9.678278425875551649e-01 0.000000000000000000e+00
+1.086395158583513681e-01 8.913604841416487012e-01 0.000000000000000000e+00
+2.092797014046764932e-05 9.999790720298595836e-01 0.000000000000000000e+00
+2.913396192887797255e-05 9.999708660380710601e-01 0.000000000000000000e+00
+2.595404611103438106e-02 9.740459538889655322e-01 0.000000000000000000e+00
+7.497028646797462836e-02 9.250297135320253439e-01 0.000000000000000000e+00
+1.678666286860705861e-02 9.832133371313929171e-01 0.000000000000000000e+00
+1.164739640323850418e-02 9.883526035967614698e-01 0.000000000000000000e+00
+1.086794713127304385e-02 9.891320528687269631e-01 0.000000000000000000e+00
+8.046972684936702300e-03 9.919530273150632960e-01 0.000000000000000000e+00
+8.148172653409497049e-03 9.918518273465906088e-01 0.000000000000000000e+00
+4.346237336513176022e-03 9.956537626634868188e-01 0.000000000000000000e+00
+1.699666565350518637e-03 9.983003334346495228e-01 0.000000000000000000e+00
+1.699666565350518637e-03 9.983003334346495228e-01 0.000000000000000000e+00
+1.699666565350518637e-03 9.983003334346495228e-01 0.000000000000000000e+00
+8.734572301004387557e-03 9.912654276989956159e-01 0.000000000000000000e+00
+7.991419513981664127e-03 9.920085804860182543e-01 0.000000000000000000e+00
+3.267959102535947782e-06 9.999967320408974514e-01 0.000000000000000000e+00
+1.460047081323520370e-08 9.999999853995292787e-01 0.000000000000000000e+00
+1.460047081323520370e-08 9.999999853995292787e-01 0.000000000000000000e+00
+1.766429652745656758e-04 9.998233570347254684e-01 0.000000000000000000e+00
+2.077885066122589150e-02 9.792211493387741328e-01 0.000000000000000000e+00
+4.533031166921319298e-04 9.995466968833077726e-01 0.000000000000000000e+00
+8.571580851002392337e-03 9.914284191489975973e-01 0.000000000000000000e+00
+2.276813868435458618e-04 9.997723186131564077e-01 0.000000000000000000e+00
+6.126804025456569595e-05 9.999387319597453638e-01 0.000000000000000000e+00
+4.949612814266893424e-06 9.999950503871858354e-01 0.000000000000000000e+00
+3.936855111240485311e-04 9.996063144888759355e-01 0.000000000000000000e+00
+1.292568208006479764e-02 9.870743179199352735e-01 0.000000000000000000e+00
+7.013920714408439401e-03 9.929860792855916829e-01 0.000000000000000000e+00
+6.011424435264207077e-03 9.939885755647358545e-01 0.000000000000000000e+00
+9.912295006919657342e-03 9.900877049930802976e-01 0.000000000000000000e+00
+6.134791526146873147e-03 9.938652084738531789e-01 0.000000000000000000e+00
+8.608685309301998545e-03 9.913913146906979668e-01 0.000000000000000000e+00
+3.634018884513381519e-03 9.963659811154866874e-01 0.000000000000000000e+00
+8.601404582320918910e-03 9.913985954176791626e-01 0.000000000000000000e+00
+9.617046947091681744e-03 9.903829530529082437e-01 0.000000000000000000e+00
+5.297730942651922292e-03 9.947022690573480430e-01 0.000000000000000000e+00
+1.630000224331441816e-03 9.983699997756684263e-01 0.000000000000000000e+00
+8.388368151874272052e-03 9.916116318481256187e-01 0.000000000000000000e+00
+2.129716071659483803e-02 9.787028392834050683e-01 0.000000000000000000e+00
+9.083025043241420640e-03 9.909169749567585672e-01 0.000000000000000000e+00
+1.684282015669455804e-02 9.831571798433054177e-01 0.000000000000000000e+00
+1.354143389811766733e-02 9.864585661018823171e-01 0.000000000000000000e+00
+4.275311378767571863e-02 9.572468862123243438e-01 0.000000000000000000e+00
+8.973138808244065720e-03 9.910268611917558701e-01 0.000000000000000000e+00
+4.040602088659778890e-05 9.999595939791133814e-01 0.000000000000000000e+00
+8.723759537941360747e-07 9.999991276240461913e-01 0.000000000000000000e+00
+8.040735102507494056e-04 9.991959264897491977e-01 0.000000000000000000e+00
+4.052445433117127021e-05 9.999594755456687745e-01 0.000000000000000000e+00
+4.582191679226417341e-07 9.999995417808319464e-01 0.000000000000000000e+00
+4.951563861555918986e-06 9.999950484361384007e-01 0.000000000000000000e+00
+7.336854442731346586e-06 9.999926631455572368e-01 0.000000000000000000e+00
+1.888611019166209148e-04 9.998111388980832626e-01 0.000000000000000000e+00
+5.574537786997843996e-05 9.999442546221299910e-01 0.000000000000000000e+00
+2.031125763227993554e-04 9.997968874236772274e-01 0.000000000000000000e+00
+6.072541514011508580e-03 9.939274584859885131e-01 0.000000000000000000e+00
+9.992040316589574211e-04 9.990007959683410155e-01 0.000000000000000000e+00
+0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00
+5.844602660377442275e-05 9.999415539733961245e-01 0.000000000000000000e+00
+2.391566444889592558e-05 9.999760843355510742e-01 0.000000000000000000e+00
+6.614422930996923160e-11 9.999999999338557988e-01 0.000000000000000000e+00
+3.439325999641129768e-04 9.996560674000359858e-01 0.000000000000000000e+00
+1.685300684353980693e-04 9.998314699315646870e-01 0.000000000000000000e+00
+6.190869068061546085e-04 9.993809130931937679e-01 0.000000000000000000e+00
+1.595765835777971211e-04 9.998404234164220972e-01 0.000000000000000000e+00
+7.930403175955836042e-05 9.999206959682404028e-01 0.000000000000000000e+00
+0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00
+2.326711622929058349e-04 9.997673288377070255e-01 0.000000000000000000e+00
+1.493336699053528444e-03 9.985066633009465065e-01 0.000000000000000000e+00
+1.086155649520761684e-05 9.999891384435047881e-01 0.000000000000000000e+00
+0.000000000000000000e+00 1.000000000000000222e+00 0.000000000000000000e+00
+9.137878211071493657e-07 9.999990862121789226e-01 0.000000000000000000e+00
+3.102800762221597559e-06 9.999968971992378997e-01 0.000000000000000000e+00
+0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00
+6.232139982238003428e-04 9.993767860017762628e-01 0.000000000000000000e+00
+2.010944360771889491e-04 9.997989055639227018e-01 0.000000000000000000e+00
+5.232892543673250653e-05 9.999476710745632824e-01 0.000000000000000000e+00
+2.068643308969085777e-04 9.997931356691029947e-01 0.000000000000000000e+00
+3.188261050307610166e-06 9.999968117389497202e-01 0.000000000000000000e+00
+6.863453471838484995e-04 9.993136546528161857e-01 0.000000000000000000e+00
+0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00
+5.903660534248891576e-08 9.999999409633946179e-01 0.000000000000000000e+00
+1.425257967623769067e-06 9.999985747420323534e-01 0.000000000000000000e+00
+4.357670585744466884e-05 9.999564232941424713e-01 0.000000000000000000e+00
+1.500355536979819371e-04 9.998499644463020308e-01 0.000000000000000000e+00
+3.180529999449918633e-04 9.996819470000549712e-01 0.000000000000000000e+00
+1.328356812251134781e-06 9.999986716431877865e-01 0.000000000000000000e+00
+2.339770575509696691e-06 9.999976602294243788e-01 0.000000000000000000e+00
+1.110790986214248066e-05 9.999888920901378597e-01 0.000000000000000000e+00
+4.297041775605052981e-04 9.995702958224395029e-01 0.000000000000000000e+00
+2.334984007853375954e-02 9.766501599214661988e-01 0.000000000000000000e+00
+5.543317226988346167e-04 9.994456682773010803e-01 0.000000000000000000e+00
+5.598483040708194646e-04 9.994401516959291465e-01 0.000000000000000000e+00
+3.868132710558134396e-04 9.996131867289441697e-01 0.000000000000000000e+00
+2.150216430581546479e-03 9.978497835694184470e-01 0.000000000000000000e+00
+2.280450046331264116e-05 9.999771954995367862e-01 0.000000000000000000e+00
+4.886091393059526210e-05 9.999511390860693627e-01 0.000000000000000000e+00
+5.206904487924461080e-04 9.994793095512074510e-01 0.000000000000000000e+00
+1.081640912416817913e-03 9.989183590875831964e-01 0.000000000000000000e+00
+2.628939525553483929e-04 9.997371060474447013e-01 0.000000000000000000e+00
+2.281283087473271517e-04 9.997718716912527004e-01 0.000000000000000000e+00
+1.092244069630980696e-02 9.890775593036902347e-01 0.000000000000000000e+00
+0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00
+1.528306163059360753e-08 9.999999847169382949e-01 0.000000000000000000e+00
+3.101203937585426653e-06 9.999968987960623501e-01 0.000000000000000000e+00
+1.442103899223256863e-05 9.999855789610077039e-01 0.000000000000000000e+00
+1.325823927870199573e-03 9.986741760721298267e-01 0.000000000000000000e+00
+1.690608624739996192e-03 9.983093913752599802e-01 0.000000000000000000e+00
+7.115517590470137651e-04 9.992884482409529756e-01 0.000000000000000000e+00
+4.002203679137918023e-06 9.999959977963207569e-01 0.000000000000000000e+00
+0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00
+3.283175452636412936e-05 9.999671682454736032e-01 0.000000000000000000e+00
+2.402278113413825085e-03 9.975977218865861307e-01 0.000000000000000000e+00
+2.481382396999426898e-04 9.997518617603000646e-01 0.000000000000000000e+00
+8.470506340180375417e-07 9.999991529493659215e-01 0.000000000000000000e+00
+9.259991003589672365e-03 9.907400089964104595e-01 0.000000000000000000e+00
+8.292238116324482378e-02 9.170776188367550930e-01 0.000000000000000000e+00
+9.196417596839462968e-04 9.990803582403160465e-01 0.000000000000000000e+00
+3.092941210002803218e-04 9.996907058789996636e-01 0.000000000000000000e+00
+8.133602696631743803e-03 9.918663973033683412e-01 0.000000000000000000e+00
+5.047335452112966005e-03 9.949526645478871112e-01 0.000000000000000000e+00
+1.082326194775913752e-05 9.999891767380523211e-01 0.000000000000000000e+00
+2.870496842440280888e-03 9.971295031575596601e-01 0.000000000000000000e+00
+1.649928513034073932e-03 9.983500714869659731e-01 0.000000000000000000e+00
+0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00
+1.149744406550636758e-03 9.988502555934493099e-01 0.000000000000000000e+00
+2.960996886851654058e-05 9.999703900311316396e-01 0.000000000000000000e+00
+1.257104107557816702e-04 9.998742895892441807e-01 0.000000000000000000e+00
+3.621593825608752037e-05 9.999637840617441320e-01 0.000000000000000000e+00
+3.108575623150897343e-03 9.968914243768490779e-01 0.000000000000000000e+00
+2.376848641880500912e-06 9.999976231513580949e-01 0.000000000000000000e+00
+1.861570180677213913e-04 9.998138429819323214e-01 0.000000000000000000e+00
+1.081640912416817913e-03 9.989183590875831964e-01 0.000000000000000000e+00
+9.196417596839462968e-04 9.990803582403160465e-01 0.000000000000000000e+00
+5.047335452112966005e-03 9.949526645478871112e-01 0.000000000000000000e+00
+1.200993024782451637e-02 9.879900697521755149e-01 0.000000000000000000e+00
+5.093772647858645954e-03 9.949062273521414035e-01 0.000000000000000000e+00
+0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00
+2.767061085115974566e-05 9.999723293891488174e-01 0.000000000000000000e+00
+2.628939525553483929e-04 9.997371060474447013e-01 0.000000000000000000e+00
+4.886091393059526210e-05 9.999511390860693627e-01 0.000000000000000000e+00
+7.904835746483410489e-03 9.920951642535165149e-01 0.000000000000000000e+00
+1.256500407188586646e-02 9.874349959281142342e-01 0.000000000000000000e+00
+1.128450079660285078e-02 9.887154992033972967e-01 0.000000000000000000e+00
+1.077511121079013229e-02 9.892248887892098885e-01 0.000000000000000000e+00
+1.170621322638584240e-02 9.882937867736142357e-01 0.000000000000000000e+00
+1.406227582054295558e-02 9.859377241794571312e-01 0.000000000000000000e+00
+1.406227582054295558e-02 9.859377241794571312e-01 0.000000000000000000e+00
+1.412051484522520821e-02 9.858794851547746374e-01 0.000000000000000000e+00
+1.190540735998337971e-02 9.880945926400166446e-01 0.000000000000000000e+00
+8.511272523333973661e-03 9.914887274766660541e-01 0.000000000000000000e+00
+6.598532466738387357e-03 9.934014675332615285e-01 0.000000000000000000e+00
+1.200993024782451637e-02 9.879900697521755149e-01 0.000000000000000000e+00
+1.200993024782451637e-02 9.879900697521755149e-01 0.000000000000000000e+00
+4.295862644646969712e-04 9.995704137355353458e-01 0.000000000000000000e+00
+3.742234019738614054e-03 9.962577659802612784e-01 0.000000000000000000e+00
+4.295862644646969712e-04 9.995704137355353458e-01 0.000000000000000000e+00
+1.591177422645521922e-04 9.998408822577355970e-01 0.000000000000000000e+00
+4.680096412332553210e-04 9.995319903587666088e-01 0.000000000000000000e+00
+4.520229626943932273e-03 9.954797703730561276e-01 0.000000000000000000e+00
+9.982715852524207828e-05 9.999001728414748102e-01 0.000000000000000000e+00
+1.253550765632878363e-04 9.998746449234368061e-01 0.000000000000000000e+00
+0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00
+1.335842199925227000e-02 9.866415780007476988e-01 0.000000000000000000e+00
+4.017597251943550403e-06 9.999959824027480071e-01 0.000000000000000000e+00
+1.475443932066835139e-06 9.999985245560678582e-01 0.000000000000000000e+00
+6.325628558717255312e-06 9.999936743714412657e-01 0.000000000000000000e+00
+9.835051830290222327e-06 9.999901649481696131e-01 0.000000000000000000e+00
+8.949091329050540885e-04 9.991050908670949804e-01 0.000000000000000000e+00
+2.509385202228829552e-05 9.999749061479777934e-01 0.000000000000000000e+00
+4.880467747396461981e-04 9.995119532252603189e-01 0.000000000000000000e+00
+2.281878818264203453e-05 9.999771812118173342e-01 0.000000000000000000e+00
+1.031661023823903206e-04 9.998968338976176318e-01 0.000000000000000000e+00
+1.891918087222814937e-03 9.981080819127771120e-01 0.000000000000000000e+00
+1.118205215059714982e-03 9.988817947849402135e-01 0.000000000000000000e+00
+3.880280157332981878e-05 9.999611971984266878e-01 0.000000000000000000e+00
+2.585746423412355619e-04 9.997414253576588639e-01 0.000000000000000000e+00
+1.435678163511606035e-05 9.999856432183649169e-01 0.000000000000000000e+00
+2.828435781169007755e-04 9.997171564218830797e-01 0.000000000000000000e+00
+2.760109725013567634e-07 9.999997239890274781e-01 0.000000000000000000e+00
+4.918238300261591756e-03 9.950817616997382764e-01 0.000000000000000000e+00
+0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00
+0.000000000000000000e+00 9.999999999999998890e-01 0.000000000000000000e+00
+8.439452627321975160e-08 9.999999156054736327e-01 0.000000000000000000e+00
+4.585021055512082449e-04 9.995414978944487938e-01 0.000000000000000000e+00
+5.546397025713034733e-08 9.999999445360296946e-01 0.000000000000000000e+00
+4.520229626943932273e-03 9.954797703730561276e-01 0.000000000000000000e+00
+2.794784377115112504e-06 9.999972052156228530e-01 0.000000000000000000e+00
+7.487338069821908304e-04 9.992512661930178508e-01 0.000000000000000000e+00
+6.937669385896168273e-02 9.306233061410382756e-01 0.000000000000000000e+00
+2.610567380487986886e-07 9.999997389432618844e-01 0.000000000000000000e+00
+2.635283011904650534e-04 9.997364716988096367e-01 0.000000000000000000e+00
+9.017480542249836639e-02 9.098251945775016614e-01 0.000000000000000000e+00
+1.440636666663253906e-01 8.559363333336744706e-01 0.000000000000000000e+00
+4.168475334260034193e-03 9.958315246657399866e-01 0.000000000000000000e+00
+6.278545680828223619e-02 9.372145431917179303e-01 0.000000000000000000e+00
+1.252165841336563314e-03 9.987478341586635278e-01 0.000000000000000000e+00
+5.271259560958450191e-02 9.472874043904155883e-01 0.000000000000000000e+00
+1.215622720582210739e-05 9.999878437727941494e-01 0.000000000000000000e+00
+8.523448737409815811e-04 9.991476551262591377e-01 0.000000000000000000e+00
+1.364233604016709331e-03 9.986357663959832820e-01 0.000000000000000000e+00
+6.904475716374882516e-06 9.999930955242835040e-01 0.000000000000000000e+00
+1.288789073146522886e-05 9.999871121092684945e-01 0.000000000000000000e+00
+1.158165517425897156e-02 9.884183448257409799e-01 0.000000000000000000e+00
+1.037039405144723515e-02 9.896296059485526486e-01 0.000000000000000000e+00
+4.035026415517931064e-02 9.596497358448206061e-01 0.000000000000000000e+00
+1.298940237770540851e-01 8.701059762229458316e-01 0.000000000000000000e+00
+1.399008401403640245e-01 8.600991598596361420e-01 0.000000000000000000e+00
+0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00
+3.136147636377825481e-04 9.996863852363622183e-01 0.000000000000000000e+00
+2.610567380487986886e-07 9.999997389432618844e-01 0.000000000000000000e+00
+0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00
+3.841066033049441949e-05 9.999615893396694988e-01 0.000000000000000000e+00
+1.033672308047505709e-05 9.999896632769196270e-01 0.000000000000000000e+00
+2.181028540001838631e-06 9.999978189714600063e-01 0.000000000000000000e+00
+2.033874004633050910e-04 9.997966125995367825e-01 0.000000000000000000e+00
+6.904475716374882516e-06 9.999930955242835040e-01 0.000000000000000000e+00
+4.343234804926081804e-04 9.995656765195074511e-01 0.000000000000000000e+00
+1.425257967623769067e-06 9.999985747420323534e-01 0.000000000000000000e+00
+4.889292493132674396e-03 9.951107075068673646e-01 0.000000000000000000e+00
+5.076739003324670435e-04 9.994923260996675385e-01 0.000000000000000000e+00
+6.231085552982358177e-04 9.993768914447018759e-01 0.000000000000000000e+00
+9.706173976027986094e-02 9.029382602397200142e-01 0.000000000000000000e+00
+7.455947631375006712e-02 9.254405236862500717e-01 0.000000000000000000e+00
+3.506282619604699641e-02 9.649371738039529411e-01 0.000000000000000000e+00
+1.096817561101756239e-01 8.903182438898243900e-01 0.000000000000000000e+00
+2.465380897209241479e-05 9.999753461910279029e-01 0.000000000000000000e+00
+4.754551441965680883e-07 9.999995245448557446e-01 0.000000000000000000e+00
+7.680261905715100867e-02 9.231973809428490885e-01 0.000000000000000000e+00
+2.912952622391859134e-02 9.708704737760813774e-01 0.000000000000000000e+00
+1.256198622358731774e-02 9.874380137764126042e-01 0.000000000000000000e+00
+1.232940975545529505e-02 9.876705902445447327e-01 0.000000000000000000e+00
+1.220392501263666690e-02 9.877960749873633262e-01 0.000000000000000000e+00
+1.133955325285818452e-02 9.886604467471418189e-01 0.000000000000000000e+00
+5.660972100994998181e-03 9.943390278990050790e-01 0.000000000000000000e+00
+1.715958719452771080e-03 9.982840412805471519e-01 0.000000000000000000e+00
+3.163345056404154483e-03 9.968366549435956347e-01 0.000000000000000000e+00
+3.163345056404154483e-03 9.968366549435956347e-01 0.000000000000000000e+00
+8.135624731338938348e-03 9.918643752686611137e-01 0.000000000000000000e+00
+1.054804046642309444e-02 9.894519595335770079e-01 0.000000000000000000e+00
+9.825044186422546557e-06 9.999901749558136599e-01 0.000000000000000000e+00
+0.000000000000000000e+00 1.000000000000000222e+00 0.000000000000000000e+00
+2.858857842912272720e-07 9.999997141142157320e-01 0.000000000000000000e+00
+1.715958719452771080e-03 9.982840412805471519e-01 0.000000000000000000e+00
+2.237650239555898438e-02 9.776234976044410052e-01 0.000000000000000000e+00
+1.796734695807572283e-06 9.999982032653040864e-01 0.000000000000000000e+00
+1.286979019848107086e-02 9.871302098015189985e-01 0.000000000000000000e+00
+3.205527984704827017e-04 9.996794472015296806e-01 0.000000000000000000e+00
+8.227212409021464020e-05 9.999177278759098231e-01 0.000000000000000000e+00
+8.524486173950426501e-03 9.914755138260495926e-01 0.000000000000000000e+00
+1.192300202742535044e-02 9.880769979725747554e-01 0.000000000000000000e+00
+6.837977346024055186e-03 9.931620226539759066e-01 0.000000000000000000e+00
+1.393831478368395653e-02 9.860616852163160972e-01 0.000000000000000000e+00
+2.126271119178360213e-03 9.978737288808215977e-01 0.000000000000000000e+00
+8.864693765272988954e-03 9.911353062347270093e-01 0.000000000000000000e+00
+7.660018865584738643e-03 9.923399811344151278e-01 0.000000000000000000e+00
+1.843187203290639828e-02 9.815681279670935844e-01 0.000000000000000000e+00
+1.054767802283502511e-03 9.989452321977164706e-01 0.000000000000000000e+00
+4.857634793195520634e-02 9.514236520680449116e-01 0.000000000000000000e+00
+2.507869816883064040e-02 9.749213018311693180e-01 0.000000000000000000e+00
+9.287363558562300447e-03 9.907126364414376996e-01 0.000000000000000000e+00
+2.642850437790226006e-02 9.735714956220978822e-01 0.000000000000000000e+00
+1.436010145557596596e-02 9.856398985444240202e-01 0.000000000000000000e+00
+4.271796360536132819e-02 9.572820363946386024e-01 0.000000000000000000e+00
+1.196451384912192856e-02 9.880354861508781061e-01 0.000000000000000000e+00
+3.777318498637371839e-04 9.996222681501362173e-01 0.000000000000000000e+00
+1.711174168222450969e-05 9.999828882583178258e-01 0.000000000000000000e+00
+1.254750963064949843e-03 9.987452490369350677e-01 0.000000000000000000e+00
+8.591191788759359397e-06 9.999914088082111352e-01 0.000000000000000000e+00
+0.000000000000000000e+00 9.999999999999998890e-01 0.000000000000000000e+00
+1.649928513034073932e-03 9.983500714869659731e-01 0.000000000000000000e+00
+0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00
+2.339770575509696691e-06 9.999976602294243788e-01 0.000000000000000000e+00
+9.738144751346299477e-06 9.999902618552486411e-01 0.000000000000000000e+00
+3.672742607746636842e-05 9.999632725739224792e-01 0.000000000000000000e+00
+6.156080616682296780e-04 9.993843919383317287e-01 0.000000000000000000e+00
+1.031717134495546212e-04 9.998968282865503543e-01 0.000000000000000000e+00
+1.709685080309916987e-04 9.998290314919691113e-01 0.000000000000000000e+00
+1.957423684348158361e-05 9.999804257631565996e-01 0.000000000000000000e+00
+0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00
+1.124862385649989968e-05 9.999887513761435143e-01 0.000000000000000000e+00
+1.125641537443725916e-06 9.999988743584626860e-01 0.000000000000000000e+00
+1.352966251510091551e-03 9.986470337484898430e-01 0.000000000000000000e+00
+2.870496842440280888e-03 9.971295031575596601e-01 0.000000000000000000e+00
+4.611311071002503130e-04 9.995388688928996679e-01 0.000000000000000000e+00
+2.075967233295271604e-07 9.999997924032765217e-01 0.000000000000000000e+00
+5.176842983245834896e-07 9.999994823157015711e-01 0.000000000000000000e+00
+2.607195281232621857e-06 9.999973928047187766e-01 0.000000000000000000e+00
+2.192849431576730703e-03 9.978071505684231735e-01 0.000000000000000000e+00
+0.000000000000000000e+00 1.000000000000000222e+00 0.000000000000000000e+00
+2.737228088254281044e-06 9.999972627719116991e-01 0.000000000000000000e+00
+4.585848316995945289e-05 9.999541415168300418e-01 0.000000000000000000e+00
+4.585848316995945289e-05 9.999541415168300418e-01 0.000000000000000000e+00
+0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00
+1.028011303197595008e-05 9.999897198869679427e-01 0.000000000000000000e+00
+3.985761581064282998e-05 9.999601423841893988e-01 0.000000000000000000e+00
+7.455919867245278947e-06 9.999925440801328280e-01 0.000000000000000000e+00
+4.551931316792500576e-08 9.999999544806869034e-01 0.000000000000000000e+00
+3.072331846036408767e-05 9.999692766815395650e-01 0.000000000000000000e+00
+1.956520420926877776e-03 9.980434795790732450e-01 0.000000000000000000e+00
+7.455919867245278947e-06 9.999925440801328280e-01 0.000000000000000000e+00
+1.288789073146522886e-05 9.999871121092684945e-01 0.000000000000000000e+00
+2.033874004633050910e-04 9.997966125995367825e-01 0.000000000000000000e+00
+1.288789073146522886e-05 9.999871121092684945e-01 0.000000000000000000e+00
+1.934071216782288669e-04 9.998065928783218537e-01 0.000000000000000000e+00
+1.288789073146522886e-05 9.999871121092684945e-01 0.000000000000000000e+00
diff --git a/mini_live/obj/wrap_utils.py b/mini_live/obj/wrap_utils.py
new file mode 100644
index 0000000..33009af
--- /dev/null
+++ b/mini_live/obj/wrap_utils.py
@@ -0,0 +1,46 @@
+index_wrap = [0, 2, 11, 12, 13, 14, 15, 16, 17, 18, 32, 36, 37, 38, 39, 40, 41, 42, 43, 50, 57, 58, 61,
+ 62, 72, 73, 74, 76, 77, 78, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 95,
+ 96, 97, 98, 100, 101, 106, 116, 117, 118, 119, 123, 129, 132, 135, 136, 137, 138, 140,
+ 142, 146, 147, 148, 149, 150, 152, 164, 165, 167, 169, 170, 171, 172, 175, 176, 177,
+ 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 191, 192, 194, 199, 200, 201, 202,
+ 203, 204, 205, 206, 207, 208, 210, 211, 212, 213, 214, 215, 216, 227, 234, 262, 266,
+ 267, 268, 269, 270, 271, 272, 273, 280, 287, 288, 291, 292, 302, 303, 304, 306, 307,
+ 308, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325,
+ 326, 327, 329, 330, 335, 345, 346, 347, 348, 352, 358, 361, 364, 365, 366, 367, 369,
+ 371, 375, 376, 377, 378, 379, 391, 393, 394, 395, 396, 397, 400, 401, 402, 403, 404,
+ 405, 406, 407, 408, 409, 410, 411, 415, 416, 418, 421, 422, 423, 424, 425, 426, 427,
+ 428, 430, 431, 432, 433, 434, 435, 436, 447, 454]
+
+index_edge_wrap = [111,43,57,21,76,59,68,67,78,66,69,168,177,169,170,161,176,123,159,145,208]
+index_edge_wrap_upper = [111, 110, 51, 52, 53, 54, 48, 63, 56, 47, 46, 1, 148, 149, 158, 165, 150, 156, 155, 154, 153, 207, 208]
+
+print(len(index_wrap))
+
+# index_wrap = index_wrap + [291, 409, 270, 269, 267, 0, 37, 39, 40, 185, 61,
+# 146, 91, 181, 84, 17, 314, 405, 321, 375,]
+import numpy as np
+# 求平均人脸
+def newWrapModel(wrapModel, face_pts_mean_personal_primer):
+
+ face_wrap_entity = wrapModel.copy()
+ # 正规点
+ face_wrap_entity[:len(index_wrap),:3] = face_pts_mean_personal_primer[index_wrap, :3]
+ # 边缘点
+ vert_mid = face_wrap_entity[:,:3][index_edge_wrap[:4] + index_edge_wrap[-4:]].mean(axis=0)
+ for index_, jj in enumerate(index_edge_wrap):
+ face_wrap_entity[len(index_wrap) + index_,:3] = face_wrap_entity[jj, :3] + (face_wrap_entity[jj, :3] - vert_mid) * (0.3 - abs(10-index_)/40)
+ # 牙齿点
+ from talkingface.utils import INDEX_LIPS, main_keypoints_index, INDEX_LIPS_UPPER, INDEX_LIPS_LOWER
+ # 上嘴唇中点
+ mid_upper_mouth = np.mean(face_pts_mean_personal_primer[main_keypoints_index][INDEX_LIPS_UPPER], axis=0)
+ mid_upper_teeth = np.mean(face_wrap_entity[-36:-18, :3], axis=0)
+ tmp = mid_upper_teeth - mid_upper_mouth
+ face_wrap_entity[-36:-18, :2] = face_wrap_entity[-36:-18, :2] - tmp[:2]
+ # 下嘴唇中点
+ mid_lower_mouth = np.mean(face_pts_mean_personal_primer[main_keypoints_index][INDEX_LIPS_LOWER], axis=0)
+ mid_lower_teeth = np.mean(face_wrap_entity[-18:, :3], axis=0)
+ tmp = mid_lower_teeth - mid_lower_mouth
+ # print(tmp)
+ face_wrap_entity[-18:, :2] = face_wrap_entity[-18:, :2] - tmp[:2]
+
+ return face_wrap_entity
\ No newline at end of file
diff --git a/mini_live/opengl_render_interface.py b/mini_live/opengl_render_interface.py
new file mode 100644
index 0000000..e81f844
--- /dev/null
+++ b/mini_live/opengl_render_interface.py
@@ -0,0 +1,251 @@
+import os
+os.environ["kmp_duplicate_lib_ok"] = "true"
+import glfw
+from OpenGL.GL import *
+from OpenGL.GL.shaders import compileProgram, compileShader
+import numpy as np
+import glm
+import os
+current_dir = os.path.dirname(os.path.abspath(__file__))
+import cv2
+class RenderModel:
+ def __init__(self, window_size):
+ self.window_size = window_size
+ if not glfw.init():
+ raise Exception("glfw can not be initialized!")
+ glfw.window_hint(glfw.VISIBLE, glfw.FALSE)
+ print(window_size[0], window_size[1])
+ self.window = glfw.create_window(window_size[0], window_size[1], "Face Render window", None, None)
+ if not self.window:
+ glfw.terminate()
+ raise Exception("glfw window can not be created!")
+ glfw.set_window_pos(self.window, 100, 100)
+ glfw.make_context_current(self.window)
+ # shader 设置
+ current_dir = os.path.dirname(os.path.abspath(__file__))
+ self.program = compileProgram(compileShader(open(os.path.join(current_dir, "shader/prompt.vsh")).readlines(), GL_VERTEX_SHADER),
+ compileShader(open(os.path.join(current_dir, "shader/prompt.fsh")).readlines(), GL_FRAGMENT_SHADER))
+ self.VBO = glGenBuffers(1)
+ self.render_verts = None
+ self.render_face = None
+ self.face_pts_mean = None
+
+ def setContent(self, vertices_, face):
+ glfw.make_context_current(self.window)
+ self.render_verts = vertices_
+ self.render_face = face
+ glUseProgram(self.program)
+ # set up vertex array object (VAO)
+ self.vao = glGenVertexArrays(1)
+ glBindVertexArray(self.vao)
+
+ self.GenVBO(vertices_)
+ self.GenEBO(face)
+
+ # unbind VAO
+ glBindVertexArray(0)
+ glBindBuffer(GL_ARRAY_BUFFER, 0)
+
+ def GenEBO(self, face):
+ self.indices = np.array(face, dtype=np.uint32)
+ self.EBO = glGenBuffers(1)
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.EBO)
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, self.indices.nbytes, self.indices, GL_STATIC_DRAW)
+
+ def GenTexture(self, img, texture_index = GL_TEXTURE0):
+ glfw.make_context_current(self.window)
+ glActiveTexture(texture_index)
+ texture = glGenTextures(1)
+ glBindTexture(GL_TEXTURE_2D, texture)
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
+ image_height, image_width = img.shape[:2]
+ if len(img.shape) == 2:
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, image_width, image_height, 0, GL_RED, GL_UNSIGNED_BYTE,
+ img.tobytes())
+ elif img.shape[2] == 3:
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image_width, image_height, 0, GL_RGB, GL_UNSIGNED_BYTE, img.tobytes())
+ elif img.shape[2] == 4:
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image_width, image_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, img.tobytes())
+ else:
+ print("Image Format not supported")
+ exit(-1)
+
+ # def ChangeTexture(self, img, texture_index):
+ # glBindTexture(GL_TEXTURE_2D, texture1)
+ # glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
+ # glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
+ # glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
+ # glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
+ # # image = cv2.imread(os.path.join(current_dir, "face_mask2.png"), cv2.IMREAD_UNCHANGED)
+ # image = ref_image
+ # img_data = image.tobytes()
+ # image_height, image_width = image.shape[:2]
+ # glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image_width, image_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, img_data)
+
+ def GenVBO(self, vertices_):
+ glfw.make_context_current(self.window)
+ vertices = np.array(vertices_, dtype=np.float32)
+ glBindBuffer(GL_ARRAY_BUFFER, self.VBO)
+ glBufferData(GL_ARRAY_BUFFER, vertices.nbytes, vertices, GL_DYNAMIC_DRAW)
+ glEnableVertexAttribArray(0)
+ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, vertices.itemsize * 13, ctypes.c_void_p(0))
+ # 顶点纹理属性
+ glEnableVertexAttribArray(1)
+ glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, vertices.itemsize * 13, ctypes.c_void_p(12))
+
+ glEnableVertexAttribArray(2)
+ glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, vertices.itemsize * 13, ctypes.c_void_p(28))
+
+ glEnableVertexAttribArray(3)
+ glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, vertices.itemsize * 13, ctypes.c_void_p(44))
+
+ def render2cv(self, out_size = (1000, 1000), mat_world=None, bs_array=None):
+ glfw.make_context_current(self.window)
+ # 设置正交投影矩阵
+ # left = 0
+ # right = standard_size
+ # bottom = 0
+ # top = standard_size
+ # near = standard_size # 近裁剪面距离
+ # far = -standard_size # 远裁剪面距离
+ left = 0
+ right = out_size[0]
+ bottom = 0
+ top = out_size[1]
+ near = 1000 # 近裁剪面距离
+ far = -1000 # 远裁剪面距离
+
+ ortho_matrix = glm.ortho(left, right, bottom, top, near, far)
+ # print("ortho_matrix: ", ortho_matrix)
+
+ glUseProgram(self.program)
+ glEnable(GL_DEPTH_TEST)
+ glEnable(GL_BLEND)
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
+ glEnable(GL_CULL_FACE)
+ # glEnable(GL_CULL_FACE)
+ glCullFace(GL_BACK) # 剔除背面
+ glFrontFace(GL_CW) # 通常顶点顺序是顺时针
+ glClearColor(0, 0, 0, 0)
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
+
+ # # 设置视口
+ # glViewport(100, 0, self.window_size[0], self.window_size[1])
+
+
+
+ glUniform1i(glGetUniformLocation(self.program, "texture_face"), 0)
+ glUniform1i(glGetUniformLocation(self.program, "texture_bs"), 1)
+ glUniformMatrix4fv(glGetUniformLocation(self.program, "gWorld0"), 1, GL_FALSE, mat_world)
+ glUniform1fv(glGetUniformLocation(self.program, "bsVec"), 12, bs_array.astype(np.float32))
+
+ glUniformMatrix4fv(glGetUniformLocation(self.program, "gProjection"), 1, GL_FALSE, glm.value_ptr(ortho_matrix))
+ # bind VAO
+ glBindVertexArray(self.vao)
+ # draw
+ glDrawElements(GL_TRIANGLES, self.indices.size, GL_UNSIGNED_INT, None)
+ # unbind VAO
+ glBindVertexArray(0)
+
+ glfw.swap_buffers(self.window)
+ glReadBuffer(GL_FRONT)
+ # 从缓冲区中的读出的数据是字节数组
+ data = glReadPixels(0, 0, self.window_size[0], self.window_size[1], GL_RGBA, GL_UNSIGNED_BYTE, outputType=None)
+ rgb = data.reshape(self.window_size[1], self.window_size[0], -1).astype(np.uint8)
+ return rgb
+
+def create_render_model(out_size = (384, 384), floor = 5):
+ renderModel = RenderModel(out_size)
+
+ image2 = cv2.imread(os.path.join(current_dir, "bs_texture.png"))
+ renderModel.GenTexture(image2, GL_TEXTURE1)
+
+ from obj.obj_utils import generateRenderInfo
+ render_verts, render_face = generateRenderInfo(floor = floor)
+ renderModel.setContent(render_verts, render_face)
+ renderModel.face_pts_mean = render_verts[:478, :3].copy()
+ return renderModel
+
+def create_render_model2(out_size = (384, 384), floor = 5):
+ renderModel = RenderModel(out_size)
+
+ image2 = cv2.imread(os.path.join(current_dir, "bs_texture.png"))
+ renderModel.GenTexture(image2, GL_TEXTURE1)
+
+ from obj.obj_utils import generateRenderInfo
+ render_verts, render_face = generateRenderInfo(floor = floor)
+ renderModel.setContent(render_verts, render_face)
+ renderModel.face_pts_mean = render_verts[:478, :3].copy()
+ return renderModel
+
+model_size_ = 384
+
+# 示例使用
+if __name__ == "__main__":
+ import pickle
+ import cv2
+ import time
+ import numpy as np
+ import glob
+ import random
+ from OpenGL.GL import *
+ import os
+
+ start_time = time.time()
+ standard_size = 384
+ crop_rotio = [0.5, 0.5, 0.5, 0.5]
+ out_w = int(standard_size*(crop_rotio[0] + crop_rotio[1]))
+ out_h = int(standard_size*(crop_rotio[2] + crop_rotio[3]))
+ out_size = (out_w, out_h)
+ renderModel = create_render_model((int(out_w*0.8), int(out_h*0.8)), floor = 20)
+
+ from talkingface.mediapipe_utils import detect_face_mesh
+ from obj.image_utils import crop_face_from_image, get_standard_image
+ from obj.obj_utils import faceModeling, NewFaceVerts
+
+ image_list = glob.glob(r"F:\C\AI\CV\TalkingFace\OpenGLRender_0830/face_rgba/*.png")
+ image_list.sort()
+ from talkingface.utils import crop_mouth,main_keypoints_index
+ for index, img_path in enumerate(image_list):
+ img_primer_rgba = cv2.imread(img_path, cv2.IMREAD_UNCHANGED)
+ source_pts = detect_face_mesh([img_primer_rgba[:, :, :3]])[0]
+ img_primer_rgba = cv2.cvtColor(img_primer_rgba, cv2.COLOR_BGRA2RGBA)
+ source_crop_rect = crop_mouth(source_pts[main_keypoints_index],img_primer_rgba.shape[1], img_primer_rgba.shape[0])
+ standard_img, standard_v, standard_vt = get_standard_image(img_primer_rgba, source_pts, source_crop_rect,
+ out_size=(
+ int(standard_size * (crop_rotio[0] + crop_rotio[1])),
+ int(standard_size * (
+ crop_rotio[2] + crop_rotio[3]))))
+
+ source_crop_pts = standard_v
+
+ # from obj.image_utils import check_keypoint
+ # check_keypoint(standard_img, source_crop_pts)
+
+ render_verts = renderModel.render_verts.copy()
+ render_verts[:len(source_crop_pts), :3] = source_crop_pts
+ w = standard_size * (crop_rotio[0] + crop_rotio[1])
+ h = standard_size * (crop_rotio[2] + crop_rotio[3])
+ render_verts[:len(source_crop_pts), 3] = source_crop_pts[:, 0] / w
+ render_verts[:len(source_crop_pts), 4] = source_crop_pts[:, 1] / h
+ render_verts,Rmat = NewFaceVerts(render_verts, source_crop_pts, renderModel.face_pts_mean)
+
+ image2 = standard_img.copy()
+ renderModel.GenTexture(image2, GL_TEXTURE0)
+ renderModel.GenVBO(render_verts)
+
+ rotate_max = 20
+ for i in range(-rotate_max * 5, rotate_max * 5, 5):
+ # bs = np.array([i*1, 0, 0, 0,0,0], dtype=np.float32)*1.2
+ bs = np.zeros([12], dtype=np.float32)
+ bs[0] = i
+ # rotationMatrix = mat_list__.T
+ bs[1] = 1.2 * bs[1] + 5
+ i = (bs[0] + bs[1]) / 3. + 3
+ rgba = renderModel.render2cv(out_size=out_size, mat_world=Rmat, bs_array=bs)
+ final_img = cv2.cvtColor(rgba, cv2.COLOR_RGBA2BGRA)
+ cv2.imshow('scene', final_img[:, :, :3].astype(np.uint8))
+ cv2.waitKey(30)
diff --git a/mini_live/render.py b/mini_live/render.py
new file mode 100644
index 0000000..8e385a4
--- /dev/null
+++ b/mini_live/render.py
@@ -0,0 +1,300 @@
+import os
+os.environ["kmp_duplicate_lib_ok"] = "true"
+import glfw
+from OpenGL.GL import *
+from OpenGL.GL.shaders import compileProgram, compileShader
+import numpy as np
+import glm
+import os
+from mini_live.obj.wrap_utils import index_wrap, index_edge_wrap
+from mini_live.obj.obj_utils import generateRenderInfo, generateWrapModel
+from talkingface.utils import crop_mouth, main_keypoints_index
+current_dir = os.path.dirname(os.path.abspath(__file__))
+import cv2
+import torch.nn.functional as F
+class RenderModel_gl:
+ def __init__(self, window_size):
+ self.window_size = window_size
+ if not glfw.init():
+ raise Exception("glfw can not be initialized!")
+ glfw.window_hint(glfw.VISIBLE, glfw.FALSE)
+ print(window_size[0], window_size[1])
+ self.window = glfw.create_window(window_size[0], window_size[1], "Face Render window", None, None)
+ if not self.window:
+ glfw.terminate()
+ raise Exception("glfw window can not be created!")
+ glfw.set_window_pos(self.window, 100, 100)
+ glfw.make_context_current(self.window)
+ # shader 设置
+ current_dir = os.path.dirname(os.path.abspath(__file__))
+ self.program = compileProgram(compileShader(open(os.path.join(current_dir, "shader/prompt3.vsh")).readlines(), GL_VERTEX_SHADER),
+ compileShader(open(os.path.join(current_dir, "shader/prompt3.fsh")).readlines(), GL_FRAGMENT_SHADER))
+ self.VBO = glGenBuffers(1)
+ self.render_verts = None
+ self.render_face = None
+ self.face_pts_mean = None
+
+ def setContent(self, vertices_, face):
+ glfw.make_context_current(self.window)
+ self.render_verts = vertices_
+ self.render_face = face
+ glUseProgram(self.program)
+ # set up vertex array object (VAO)
+ self.vao = glGenVertexArrays(1)
+ glBindVertexArray(self.vao)
+
+ self.GenVBO(vertices_)
+ self.GenEBO(face)
+
+ # unbind VAO
+ glBindVertexArray(0)
+ glBindBuffer(GL_ARRAY_BUFFER, 0)
+
+ def GenEBO(self, face):
+ self.indices = np.array(face, dtype=np.uint32)
+ self.EBO = glGenBuffers(1)
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.EBO)
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, self.indices.nbytes, self.indices, GL_STATIC_DRAW)
+
+ def GenTexture(self, img, texture_index = GL_TEXTURE0):
+ glfw.make_context_current(self.window)
+ glActiveTexture(texture_index)
+ texture = glGenTextures(1)
+ glBindTexture(GL_TEXTURE_2D, texture)
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
+ image_height, image_width = img.shape[:2]
+ if len(img.shape) == 2:
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, image_width, image_height, 0, GL_RED, GL_UNSIGNED_BYTE,
+ img.tobytes())
+ elif img.shape[2] == 3:
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image_width, image_height, 0, GL_RGB, GL_UNSIGNED_BYTE, img.tobytes())
+ elif img.shape[2] == 4:
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image_width, image_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, img.tobytes())
+ else:
+ print("Image Format not supported")
+ exit(-1)
+
+ def GenVBO(self, vertices_):
+ glfw.make_context_current(self.window)
+ vertices = np.array(vertices_, dtype=np.float32)
+ glBindBuffer(GL_ARRAY_BUFFER, self.VBO)
+ glBufferData(GL_ARRAY_BUFFER, vertices.nbytes, vertices, GL_DYNAMIC_DRAW)
+ glEnableVertexAttribArray(0)
+ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, vertices.itemsize * 5, ctypes.c_void_p(0))
+ # 顶点纹理属性
+ glEnableVertexAttribArray(1)
+ glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, vertices.itemsize * 5, ctypes.c_void_p(12))
+
+ def render2cv(self, vertBuffer, out_size = (1000, 1000), mat_world=None, bs_array=None):
+ glfw.make_context_current(self.window)
+ # 设置正交投影矩阵
+ # left = 0
+ # right = standard_size
+ # bottom = 0
+ # top = standard_size
+ # near = standard_size # 近裁剪面距离
+ # far = -standard_size # 远裁剪面距离
+ left = 0
+ right = out_size[0]
+ bottom = 0
+ top = out_size[1]
+ near = 1000 # 近裁剪面距离
+ far = -1000 # 远裁剪面距离
+
+ ortho_matrix = glm.ortho(left, right, bottom, top, near, far)
+ glUniformMatrix4fv(glGetUniformLocation(self.program, "gProjection"), 1, GL_FALSE, glm.value_ptr(ortho_matrix))
+
+ # print("ortho_matrix: ", ortho_matrix)
+
+ glUseProgram(self.program)
+ glEnable(GL_DEPTH_TEST)
+ glEnable(GL_BLEND)
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
+ glEnable(GL_CULL_FACE)
+ # glEnable(GL_CULL_FACE)
+ glCullFace(GL_BACK) # 剔除背面
+ glFrontFace(GL_CW) # 通常顶点顺序是顺时针
+ glClearColor(0.5, 0.5, 0.5, 0)
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
+
+ # # 设置视口
+ # glViewport(100, 0, self.window_size[0], self.window_size[1])
+
+
+ glUniform1i(glGetUniformLocation(self.program, "texture_bs"), 0)
+ glUniformMatrix4fv(glGetUniformLocation(self.program, "gWorld0"), 1, GL_FALSE, mat_world)
+ glUniform1fv(glGetUniformLocation(self.program, "bsVec"), 12, bs_array.astype(np.float32))
+
+ glUniform2fv(glGetUniformLocation(self.program, "vertBuffer"), 209, vertBuffer.astype(np.float32))
+
+ glUniformMatrix4fv(glGetUniformLocation(self.program, "gProjection"), 1, GL_FALSE, glm.value_ptr(ortho_matrix))
+ # bind VAO
+ glBindVertexArray(self.vao)
+ # draw
+ glDrawElements(GL_TRIANGLES, self.indices.size, GL_UNSIGNED_INT, None)
+ # unbind VAO
+ glBindVertexArray(0)
+
+ glfw.swap_buffers(self.window)
+ glReadBuffer(GL_FRONT)
+ # 从缓冲区中的读出的数据是字节数组
+ data = glReadPixels(0, 0, self.window_size[0], self.window_size[1], GL_RGBA, GL_UNSIGNED_BYTE, outputType=None)
+ rgb = data.reshape(self.window_size[1], self.window_size[0], -1).astype(np.uint8)
+ return rgb
+
+def create_render_model(out_size = (384, 384), floor = 5):
+ renderModel_gl = RenderModel_gl(out_size)
+
+ image2 = cv2.imread(os.path.join(current_dir, "bs_texture_halfFace.png"))
+ image2 = cv2.cvtColor(image2, cv2.COLOR_BGR2RGBA)
+ renderModel_gl.GenTexture(image2, GL_TEXTURE0)
+
+ render_verts, render_face = generateRenderInfo()
+ wrapModel_verts,wrapModel_face = generateWrapModel()
+
+ renderModel_gl.setContent(wrapModel_verts, wrapModel_face)
+ renderModel_gl.render_verts = render_verts
+ renderModel_gl.render_face = render_face
+ renderModel_gl.face_pts_mean = render_verts[:478, :3].copy()
+ return renderModel_gl
+
+# 示例使用
+if __name__ == "__main__":
+ import pickle
+ import cv2
+ import time
+ import numpy as np
+ import glob
+ import random
+ from OpenGL.GL import *
+ import os
+
+ import torch
+ from talkingface.model_utils import LoadAudioModel,Audio2bs
+ from talkingface.data.few_shot_dataset import get_image
+
+ Audio2FeatureModel = LoadAudioModel(r'../checkpoint\lstm/lstm_model_epoch_325.pkl')
+
+ from talkingface.render_model_mini import RenderModel_Mini
+ renderModel_mini = RenderModel_Mini()
+ renderModel_mini.loadModel("../checkpoint/DINet_mini/epoch_40.pth")
+
+ start_time = time.time()
+ standard_size = 256
+ crop_rotio = [0.5, 0.5, 0.5, 0.5]
+ out_w = int(standard_size*(crop_rotio[0] + crop_rotio[1]))
+ out_h = int(standard_size*(crop_rotio[2] + crop_rotio[3]))
+ out_size = (out_w, out_h)
+ renderModel_gl = create_render_model((out_w, out_h), floor = 20)
+
+ wrapModel,wrapModel_face = generateWrapModel()
+
+ path = r"F:\C\AI\CV\DH008_few_shot/preparation_new"
+ video_list = os.listdir(r"{}".format(path))
+ print(video_list)
+ for test_video in video_list[:15]:
+ Path_output_pkl = "{}/{}/keypoint_rotate.pkl".format(path, test_video)
+ with open(Path_output_pkl, "rb") as f:
+ images_info = pickle.load(f)
+
+ images_info = np.concatenate([images_info, images_info[::-1]], axis=0)
+
+ video_path = "{}/{}/circle.mp4".format(path, test_video)
+ cap = cv2.VideoCapture(video_path)
+ vid_frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
+ vid_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
+ vid_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
+
+ list_source_crop_rect = []
+ list_video_img = []
+ list_standard_img = []
+ list_standard_v = []
+ list_standard_vt = []
+ for frame_index in range(min(vid_frame_count, len(images_info))):
+ ret, frame = cap.read()
+ frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA)
+ source_pts = images_info[frame_index]
+ source_crop_rect = crop_mouth(source_pts[main_keypoints_index], vid_width, vid_height)
+
+ standard_img = get_image(frame, source_crop_rect, input_type="image", resize = standard_size)
+ standard_v = get_image(source_pts, source_crop_rect, input_type="mediapipe", resize = standard_size)
+ standard_vt = standard_v[:, :2] / standard_size
+
+ list_video_img.append(frame)
+ list_source_crop_rect.append(source_crop_rect)
+ list_standard_img.append(standard_img)
+ list_standard_v.append(standard_v)
+ list_standard_vt.append(standard_vt)
+ cap.release()
+
+ renderModel_mini.reset_charactor(list_standard_img, np.array(list_standard_v)[:,main_keypoints_index])
+ from talkingface.run_utils import calc_face_mat
+ mat_list, _, face_pts_mean_personal_primer = calc_face_mat(np.array(list_standard_v), renderModel_gl.face_pts_mean)
+ from mini_live.obj.wrap_utils import newWrapModel
+ face_wrap_entity = newWrapModel(wrapModel, face_pts_mean_personal_primer)
+
+ renderModel_gl.GenVBO(face_wrap_entity)
+
+ wav2_dir = glob.glob(r"F:\C\AI\CV\DH008_few_shot\wav/*.wav")
+ sss = random.randint(0, len(wav2_dir)-1)
+ wavpath = wav2_dir[sss]
+ bs_array = Audio2bs(wavpath, Audio2FeatureModel)[5:] * 0.5
+
+ import uuid
+ task_id = str(uuid.uuid1())
+ fourcc = cv2.VideoWriter_fourcc(*'mp4v')
+ save_path = "{}.mp4".format(task_id)
+
+ videoWriter = cv2.VideoWriter(save_path, fourcc, 25, (int(vid_width), int(vid_height)))
+
+ for frame_index in range(len(mat_list)):
+ if frame_index >= len(bs_array):
+ continue
+ bs = np.zeros([12], dtype=np.float32)
+ bs[:6] = bs_array[frame_index, :6]
+ # bs[2] = frame_index* 5
+
+ verts_frame_buffer = np.array(list_standard_vt)[frame_index, index_wrap, :2].copy() * 2 - 1
+
+ rgba = renderModel_gl.render2cv(verts_frame_buffer, out_size=out_size, mat_world=mat_list[frame_index].T, bs_array=bs)
+ # rgb = cv2.cvtColor(rgba, cv2.COLOR_RGBA2RGB)
+
+ # rgba = cv2.resize(rgba, (128, 128))
+ rgba = rgba[::2, ::2, :]
+
+ gl_tensor = torch.from_numpy(rgba/255.).float().permute(2, 0, 1).unsqueeze(0)
+ source_tensor = cv2.resize(list_standard_img[frame_index], (128, 128))
+ source_tensor = torch.from_numpy(source_tensor/255.).float().permute(2, 0, 1).unsqueeze(0)
+
+ warped_img = renderModel_mini.interface(source_tensor.cuda(), gl_tensor.cuda())
+
+ image_numpy = warped_img.detach().squeeze(0).cpu().float().numpy()
+ image_numpy = np.transpose(image_numpy, (1, 2, 0)) * 255.0
+ image_numpy = image_numpy.clip(0, 255)
+ image_numpy = image_numpy.astype(np.uint8)
+ # print(image_numpy.shape)
+ # cv2.imshow('scene', image_numpy)
+ # cv2.waitKey(40)
+ x_min, y_min, x_max, y_max = list_source_crop_rect[frame_index]
+
+ img_face = cv2.resize(image_numpy, (x_max - x_min, y_max - y_min))
+ img_bg = list_video_img[frame_index][:,:,:3]
+ img_bg[y_min:y_max, x_min:x_max, :3] = img_face[:,:,:3]
+ # cv2.imshow('scene', img_bg[:,:,::-1])
+ # cv2.waitKey(40)
+ # print(time.time())
+
+ videoWriter.write(img_bg[:,:,::-1])
+ videoWriter.release()
+ os.makedirs("output", exist_ok=True)
+ val_video = "output/{}.mp4".format(task_id + "_2")
+
+ wav_path = wavpath
+ os.system(
+ "ffmpeg -i {} -i {} -c:v libx264 -pix_fmt yuv420p {}".format(save_path, wav_path, val_video))
+ os.remove(save_path)
+
+ cv2.destroyAllWindows()
\ No newline at end of file
diff --git a/mini_live/shader/prompt3.fsh b/mini_live/shader/prompt3.fsh
new file mode 100644
index 0000000..0c16402
--- /dev/null
+++ b/mini_live/shader/prompt3.fsh
@@ -0,0 +1,34 @@
+# version 330
+precision mediump float;
+in mediump vec2 v_texture;
+in mediump vec2 v_bias;
+out highp vec4 out_color;
+
+void main()
+{
+ if (v_texture.x == 2.0f)
+ {
+ out_color = vec4(1.0, 0.0, 0.0, 1.0);
+ }
+ else if (v_texture.x > 2.0f && v_texture.x < 2.1f)
+ {
+ out_color = vec4(0.5f, 0.0, 0.0, 1.0);
+ }
+ else if (v_texture.x == 3.0f)
+ {
+ out_color = vec4(0.0, 1.0, 0.0, 1.0);
+ }
+ else if (v_texture.x == 4.0f)
+ {
+ out_color = vec4(0.0, 0.0, 1.0, 1.0);
+ }
+ else if (v_texture.x > 3.0f && v_texture.x < 4.0f)
+ {
+ out_color = vec4(0.0, 0.0, 0.0, 1.0);
+ }
+ else
+ {
+ vec2 wrap = (v_bias.xy + 1.0)/2.0;
+ out_color = vec4(wrap.xy, 0.5, 1.0);
+ }
+}
\ No newline at end of file
diff --git a/mini_live/shader/prompt3.vsh b/mini_live/shader/prompt3.vsh
new file mode 100644
index 0000000..174f371
--- /dev/null
+++ b/mini_live/shader/prompt3.vsh
@@ -0,0 +1,67 @@
+# version 330
+
+layout(location = 0) in vec3 a_position;
+layout(location = 1) in vec2 a_texture;
+uniform float bsVec[12];
+uniform mat4 gProjection;
+uniform mat4 gWorld0;
+uniform sampler2D texture_bs;
+
+uniform vec2 vertBuffer[209];
+
+out vec2 v_texture;
+out vec2 v_bias;
+vec4 calculateMorphPosition(vec3 position, vec2 textureCoord) {
+ vec4 tmp_Position2 = vec4(position, 1.0);
+ if (textureCoord.x < 3.0) {
+ vec3 morphSum = vec3(0.0);
+ for (int i = 0; i < 6; i++) {
+ ivec2 coord = ivec2(int(textureCoord.y), i);
+ vec3 morph = texelFetch(texture_bs, coord, 0).xyz * 2.0 - 1.0;
+ morphSum += bsVec[i] * morph;
+ }
+ ivec2 coord6 = ivec2(int(textureCoord.y), 6);
+ morphSum += bsVec[6] * texelFetch(texture_bs, coord6, 0).xyz;
+ tmp_Position2.xyz += morphSum;
+ }
+ else if (textureCoord.x == 4.0)
+ {
+ // lower teeth
+ vec3 morphSum = vec3(0.0, (bsVec[0] + bsVec[1])/ 2.7 + 6, 0.0);
+ tmp_Position2.xyz += morphSum;
+ }
+ return tmp_Position2;
+}
+
+void main() {
+ mat4 gWorld = gWorld0;
+
+ vec4 tmp_Position2 = calculateMorphPosition(a_position, a_texture);
+ vec4 tmp_Position = gWorld * tmp_Position2;
+ // vec4 tmp_Position = gWorld * vec4(a_position, 1.0);
+ // vec3 tmp_Position = a_position;
+// vec4 pos_ = gProjection * vec4(tmp_Position.x, tmp_Position.y, tmp_Position.z, 1.0);
+ // # upper lips 1 lower lips2 teeth3 edge4
+
+ v_bias = vec2(0.0, 0.0);
+ if (a_texture.x == -1.0f)
+ {
+ v_bias = vec2(0.0, 0.0);
+ }
+ else if (a_texture.y < 209.0f)
+ {
+ vec4 vert_new = gProjection * vec4(tmp_Position.x, tmp_Position.y, tmp_Position.z, 1.0);
+ v_bias = vert_new.xy - vertBuffer[int(a_texture.y)].xy;
+ }
+
+ if (a_texture.x >= 3.0f)
+ {
+ gl_Position = gProjection * vec4(tmp_Position.x, tmp_Position.y, 500.0, 1.0);
+ }
+ else
+ {
+ gl_Position = gProjection * vec4(tmp_Position.x, tmp_Position.y, tmp_Position.z, 1.0);
+ }
+
+ v_texture = a_texture;
+}
\ No newline at end of file
diff --git a/mini_live/train.py b/mini_live/train.py
new file mode 100644
index 0000000..6a466c3
--- /dev/null
+++ b/mini_live/train.py
@@ -0,0 +1,197 @@
+import os
+os.environ["kmp_duplicate_lib_ok"] = "true"
+from talkingface.models.common.Discriminator import Discriminator
+from talkingface.models.common.VGG19 import Vgg19
+from talkingface.models.DINet_mini import DINet_mini as DINet
+from talkingface.util.utils import GANLoss,get_scheduler, update_learning_rate
+from talkingface.config.config import DINetTrainingOptions
+from torch.utils.tensorboard import SummaryWriter
+from talkingface.util.log_board import log
+import torch
+import torch.nn as nn
+import torch.optim as optim
+from torch.utils.data import DataLoader
+import random
+import numpy as np
+import os
+import pandas as pd
+import torch.nn.functional as F
+import cv2
+from talkingface.data.DHLive_mini_dataset import Few_Shot_Dataset,data_preparation
+
+def Tensor2img(tensor_, channel_index):
+ frame = tensor_[channel_index:channel_index + 3, :, :].detach().squeeze(0).cpu().float().numpy()
+ frame = np.transpose(frame, (1, 2, 0)) * 255.0
+ frame = frame.clip(0, 255)
+ return frame.astype(np.uint8)
+
+if __name__ == "__main__":
+ '''
+ training code of person image generation
+ '''
+ # load config
+ opt = DINetTrainingOptions().parse_args()
+
+ model_name = "DINet_mini"
+ n_ref = 3
+ opt.source_channel = 3
+ opt.target_channel = 3
+ opt.ref_channel = n_ref * 4
+ opt.D_num_blocks = 3
+ opt.batch_size = 4
+ opt.result_path = "checkpoint/{}".format(model_name)
+ opt.resume = True
+ opt.resume_path = "checkpoint/{}/epoch_18.pth".format(model_name)
+ train_log_path = os.path.join("checkpoint/{}/log".format(model_name), "")
+ opt.seed = 1008
+
+ # set seed
+ random.seed(opt.seed)
+ np.random.seed(opt.seed)
+ torch.cuda.manual_seed(opt.seed)
+
+ df = pd.read_csv(r"F:\C\AI\CV\DH008_few_shot\DH0119_mouth64_48/imageVar2.csv")
+ video_list = df[df["imageVar"] > 360000]["name"].tolist()
+ video_list = [i for i in video_list if os.path.exists(i)]
+ video_list = [os.path.dirname(os.path.dirname(i)) for i in video_list]
+ path_ = r"F:\C\AI\CV\DH008_few_shot/preparation_bilibili"
+ video_list += [os.path.join(path_, i) for i in os.listdir(path_)]
+
+ print("video_selected final: ", len(video_list))
+ video_list.sort()
+ train_dict_info = data_preparation(video_list[:])
+ train_set = Few_Shot_Dataset(train_dict_info, n_ref=n_ref, is_train=True)
+ training_data_loader = DataLoader(dataset=train_set, num_workers=0, batch_size=opt.batch_size, shuffle=True)
+
+ # init network
+ net_g = DINet(opt.source_channel,opt.ref_channel, cuda= True).cuda()
+ net_d = Discriminator(opt.target_channel, opt.D_block_expansion, opt.D_num_blocks, opt.D_max_features).cuda()
+ net_vgg = Vgg19().cuda()
+
+ # set optimizer
+ optimizer_g = optim.Adam(net_g.parameters(), lr=opt.lr_g)
+ optimizer_d = optim.Adam(net_d.parameters(), lr=opt.lr_d)
+
+ if opt.resume:
+ print('loading checkpoint {}'.format(opt.resume_path))
+ checkpoint = torch.load(opt.resume_path)
+ # opt.start_epoch = checkpoint['epoch']
+ # opt.start_epoch = 200
+ net_g_static = checkpoint['state_dict']['net_g']
+ net_g.load_state_dict(net_g_static, strict=False)
+ net_d.load_state_dict(checkpoint['state_dict']['net_d'])
+ optimizer_g.load_state_dict(checkpoint['optimizer']['net_g'])
+ optimizer_d.load_state_dict(checkpoint['optimizer']['net_d'])
+
+ # set criterion
+ criterionGAN = GANLoss().cuda()
+ criterionL1 = nn.L1Loss().cuda()
+ # set scheduler
+ net_g_scheduler = get_scheduler(optimizer_g, opt.non_decay, opt.decay)
+ net_d_scheduler = get_scheduler(optimizer_d, opt.non_decay, opt.decay)
+
+ os.makedirs(train_log_path, exist_ok=True)
+ train_logger = SummaryWriter(train_log_path)
+ tag_index = 0
+ # start train
+ for epoch in range(opt.start_epoch, opt.non_decay + opt.decay + 1):
+ net_g.train()
+ avg_loss_g_perception = 0
+ avg_Loss_DI = 0
+ avg_Loss_GI = 0
+ for iteration, data in enumerate(training_data_loader):
+ # read data
+ source_tensor, ref_tensor, target_tensor, image_name = data
+ source_tensor = source_tensor.float().cuda()
+ ref_tensor = ref_tensor.float().cuda()
+ target_tensor = target_tensor.float().cuda()
+
+ # network forward
+ fake_out = net_g(ref_tensor, source_tensor)
+ # down sample output image and real image
+ fake_out_half = F.avg_pool2d(fake_out, 3, 2, 1, count_include_pad=False)
+ target_tensor_half = F.interpolate(target_tensor, scale_factor=0.5, mode='bilinear')
+ # (1) Update D network
+ optimizer_d.zero_grad()
+ # compute fake loss
+ _,pred_fake_d = net_d(fake_out)
+ loss_d_fake = criterionGAN(pred_fake_d, False)
+ # compute real loss
+ _,pred_real_d = net_d(target_tensor)
+ loss_d_real = criterionGAN(pred_real_d, True)
+ # Combine D loss
+ loss_dI = (loss_d_fake + loss_d_real) * 0.5
+ loss_dI.backward(retain_graph=True)
+ optimizer_d.step()
+ # (2) Update G network
+ _, pred_fake_dI = net_d(fake_out)
+ optimizer_g.zero_grad()
+ # compute perception loss
+ perception_real = net_vgg(target_tensor)
+ perception_fake = net_vgg(fake_out)
+ perception_real_half = net_vgg(target_tensor_half)
+ perception_fake_half = net_vgg(fake_out_half)
+ loss_g_perception = 0
+ for i in range(len(perception_real)):
+ loss_g_perception += criterionL1(perception_fake[i], perception_real[i])
+ loss_g_perception += criterionL1(perception_fake_half[i], perception_real_half[i])
+ loss_g_perception = (loss_g_perception / (len(perception_real) * 2)) * opt.lamb_perception
+
+ # gan dI loss
+ loss_g_dI = criterionGAN(pred_fake_dI, True)
+ # combine perception loss and gan loss
+ loss_g = loss_g_perception + loss_g_dI
+ loss_g.backward()
+ optimizer_g.step()
+ message = "===> Epoch[{}]({}/{}): Loss_DI: {:.4f} Loss_GI: {:.4f} Loss_perception: {:.4f} lr_g = {:.7f} lr_d = {:.7f}".format(
+ epoch, iteration, len(training_data_loader), float(loss_dI), float(loss_g_dI),
+ float(loss_g_perception), optimizer_g.param_groups[0]['lr'], optimizer_d.param_groups[0]['lr'])
+ print(message)
+ # with open("train_log.txt", "a") as f:
+ # f.write(message + "\n")
+
+ if iteration%200 == 0:
+ inference_out = fake_out * 255
+ inference_out = inference_out[0].cpu().permute(1, 2, 0).float().detach().numpy().astype(np.uint8)
+ inference_in = (target_tensor[0, :3]* 255).cpu().permute(1, 2, 0).float().detach().numpy().astype(np.uint8)
+ inference_in_prompt = (source_tensor[0, :3] * 255).cpu().permute(1, 2, 0).float().detach().numpy().astype(
+ np.uint8)
+ frame2 = Tensor2img(ref_tensor[0], 1)
+ frame3 = Tensor2img(ref_tensor[0], 5)
+
+ inference_out = np.concatenate([inference_in, inference_in_prompt, inference_out, frame2, frame3], axis=1)
+ # inference_out = cv2.cvtColor(inference_out, cv2.COLOR_RGB2BGR)
+
+ log(train_logger, fig=inference_out, tag="Training/epoch_{}_{}".format(epoch, iteration))
+
+ real_iteration = epoch * len(training_data_loader) + iteration
+ message1 = "Step {}/{}, ".format(real_iteration, (epoch + 1) * len(training_data_loader))
+ message2 = ""
+ losses = [loss_dI.item(), loss_g_perception.item(), loss_g_dI.item()]
+ train_logger.add_scalar("Loss/loss_dI", losses[0], real_iteration)
+ train_logger.add_scalar("Loss/loss_g_perception", losses[1], real_iteration)
+ train_logger.add_scalar("Loss/loss_g_dI", losses[2], real_iteration)
+
+ avg_loss_g_perception += loss_g_perception.item()
+ avg_Loss_DI += loss_dI.item()
+ avg_Loss_GI += loss_g_dI.item()
+ train_logger.add_scalar("Loss/{}".format("epoch_g_perception"), avg_loss_g_perception / len(training_data_loader), epoch)
+ train_logger.add_scalar("Loss/{}".format("epoch_DI"),
+ avg_Loss_DI / len(training_data_loader), epoch)
+ train_logger.add_scalar("Loss/{}".format("epoch_GI"),
+ avg_Loss_GI / len(training_data_loader), epoch)
+ update_learning_rate(net_g_scheduler, optimizer_g)
+ update_learning_rate(net_d_scheduler, optimizer_d)
+
+ # checkpoint
+ if epoch % opt.checkpoint == 0:
+ if not os.path.exists(opt.result_path):
+ os.mkdir(opt.result_path)
+ model_out_path = os.path.join(opt.result_path, 'epoch_{}.pth'.format(epoch))
+ states = {
+ 'epoch': epoch + 1,
+ 'state_dict': {'net_g': net_g.state_dict(), 'net_d': net_d.state_dict()},
+ 'optimizer': {'net_g': optimizer_g.state_dict(), 'net_d': optimizer_d.state_dict()}
+ }
+ torch.save(states, model_out_path)
+ print("Checkpoint saved to {}".format(epoch))
\ No newline at end of file
diff --git a/mini_live/train_input_validation.py b/mini_live/train_input_validation.py
new file mode 100644
index 0000000..46b1956
--- /dev/null
+++ b/mini_live/train_input_validation.py
@@ -0,0 +1,65 @@
+import os
+os.environ["kmp_duplicate_lib_ok"] = "true"
+import pickle
+import cv2
+import numpy as np
+import random
+import pandas as pd
+import glob
+import copy
+import torch
+from torch.utils.data import DataLoader
+from talkingface.data.DHLive_mini_dataset import Few_Shot_Dataset,data_preparation
+from talkingface.utils import *
+# video_list = glob.glob(r"E:\data\video\video\*.mp4")
+# video_list = [os.path.basename(i).split(".")[0] for i in video_list]
+
+df = pd.read_csv(r"F:\C\AI\CV\DH008_few_shot\DH0119_mouth64_48/imageVar2.csv")
+video_list = df[df["imageVar"] > 265000]["name"].tolist()
+video_list = [os.path.dirname(os.path.dirname(i)) for i in video_list]
+print(len(video_list))
+point_size = 1
+point_color = (0, 0, 255) # BGR
+thickness = 4 # 0 、4、8
+video_list = video_list[105:125]
+
+dict_info = data_preparation(video_list)
+
+device = torch.device("cuda:0")
+test_set = Few_Shot_Dataset(dict_info, is_train=True, n_ref = 3)
+testing_data_loader = DataLoader(dataset=test_set, num_workers=0, batch_size=1, shuffle=False)
+
+def Tensor2img(tensor_, channel_index):
+ frame = tensor_[channel_index:channel_index + 3, :, :].detach().squeeze(0).cpu().float().numpy()
+ frame = np.transpose(frame, (1, 2, 0)) * 255.0
+ frame = frame.clip(0, 255)
+ return frame.astype(np.uint8)
+size_ = 256
+for iteration, batch in enumerate(testing_data_loader):
+ # source_tensor, source_prompt_tensor, ref_tensor, ref_prompt_tensor, target_tensor = [iii.to(device) for iii in batch]
+ source_tensor, ref_tensor, target_tensor = [iii.to(device) for iii in batch[:3]]
+ print(source_tensor.size(), ref_tensor.size(), target_tensor.size(), batch[3][0])
+
+ frame0 = Tensor2img(source_tensor[0], 0)
+ frame1 = Tensor2img(ref_tensor[0], 0)
+ frame2 = Tensor2img(ref_tensor[0], 1)
+ frame3 = Tensor2img(ref_tensor[0], 4)
+ frame4 = Tensor2img(ref_tensor[0], 5)
+ frame5 = Tensor2img(target_tensor[0], 0)
+
+ # cv2.imwrite("in0.png", frame0)
+ # cv2.imwrite("in1.png", frame1)
+ # cv2.imwrite("in2.png", frame2)
+ # cv2.imwrite("in3.png", frame3)
+ # cv2.imwrite("in4.png", frame4)
+ # exit()
+
+
+ frame = np.concatenate([frame0, frame1, frame2, frame3, frame4, frame5], axis=1)
+
+ cv2.imshow("ss", frame[:, :, ::-1])
+ # if iteration > 840:
+ # cv2.waitKey(-1)
+ cv2.waitKey(-1)
+ # break
+cv2.destroyAllWindows()
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..0c0fdb1
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,5 @@
+kaldi_native_fbank
+mediapipe
+sounddevice
+tqdm
+scikit-learn
\ No newline at end of file
diff --git a/talkingface/__init__.py b/talkingface/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/talkingface/audio_model.py b/talkingface/audio_model.py
new file mode 100644
index 0000000..f390518
--- /dev/null
+++ b/talkingface/audio_model.py
@@ -0,0 +1,129 @@
+import sys
+import numpy as np
+import kaldi_native_fbank as knf
+from scipy.io import wavfile
+import torch
+import pickle
+device = "cuda" if torch.cuda.is_available() else "cpu"
+import pickle
+import os
+def pca_process(x):
+ a = x.reshape(15, 30, 3)
+ # a = pca.mean_.reshape(15,30,3)
+ tmp = a[:, :15] + a[:, 15:][:, ::-1]
+ a[:, :15] = tmp / 2
+ a[:, 15:] = a[:, :15][:, ::-1]
+ return a.flatten()
+class AudioModel:
+ def __init__(self):
+ self.__net = None
+ self.__fbank = None
+ self.__fbank_processed_index = 0
+ self.frame_index = 0
+
+ current_dir = os.path.dirname(os.path.abspath(__file__))
+ Path_output_pkl = os.path.join(current_dir, "../data/pca.pkl")
+ with open(Path_output_pkl, "rb") as f:
+ pca = pickle.load(f)
+ self.pca_mean_ = pca_process(pca.mean_)
+ self.pca_components_ = np.zeros_like(pca.components_)
+ self.pca_components_[0] = pca_process(pca.components_[0])
+ self.pca_components_[1] = pca_process(pca.components_[1])
+ self.pca_components_[2] = pca_process(pca.components_[2])
+ self.pca_components_[3] = pca_process(pca.components_[3])
+ self.pca_components_[4] = pca_process(pca.components_[4])
+ self.pca_components_[5] = pca_process(pca.components_[5])
+
+ self.reset()
+
+ def loadModel(self, ckpt_path):
+ # if method == "lstm":
+ # ckpt_path = 'checkpoint/lstm/lstm_model_epoch_560.pth'
+ # Audio2FeatureModel = torch.load(model_path).to(device)
+ # Audio2FeatureModel.eval()
+ from talkingface.models.audio2bs_lstm import Audio2Feature
+ self.__net = Audio2Feature() # 调用模型Model
+ self.__net.load_state_dict(torch.load(ckpt_path))
+ self.__net = self.__net.to(device)
+ self.__net.eval()
+
+ def reset(self):
+ opts = knf.FbankOptions()
+ opts.frame_opts.dither = 0
+ opts.frame_opts.frame_length_ms = 50
+ opts.frame_opts.frame_shift_ms = 20
+ opts.mel_opts.num_bins = 80
+ opts.frame_opts.snip_edges = False
+ opts.mel_opts.debug_mel = False
+ self.__fbank = knf.OnlineFbank(opts)
+
+ self.h0 = torch.zeros(2, 1, 192).to(device)
+ self.c0 = torch.zeros(2, 1, 192).to(device)
+
+ self.__fbank_processed_index = 0
+
+ audio_samples = np.zeros([320])
+ self.__fbank.accept_waveform(16000, audio_samples.tolist())
+
+ def interface_frame(self, audio_samples):
+ # pcm为uint16位数据。 只处理一帧的数据, 16000/25 = 640
+ self.__fbank.accept_waveform(16000, audio_samples.tolist())
+ orig_mel = np.zeros([2, 80])
+
+ orig_mel[0] = self.__fbank.get_frame(self.__fbank_processed_index)
+ orig_mel[1] = self.__fbank.get_frame(self.__fbank_processed_index + 1)
+
+ input = torch.from_numpy(orig_mel).unsqueeze(0).float().to(device)
+ bs_array, self.h0, self.c0 = self.__net(input, self.h0, self.c0)
+ bs_array = bs_array[0].detach().cpu().float().numpy()
+ bs_real = bs_array[0]
+ # print(self.__fbank_processed_index, self.__fbank.num_frames_ready, bs_real)
+
+ frame = np.dot(bs_real[:6], self.pca_components_[:6]) + self.pca_mean_
+ # print(frame_index, frame.shape)
+ frame = frame.reshape(15, 30, 3).clip(0, 255).astype(np.uint8)
+ self.__fbank_processed_index += 2
+ return frame
+
+ def interface_wav(self, wavpath):
+ rate, wav = wavfile.read(wavpath, mmap=False)
+ augmented_samples = wav
+ augmented_samples2 = augmented_samples.astype(np.float32, order='C') / 32768.0
+ # print(augmented_samples2.shape, augmented_samples2.shape[0] / 16000)
+
+ opts = knf.FbankOptions()
+ opts.frame_opts.dither = 0
+ opts.frame_opts.frame_length_ms = 50
+ opts.frame_opts.frame_shift_ms = 20
+ opts.mel_opts.num_bins = 80
+ opts.frame_opts.snip_edges = False
+ opts.mel_opts.debug_mel = False
+ fbank = knf.OnlineFbank(opts)
+ fbank.accept_waveform(16000, augmented_samples2.tolist())
+ seq_len = fbank.num_frames_ready // 2
+ A2Lsamples = np.zeros([2 * seq_len, 80])
+ for i in range(2 * seq_len):
+ f2 = fbank.get_frame(i)
+ A2Lsamples[i] = f2
+
+ orig_mel = A2Lsamples
+ # print(orig_mel.shape)
+ input = torch.from_numpy(orig_mel).unsqueeze(0).float().to(device)
+ # print(input.shape)
+ h0 = torch.zeros(2, 1, 192).to(device)
+ c0 = torch.zeros(2, 1, 192).to(device)
+ bs_array, hn, cn = self.__net(input, h0, c0)
+ bs_array = bs_array[0].detach().cpu().float().numpy()
+ bs_array = bs_array[4:]
+
+ frame_num = len(bs_array)
+ output = np.zeros([frame_num, 15, 30, 3], dtype = np.uint8)
+ for frame_index in range(frame_num):
+ bs_real = bs_array[frame_index]
+ # bs_real[1:4] = - bs_real[1:4]
+ frame = np.dot(bs_real[:6], self.pca_components_[:6]) + self.pca_mean_
+ # print(frame_index, frame.shape)
+ frame = frame.reshape(15, 30, 3).clip(0, 255).astype(np.uint8)
+ output[frame_index] = frame
+
+ return output
\ No newline at end of file
diff --git a/talkingface/config/config.py b/talkingface/config/config.py
new file mode 100644
index 0000000..401aa40
--- /dev/null
+++ b/talkingface/config/config.py
@@ -0,0 +1,110 @@
+import argparse
+
+class DataProcessingOptions():
+ def __init__(self):
+ self.parser = argparse.ArgumentParser()
+
+ def parse_args(self):
+ self.parser.add_argument('--extract_video_frame', action='store_true', help='extract video frame')
+ self.parser.add_argument('--extract_audio', action='store_true', help='extract audio files from videos')
+ self.parser.add_argument('--extract_deep_speech', action='store_true', help='extract deep speech features')
+ self.parser.add_argument('--crop_face', action='store_true', help='crop face')
+ self.parser.add_argument('--generate_training_json', action='store_true', help='generate training json file')
+
+ self.parser.add_argument('--source_video_dir', type=str, default="./asserts/training_data/split_video_25fps",
+ help='path of source video in 25 fps')
+ self.parser.add_argument('--openface_landmark_dir', type=str, default="./asserts/training_data/split_video_25fps_landmark_openface",
+ help='path of openface landmark dir')
+ self.parser.add_argument('--video_frame_dir', type=str, default="./asserts/training_data/split_video_25fps_frame",
+ help='path of video frames')
+ self.parser.add_argument('--audio_dir', type=str, default="./asserts/training_data/split_video_25fps_audio",
+ help='path of audios')
+ self.parser.add_argument('--deep_speech_dir', type=str, default="./asserts/training_data/split_video_25fps_deepspeech",
+ help='path of deep speech')
+ self.parser.add_argument('--crop_face_dir', type=str, default="./asserts/training_data/split_video_25fps_crop_face",
+ help='path of crop face dir')
+ self.parser.add_argument('--json_path', type=str, default="./asserts/training_data/training_json.json",
+ help='path of training json')
+ self.parser.add_argument('--clip_length', type=int, default=9, help='clip length')
+ self.parser.add_argument('--deep_speech_model', type=str, default="./asserts/output_graph.pb",
+ help='path of pretrained deepspeech model')
+ return self.parser.parse_args()
+
+class DINetTrainingOptions():
+ def __init__(self):
+ self.parser = argparse.ArgumentParser()
+
+ def parse_args(self):
+ self.parser.add_argument('--seed', type=int, default=456, help='random seed to use.')
+ self.parser.add_argument('--source_channel', type=int, default=3, help='input source image channels')
+ self.parser.add_argument('--ref_channel', type=int, default=15, help='input reference image channels')
+ self.parser.add_argument('--audio_channel', type=int, default=29, help='input audio channels')
+ self.parser.add_argument('--augment_num', type=int, default=32, help='augment training data')
+ self.parser.add_argument('--mouth_region_size', type=int, default=64, help='augment training data')
+ self.parser.add_argument('--train_data', type=str, default=r"./asserts/training_data/training_json.json",
+ help='path of training json')
+ self.parser.add_argument('--batch_size', type=int, default=24, help='training batch size')
+ self.parser.add_argument('--lamb_perception', type=int, default=10, help='weight of perception loss')
+ self.parser.add_argument('--lamb_syncnet_perception', type=int, default=0.1, help='weight of perception loss')
+ self.parser.add_argument('--lr_g', type=float, default=0.00008, help='initial learning rate for adam')
+ self.parser.add_argument('--lr_d', type=float, default=0.00008, help='initial learning rate for adam')
+ self.parser.add_argument('--start_epoch', default=1, type=int, help='start epoch in training stage')
+ self.parser.add_argument('--non_decay', default=10, type=int, help='num of epoches with fixed learning rate')
+ self.parser.add_argument('--decay', default=30, type=int, help='num of linearly decay epochs')
+ self.parser.add_argument('--checkpoint', type=int, default=2, help='num of checkpoints in training stage')
+ self.parser.add_argument('--result_path', type=str, default=r"./asserts/training_model_weight/frame_training_64",
+ help='result path to save model')
+ self.parser.add_argument('--coarse2fine', action='store_true', help='If true, load pretrained model path.')
+ self.parser.add_argument('--coarse_model_path',
+ default='',
+ type=str,
+ help='Save data (.pth) of previous training')
+ self.parser.add_argument('--pretrained_syncnet_path',
+ default='',
+ type=str,
+ help='Save data (.pth) of pretrained syncnet')
+ self.parser.add_argument('--pretrained_frame_DINet_path',
+ default='',
+ type=str,
+ help='Save data (.pth) of frame trained DINet')
+ # ========================= Discriminator ==========================
+ self.parser.add_argument('--D_num_blocks', type=int, default=4, help='num of down blocks in discriminator')
+ self.parser.add_argument('--D_block_expansion', type=int, default=64, help='block expansion in discriminator')
+ self.parser.add_argument('--D_max_features', type=int, default=256, help='max channels in discriminator')
+ return self.parser.parse_args()
+
+
+class DINetInferenceOptions():
+ def __init__(self):
+ self.parser = argparse.ArgumentParser()
+
+ def parse_args(self):
+ self.parser.add_argument('--source_channel', type=int, default=3, help='channels of source image')
+ self.parser.add_argument('--ref_channel', type=int, default=15, help='channels of reference image')
+ self.parser.add_argument('--audio_channel', type=int, default=29, help='channels of audio feature')
+ self.parser.add_argument('--mouth_region_size', type=int, default=256, help='help to resize window')
+ self.parser.add_argument('--source_video_path',
+ default='./asserts/examples/test4.mp4',
+ type=str,
+ help='path of source video')
+ self.parser.add_argument('--source_openface_landmark_path',
+ default='./asserts/examples/test4.csv',
+ type=str,
+ help='path of detected openface landmark')
+ self.parser.add_argument('--driving_audio_path',
+ default='./asserts/examples/driving_audio_1.wav',
+ type=str,
+ help='path of driving audio')
+ self.parser.add_argument('--pretrained_clip_DINet_path',
+ default='./asserts/clip_training_DINet_256mouth.pth',
+ type=str,
+ help='pretrained model of DINet(clip trained)')
+ self.parser.add_argument('--deepspeech_model_path',
+ default='./asserts/output_graph.pb',
+ type=str,
+ help='path of deepspeech model')
+ self.parser.add_argument('--res_video_dir',
+ default='./asserts/inference_result',
+ type=str,
+ help='path of generated videos')
+ return self.parser.parse_args()
\ No newline at end of file
diff --git a/talkingface/data/DHLive_mini_dataset.py b/talkingface/data/DHLive_mini_dataset.py
new file mode 100644
index 0000000..6d895cf
--- /dev/null
+++ b/talkingface/data/DHLive_mini_dataset.py
@@ -0,0 +1,202 @@
+import numpy as np
+import cv2
+import tqdm
+import copy
+from talkingface.utils import *
+import glob
+import pickle
+import torch
+import torch.utils.data as data
+
+model_size = (256, 256)
+
+def get_image(A_path, crop_coords, input_type, resize= (256, 256)):
+ (x_min, y_min, x_max, y_max) = crop_coords
+ size = (x_max - x_min, y_max - y_min)
+
+ if input_type == 'mediapipe':
+ pose_pts = (A_path - np.array([x_min, y_min])) * resize / size
+ return pose_pts[:, :2]
+ else:
+ img_output = A_path[y_min:y_max, x_min:x_max, :]
+ img_output = cv2.resize(img_output, resize)
+ return img_output
+def generate_input(img, keypoints, is_train = False, mode=["mouth_bias"]):
+ # 根据关键点决定正方形裁剪区域
+ crop_coords = crop_mouth(keypoints, img.shape[1], img.shape[0], is_train=is_train)
+ target_keypoints = get_image(keypoints[:,:2], crop_coords, input_type='mediapipe', resize = model_size)
+ target_img = get_image(img, crop_coords, input_type='img', resize = model_size)
+
+ source_img = copy.deepcopy(target_img)
+ source_keypoints = target_keypoints
+
+ source_face_egde = draw_mouth_maps(source_keypoints, im_edges = source_img)
+ return source_img,target_img,crop_coords
+
+def generate_ref(img, keypoints, is_train=False, alpha = None, beta = None):
+ crop_coords = crop_mouth(keypoints, img.shape[1], img.shape[0], is_train=is_train)
+ ref_keypoints = get_image(keypoints, crop_coords, input_type='mediapipe', resize = model_size)
+ ref_img = get_image(img, crop_coords, input_type='img', resize = model_size)
+
+ ref_face_edge = draw_mouth_maps(ref_keypoints, size = model_size)
+ ref_img = np.concatenate([ref_img, ref_face_edge[:,:,:1]], axis=2)
+ return ref_img
+
+def select_ref_index(driven_keypoints, n_ref = 5, ratio = 1/3., ratio2 = 1):
+ # 根据嘴巴开合程度,选取开合最大的那一半
+ lips_distance = np.linalg.norm(
+ driven_keypoints[:, INDEX_LIPS_INNER[5]] - driven_keypoints[:, INDEX_LIPS_INNER[-5]], axis=1)
+ selected_index_list = np.argsort(lips_distance).tolist()[int(len(lips_distance) * ratio): int(len(lips_distance) * ratio2)]
+ ref_img_index_list = random.sample(selected_index_list, n_ref) # 从当前视频选n_ref个图片
+ return ref_img_index_list
+
+def get_ref_images_fromVideo(cap, ref_img_index_list, ref_keypoints):
+ ref_img_list = []
+ for index in ref_img_index_list:
+ cap.set(cv2.CAP_PROP_POS_FRAMES, index) # 设置要获取的帧号
+ ret, frame = cap.read()
+ frame = frame[:,:,::-1]
+ if ret is False:
+ print("请检查当前视频, 错误帧数:", index)
+ ref_img = generate_ref(frame, ref_keypoints[index])
+ ref_img_list.append(ref_img)
+ ref_img = np.concatenate(ref_img_list, axis=2)
+ return ref_img
+
+
+
+
+class Few_Shot_Dataset(data.Dataset):
+ def __init__(self, dict_info, n_ref = 2, is_train = False):
+ super(Few_Shot_Dataset, self).__init__()
+ self.driven_images = dict_info["driven_images"]
+ self.driven_keypoints = dict_info["driven_keypoints"]
+ self.driving_keypoints = dict_info["driving_keypoints"]
+
+ self.driven_teeth_images = dict_info["driven_teeth_image"]
+ self.driven_teeth_rect = dict_info["driven_teeth_rect"]
+ self.is_train = is_train
+
+ assert len(self.driven_images) == len(self.driven_keypoints)
+ assert len(self.driven_images) == len(self.driving_keypoints)
+
+ self.out_size = (256, 256)
+
+ self.sample_num = np.sum([len(i) for i in self.driven_images])
+
+ # list: 每个视频序列的视频块个数
+ self.clip_count_list = [] # number of frames in each sequence
+ for path in self.driven_images:
+ self.clip_count_list.append(len(path))
+ self.n_ref = n_ref
+
+ def get_ref_images(self, video_index, ref_img_index_list):
+ # 参考图片
+ ref_img_list = []
+ for ref_img_index in ref_img_index_list:
+ ref_img = cv2.imread(self.driven_images[video_index][ref_img_index])[:, :, ::-1]
+ # ref_img = cv2.convertScaleAbs(ref_img, alpha=self.alpha, beta=self.beta)
+ ref_keypoints = self.driven_keypoints[video_index][ref_img_index]
+ ref_img = generate_ref(ref_img, ref_keypoints, self.is_train)
+
+ ref_img_list.append(ref_img)
+ self.ref_img = np.concatenate(ref_img_list, axis=2)
+
+ def __getitem__(self, index):
+ if self.is_train:
+ video_index = random.randint(0, len(self.driven_images) - 1)
+ current_clip = random.randint(0, self.clip_count_list[video_index] - 1)
+
+ ref_img_index_list = select_ref_index(self.driven_keypoints[video_index], n_ref = self.n_ref, ratio = 0.33) # 从当前视频选n_ref个图片
+
+ self.get_ref_images(video_index, ref_img_index_list)
+ else:
+ video_index = 0
+ current_clip = index
+
+ if index == 0:
+ ref_img_index_list = select_ref_index(self.driven_keypoints[video_index], n_ref=self.n_ref) # 从当前视频选n_ref个图片
+ self.get_ref_images(video_index, ref_img_index_list)
+
+ # target图片
+ target_img = cv2.imread(self.driven_images[video_index][current_clip])[:, :, ::-1]
+ # target_img = cv2.convertScaleAbs(target_img, alpha=self.alpha, beta=self.beta)
+ ref_face_edge = np.zeros_like(target_img)
+ target_keypoints = self.driving_keypoints[video_index][current_clip]
+ source_img, target_img,crop_coords = generate_input(target_img, target_keypoints, self.is_train, mode="mouth")
+
+
+ [x_min, y_min, x_max, y_max] = self.driven_teeth_rect[video_index][current_clip]
+ teeth_img = cv2.imread(self.driven_teeth_images[video_index][current_clip])
+ # print(ref_face_edge.shape, crop_coords, [x_min, y_min, x_max, y_max])
+ ref_face_edge[int(y_min):int(y_max), int(x_min):int(x_max), 1][
+ np.where(teeth_img[:, teeth_img.shape[1] // 2:, 0] == 0)] = 255
+ ref_face_edge[int(y_min):int(y_max), int(x_min):int(x_max), 2][
+ np.where(teeth_img[:, teeth_img.shape[1] // 2:, 0] == 255)] = 255
+
+
+ # cv2.imshow("s", ref_face_edge)
+ # cv2.waitKey(-1)
+ # print(ref_face_edge.shape, crop_coords)
+ teeth_img = get_image(ref_face_edge, crop_coords, input_type='img', resize = model_size)
+
+
+ source_img[:,:,1][np.where(source_img[:,:,0] == 0)] = teeth_img[:,:,1][np.where(source_img[:,:,0] == 0)]
+ source_img[:, :, 2][np.where(source_img[:, :, 0] == 0)] = teeth_img[:, :, 2][np.where(source_img[:, :, 0] == 0)]
+
+ target_img = cv2.resize(target_img, (128, 128))
+ source_img = cv2.resize(source_img, (128, 128))
+ self.ref_img = cv2.resize(self.ref_img, (128, 128))
+
+
+ w_pad = int((128 - 72) / 2)
+ h_pad = int((128 - 56) / 2)
+
+ target_img = target_img[h_pad:-h_pad, w_pad:-w_pad]/255.
+ source_img = source_img[h_pad:-h_pad, w_pad:-w_pad]/255.
+ ref_img = self.ref_img[h_pad:-h_pad, w_pad:-w_pad]/255.
+
+ # tensor
+ source_tensor = torch.from_numpy(source_img).float().permute(2, 0, 1)
+ ref_tensor = torch.from_numpy(ref_img).float().permute(2, 0, 1)
+ target_tensor = torch.from_numpy(target_img).float().permute(2, 0, 1)
+ return source_tensor, ref_tensor, target_tensor, self.driven_images[video_index][current_clip]
+
+ def __len__(self):
+ if self.is_train:
+ return len(self.driven_images)
+ else:
+ return len(self.driven_images[0])
+ # return self.sample_num
+def data_preparation(train_video_list):
+ img_all = []
+ keypoints_all = []
+ teeth_img_all = []
+ teeth_rect_all = []
+ for i in tqdm.tqdm(train_video_list):
+ # for i in ["xiaochangzhang/00004"]:
+ model_name = i
+ img_filelist = glob.glob("{}/image/*.png".format(model_name))
+ img_filelist.sort()
+ if len(img_filelist) == 0:
+ continue
+ img_all.append(img_filelist)
+ img_teeth_filelist = glob.glob("{}/teeth_seg/*.png".format(model_name))
+ img_teeth_filelist.sort()
+ teeth_img_all.append(img_teeth_filelist)
+
+ teeth_rect_array = np.loadtxt("{}/teeth_seg/all.txt".format(model_name))
+ teeth_rect_all.append(teeth_rect_array)
+ Path_output_pkl = "{}/keypoint_rotate.pkl".format(model_name)
+ with open(Path_output_pkl, "rb") as f:
+ images_info = pickle.load(f)
+ keypoints_all.append(images_info[:, main_keypoints_index, :2])
+
+ print("train size: ", len(img_all))
+ dict_info = {}
+ dict_info["driven_images"] = img_all
+ dict_info["driven_keypoints"] = keypoints_all
+ dict_info["driving_keypoints"] = keypoints_all
+ dict_info["driven_teeth_rect"] = teeth_rect_all
+ dict_info["driven_teeth_image"] = teeth_img_all
+ return dict_info
diff --git a/talkingface/data/__init__.py b/talkingface/data/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/talkingface/data/dataset_wav.py b/talkingface/data/dataset_wav.py
new file mode 100644
index 0000000..b32f1df
--- /dev/null
+++ b/talkingface/data/dataset_wav.py
@@ -0,0 +1,104 @@
+import torch
+import torch.utils.data as data
+import numpy as np
+from audiomentations import Compose, AddGaussianNoise, TimeStretch, PitchShift, Shift, PolarityInversion
+# from audio import melspectrogram,mel_bar
+import kaldi_native_fbank as knf
+import random
+
+
+
+class AudioVisualDataset(data.Dataset):
+ """ audio-visual dataset. currently, return 2D info and 3D tracking info.
+
+ '''
+ 多个片段的APC语音特征和嘴部顶点的PCA信息
+ :param audio_features: list
+ :param mouth_features: list
+ '''
+
+ """
+
+ def __init__(self, audio_features, mouth_features, is_train = True, seq_len = 9):
+ super(AudioVisualDataset, self).__init__()
+
+ self.fps = 25
+ # 每0.2s一个序列
+ # self.seq_len = int(self.fps /5)
+ self.seq_len = seq_len
+ self.frame_jump_stride = 2
+ self.audio_features = audio_features
+ self.bs_features = mouth_features
+ self.is_train = is_train
+
+ self.augment = Compose([
+ AddGaussianNoise(min_amplitude=0.001, max_amplitude=0.015, p=0.5),
+ # TimeStretch(min_rate=0.8, max_rate=1.25, p=0.5),
+ PolarityInversion(p=0.5),
+ PitchShift(min_semitones=-4, max_semitones=4, p=0.5),
+ # Shift(min_fraction=-0.5, max_fraction=0.5, p=0.5),
+ ])
+
+
+ # 每个序列的裁剪片段个数
+ self.clip_num = []
+ for i in range(len(audio_features)):
+ audio_frame_num = int(len(self.audio_features[i])/(16000/25)) - 2
+ self.clip_num.append(min(len(self.bs_features[i]), audio_frame_num) - self.seq_len + 1)
+
+ def __getitem__(self, index):
+ if self.is_train:
+ video_index = random.randint(0, len(self.bs_features) - 1)
+ # print(video_index, self.clip_num[video_index])
+ clips_index = random.sample(range(self.clip_num[video_index]), 1) # 从当前视频选1个片段
+ current_frame = clips_index[0]
+ else:
+ video_index = 0
+ # video_index = 0
+ # for i in range(len(self.clip_num)):
+ # if index < np.sum(self.clip_num[:i+1]):
+ # video_index = i
+ # break
+ # current_frame = index - np.sum(self.clip_num[:video_index], dtype=int)
+ # print(video_index, current_frame, current_frame + self.seq_len, self.clip_num, self.bs_features[video_index].shape)
+
+ # start point is current frame
+ A2Lsamples = self.audio_features[video_index][current_frame*640: (current_frame + self.seq_len + 2)*640]
+ # A2Lsamples = copy.deepcopy(A2Lsamples_)
+ # print("A2Lsamples: ", A2Lsamples.shape, A2Lsamples.dtype, A2Lsamples.__class__)
+ augmented_samples = self.augment(np.array(A2Lsamples, dtype=np.float32), sample_rate=16000)
+ # print(augmented_samples.shape, augmented_samples.dtype)
+ # int16转换为float格式
+ augmented_samples2 = augmented_samples.astype(np.float32, order='C') / 32768.0
+ # orig_mel = mel_bar(augmented_samples2)
+ # orig_mel = melspectrogram(augmented_samples2).T
+ opts = knf.FbankOptions()
+ opts.frame_opts.dither = 0
+ opts.frame_opts.frame_length_ms = 50
+ opts.frame_opts.frame_shift_ms = 20
+ opts.mel_opts.num_bins = 80
+ opts.frame_opts.snip_edges = False
+ opts.mel_opts.debug_mel = False
+ fbank = knf.OnlineFbank(opts)
+ fbank.accept_waveform(16000, augmented_samples2.tolist())
+ A2Lsamples = np.zeros([2*self.seq_len, 80])
+ for i in range(2*self.seq_len):
+ f2 = fbank.get_frame(i)
+ A2Lsamples[i] = f2
+ fbank.input_finished()
+
+ target_bs = self.bs_features[video_index][current_frame: current_frame + self.seq_len, :].reshape(
+ self.seq_len, -1)
+
+ # target_bs = self.bs_features[video_index][current_frame + self.seq_len//2, :]
+
+ A2Lsamples = torch.from_numpy(A2Lsamples).float()
+ target_bs = torch.from_numpy(target_bs).float()
+ # print("*****", A2Lsamples.size(), target_bs.size(), len(self.clip_num))
+
+ return [A2Lsamples, target_bs]
+
+ def __len__(self):
+ return len(self.clip_num)
+ # return np.sum(self.clip_num, dtype = int)
+ # return 10000
\ No newline at end of file
diff --git a/talkingface/data/face_mask.py b/talkingface/data/face_mask.py
new file mode 100644
index 0000000..8777ed7
--- /dev/null
+++ b/talkingface/data/face_mask.py
@@ -0,0 +1,66 @@
+import os
+os.environ["KMP_DUPLICATE_LIB_OK"] = "true"
+import pickle
+import cv2
+import numpy as np
+import os
+import glob
+from talkingface.util.smooth import smooth_array
+from talkingface.run_utils import calc_face_mat
+import tqdm
+from talkingface.utils import *
+
+path_ = r"../../../preparation_mix"
+video_list = [os.path.join(path_, i) for i in os.listdir(path_)]
+path_ = r"../../../preparation_hdtf"
+video_list += [os.path.join(path_, i) for i in os.listdir(path_)]
+path_ = r"../../../preparation_vfhq"
+video_list += [os.path.join(path_, i) for i in os.listdir(path_)]
+path_ = r"../../../preparation_bilibili"
+video_list += [os.path.join(path_, i) for i in os.listdir(path_)]
+print(video_list)
+video_list = video_list[:]
+img_all = []
+keypoints_all = []
+point_size = 1
+point_color = (0, 0, 255) # BGR
+thickness = 4 # 0 、4、8
+for path_ in tqdm.tqdm(video_list):
+ img_filelist = glob.glob("{}/image/*.png".format(path_))
+ img_filelist.sort()
+ if len(img_filelist) == 0:
+ continue
+ img_all.append(img_filelist)
+
+ Path_output_pkl = "{}/keypoint_rotate.pkl".format(path_)
+
+ with open(Path_output_pkl, "rb") as f:
+ images_info = pickle.load(f)[:, main_keypoints_index, :]
+ pts_driven = images_info.reshape(len(images_info), -1)
+ pts_driven = smooth_array(pts_driven).reshape(len(pts_driven), -1, 3)
+
+ face_pts_mean = np.loadtxt(r"data\face_pts_mean_mainKps.txt")
+ mat_list,pts_normalized_list,face_pts_mean_personal = calc_face_mat(pts_driven, face_pts_mean)
+ pts_normalized_list = np.array(pts_normalized_list)
+ # print(face_pts_mean_personal[INDEX_FACE_OVAL[:10], 1])
+ # print(np.max(pts_normalized_list[:,INDEX_FACE_OVAL[:10], 1], axis = 1))
+ face_pts_mean_personal[INDEX_FACE_OVAL[:10], 1] = np.max(pts_normalized_list[:,INDEX_FACE_OVAL[:10], 1], axis = 0) + np.arange(5,25,2)
+ face_pts_mean_personal[INDEX_FACE_OVAL[:10], 0] = np.max(pts_normalized_list[:, INDEX_FACE_OVAL[:10], 0], axis=0) - (9 - np.arange(0,10))
+ face_pts_mean_personal[INDEX_FACE_OVAL[-10:], 1] = np.max(pts_normalized_list[:, INDEX_FACE_OVAL[-10:], 1], axis=0) - np.arange(5,25,2) + 28
+ face_pts_mean_personal[INDEX_FACE_OVAL[-10:], 0] = np.min(pts_normalized_list[:, INDEX_FACE_OVAL[-10:], 0], axis=0) + np.arange(0,10)
+
+ face_pts_mean_personal[INDEX_FACE_OVAL[10], 1] = np.max(pts_normalized_list[:, INDEX_FACE_OVAL[10], 1], axis=0) + 25
+
+ # for keypoints_normalized in pts_normalized_list:
+ # img = np.zeros([1000,1000,3], dtype=np.uint8)
+ # for coor in face_pts_mean_personal:
+ # # coor = (coor +1 )/2.
+ # cv2.circle(img, (int(coor[0]), int(coor[1])), point_size, (255, 0, 0), thickness)
+ # for coor in keypoints_normalized:
+ # # coor = (coor +1 )/2.
+ # cv2.circle(img, (int(coor[0]), int(coor[1])), point_size, point_color, thickness)
+ # cv2.imshow("a", img)
+ # cv2.waitKey(30)
+
+ with open("{}/face_mat_mask20240722.pkl".format(path_), "wb") as f:
+ pickle.dump([mat_list, face_pts_mean_personal], f)
diff --git a/talkingface/data/few_shot_dataset.py b/talkingface/data/few_shot_dataset.py
new file mode 100644
index 0000000..e5aed86
--- /dev/null
+++ b/talkingface/data/few_shot_dataset.py
@@ -0,0 +1,288 @@
+import numpy as np
+import cv2
+import tqdm
+import copy
+from talkingface.utils import *
+import glob
+import pickle
+import torch
+import torch.utils.data as data
+def get_image(A_path, crop_coords, input_type, resize= 256):
+ (x_min, y_min, x_max, y_max) = crop_coords
+ size = (x_max - x_min, y_max - y_min)
+
+ if input_type == 'mediapipe':
+ if A_path.shape[1] == 2:
+ pose_pts = (A_path - np.array([x_min, y_min])) * resize / size
+ return pose_pts[:, :2]
+ else:
+ A_path[:, 2] = A_path[:, 2] - np.max(A_path[:, 2])
+ pose_pts = (A_path - np.array([x_min, y_min, 0])) * resize / size[0]
+ return pose_pts[:, :3]
+
+ else:
+ img_output = A_path[y_min:y_max, x_min:x_max, :]
+ img_output = cv2.resize(img_output, (resize, resize))
+ return img_output
+def generate_input(img, keypoints, mask_keypoints, is_train = False, mode=["mouth_bias"], mouth_width = None, mouth_height = None):
+ # 根据关键点决定正方形裁剪区域
+ crop_coords = crop_face(keypoints, size=img.shape[:2], is_train=is_train)
+ target_keypoints = get_image(keypoints[:,:2], crop_coords, input_type='mediapipe')
+ target_img = get_image(img, crop_coords, input_type='img')
+
+ target_mask_keypoints = get_image(mask_keypoints[:,:2], crop_coords, input_type='mediapipe')
+
+ # source_img信息:扣出嘴部区域
+ source_img = copy.deepcopy(target_img)
+ source_keypoints = target_keypoints
+
+ pts = source_keypoints.copy()
+
+ face_edge_start_index = 2
+
+ pts[INDEX_FACE_OVAL[face_edge_start_index:-face_edge_start_index], 1] = target_mask_keypoints[face_edge_start_index:-face_edge_start_index, 1]
+
+ # pts = pts[INDEX_FACE_OVAL[face_edge_start_index:-face_edge_start_index] + INDEX_NOSE_EDGE[::-1], :2]
+ pts = pts[FACE_MASK_INDEX + INDEX_NOSE_EDGE[::-1], :2]
+
+ pts = pts.reshape((-1, 1, 2)).astype(np.int32)
+ cv2.fillPoly(source_img, [pts], color=(0, 0, 0))
+ source_face_egde = draw_face_feature_maps(source_keypoints, mode=mode, im_edges=target_img,
+ mouth_width = mouth_width * (256/(crop_coords[2] - crop_coords[0])), mouth_height = mouth_height * (256/(crop_coords[2] - crop_coords[0])))
+ source_img = np.concatenate([source_img, source_face_egde], axis=2)
+ return source_img,target_img,crop_coords
+
+def generate_ref(img, keypoints, is_train=False, alpha = None, beta = None):
+ crop_coords = crop_face(keypoints, size=img.shape[:2], is_train=is_train)
+ ref_keypoints = get_image(keypoints, crop_coords, input_type='mediapipe')
+ ref_img = get_image(img, crop_coords, input_type='img')
+
+ if beta is not None:
+ if alpha:
+ ref_img[:, :, :3] = cv2.add(ref_img[:, :, :3], beta)
+ else:
+ ref_img[:, :, :3] = cv2.subtract(ref_img[:, :, :3], beta)
+ ref_face_edge = draw_face_feature_maps(ref_keypoints, mode=["mouth", "nose", "eye", "oval_all","muscle"])
+ ref_img = np.concatenate([ref_img, ref_face_edge], axis=2)
+ return ref_img
+
+def select_ref_index(driven_keypoints, n_ref = 5, ratio = 1/3.):
+ # 根据嘴巴开合程度,选取开合最大的那一半
+ lips_distance = np.linalg.norm(
+ driven_keypoints[:, INDEX_LIPS_INNER[5]] - driven_keypoints[:, INDEX_LIPS_INNER[-5]], axis=1)
+ selected_index_list = np.argsort(lips_distance).tolist()[int(len(lips_distance) * ratio):]
+ ref_img_index_list = random.sample(selected_index_list, n_ref) # 从当前视频选n_ref个图片
+ return ref_img_index_list
+
+def get_ref_images_fromVideo(cap, ref_img_index_list, ref_keypoints):
+ ref_img_list = []
+ for index in ref_img_index_list:
+ cap.set(cv2.CAP_PROP_POS_FRAMES, index) # 设置要获取的帧号
+ ret, frame = cap.read()
+ if ret is False:
+ print("请检查当前视频, 错误帧数:", index)
+ ref_img = generate_ref(frame, ref_keypoints[index])
+ ref_img_list.append(ref_img)
+ ref_img = np.concatenate(ref_img_list, axis=2)
+ return ref_img
+
+
+
+
+class Few_Shot_Dataset(data.Dataset):
+ def __init__(self, dict_info, n_ref = 2, is_train = False):
+ super(Few_Shot_Dataset, self).__init__()
+ self.driven_images = dict_info["driven_images"]
+ self.driven_keypoints = dict_info["driven_keypoints"]
+ self.driving_keypoints = dict_info["driving_keypoints"]
+ self.driven_mask_keypoints = dict_info["driven_mask_keypoints"]
+ self.is_train = is_train
+
+ assert len(self.driven_images) == len(self.driven_keypoints)
+ assert len(self.driven_images) == len(self.driving_keypoints)
+
+ self.out_size = (256, 256)
+
+ self.sample_num = np.sum([len(i) for i in self.driven_images])
+
+ # list: 每个视频序列的视频块个数
+ self.clip_count_list = [] # number of frames in each sequence
+ for path in self.driven_images:
+ self.clip_count_list.append(len(path))
+ self.n_ref = n_ref
+
+ def get_ref_images(self, video_index, ref_img_index_list):
+ # 参考图片
+ ref_img_list = []
+ for ref_img_index in ref_img_index_list:
+ ref_img = cv2.imread(self.driven_images[video_index][ref_img_index])
+ # ref_img = cv2.convertScaleAbs(ref_img, alpha=self.alpha, beta=self.beta)
+
+
+ ref_keypoints = self.driven_keypoints[video_index][ref_img_index]
+ ref_img = generate_ref(ref_img, ref_keypoints, self.is_train, self.alpha, self.beta)
+
+ ref_img_list.append(ref_img)
+ self.ref_img = np.concatenate(ref_img_list, axis=2)
+
+ def __getitem__(self, index):
+
+ # 调整亮度和对比度
+ # self.alpha = random.uniform(0.8,1.25) # 缩放因子
+ # self.beta = random.uniform(-50,50) # 移位因子
+ # adjusted = cv2.convertScaleAbs(img, alpha=alpha, beta=beta)
+
+ self.alpha = (random.random() > 0.5) # 正负因子
+ self.beta = np.ones([256,256,3]) * np.random.rand(3) * 20 # 色彩调整0-20个色差
+ self.beta = self.beta.astype(np.uint8)
+
+
+ if self.is_train:
+ video_index = random.randint(0, len(self.driven_images) - 1)
+ current_clip = random.randint(0, self.clip_count_list[video_index] - 1)
+ ref_img_index_list = select_ref_index(self.driven_keypoints[video_index], n_ref = self.n_ref) # 从当前视频选n_ref个图片
+ self.get_ref_images(video_index, ref_img_index_list)
+ else:
+ video_index = 0
+ current_clip = index
+
+ if index == 0:
+ ref_img_index_list = select_ref_index(self.driven_keypoints[video_index], n_ref=self.n_ref5) # 从当前视频选n_ref个图片
+ self.get_ref_images(video_index, ref_img_index_list)
+
+ # target图片
+ target_img = cv2.imread(self.driven_images[video_index][current_clip])
+ # target_img = cv2.convertScaleAbs(target_img, alpha=self.alpha, beta=self.beta)
+
+ target_keypoints = self.driving_keypoints[video_index][current_clip]
+ target_mask_keypoints = self.driven_mask_keypoints[video_index][current_clip]
+
+ mouth_rect = self.driving_keypoints[video_index][:, INDEX_LIPS].max(axis=1) - self.driving_keypoints[video_index][:, INDEX_LIPS].min(axis=1)
+ mouth_width = mouth_rect[:, 0].max()
+ mouth_height = mouth_rect[:, 1].max()
+
+ # source_img, target_img,crop_coords = generate_input(target_img, target_keypoints, target_mask_keypoints, self.is_train)
+ source_img, target_img,crop_coords = generate_input(target_img, target_keypoints, target_mask_keypoints, self.is_train, mode=["mouth_bias", "nose", "eye"],
+ mouth_width = mouth_width, mouth_height = mouth_height)
+
+ target_img = target_img/255.
+ source_img = source_img/255.
+ ref_img = self.ref_img / 255.
+
+ # tensor
+ source_tensor = torch.from_numpy(source_img).float().permute(2, 0, 1)
+ ref_tensor = torch.from_numpy(ref_img).float().permute(2, 0, 1)
+ target_tensor = torch.from_numpy(target_img).float().permute(2, 0, 1)
+ return source_tensor, ref_tensor, target_tensor
+
+ def __len__(self):
+ if self.is_train:
+ return len(self.driven_images)
+ else:
+ return len(self.driven_images[0])
+ # return self.sample_num
+def data_preparation(train_video_list):
+ img_all = []
+ keypoints_all = []
+ mask_all = []
+ point_size = 1
+ point_color = (0, 0, 255) # BGR
+ thickness = 4 # 0 、4、8
+ for i in tqdm.tqdm(train_video_list):
+ # for i in ["xiaochangzhang/00004"]:
+ model_name = i
+ img_filelist = glob.glob("{}/image/*.png".format(model_name))
+ img_filelist.sort()
+ if len(img_filelist) == 0:
+ continue
+ img_all.append(img_filelist)
+
+ Path_output_pkl = "{}/keypoint_rotate.pkl".format(model_name)
+ with open(Path_output_pkl, "rb") as f:
+ images_info = pickle.load(f)
+ keypoints_all.append(images_info[:, main_keypoints_index, :2])
+
+ Path_output_pkl = "{}/face_mat_mask.pkl".format(model_name)
+ with open(Path_output_pkl, "rb") as f:
+ mat_list, face_pts_mean_personal = pickle.load(f)
+
+ face_pts_mean_personal = face_pts_mean_personal[INDEX_FACE_OVAL]
+ face_mask_pts = np.zeros([len(mat_list), len(face_pts_mean_personal), 2])
+ for index_ in range(len(mat_list)):
+ # img = np.zeros([1000,1000,3], dtype=np.uint8)
+ # img = cv2.imread(img_filelist[index_])
+
+ rotationMatrix = mat_list[index_]
+
+ keypoints = np.ones([4, len(face_pts_mean_personal)])
+ keypoints[:3, :] = face_pts_mean_personal.T
+ driving_mask = rotationMatrix.dot(keypoints).T
+ face_mask_pts[index_] = driving_mask[:, :2]
+
+
+
+ # for coor in driving_mask:
+ # # coor = (coor +1 )/2.
+ # cv2.circle(img, (int(coor[0]), int(coor[1])), point_size, point_color, thickness)
+ # cv2.imshow("a", img)
+ # cv2.waitKey(30)
+ mask_all.append(face_mask_pts)
+
+ print("train size: ", len(img_all))
+ dict_info = {}
+ dict_info["driven_images"] = img_all
+ dict_info["driven_keypoints"] = keypoints_all
+ dict_info["driving_keypoints"] = keypoints_all
+ dict_info["driven_mask_keypoints"] = mask_all
+ return dict_info
+
+
+def generate_input_pixels(img, keypoints, rotationMatrix, pixels_mouth, mask_keypoints, coords_array):
+ # 根据关键点决定正方形裁剪区域
+ crop_coords = crop_face(keypoints, size=img.shape[:2], is_train=False)
+ target_keypoints = get_image(keypoints[:, :2], crop_coords, input_type='mediapipe')
+
+ # 画出嘴部像素图
+ pixels_mouth_coords = rotationMatrix.dot(coords_array).T
+ pixels_mouth_coords = pixels_mouth_coords[:, :2].astype(int)
+ pixels_mouth_coords = (pixels_mouth_coords[:, 1], pixels_mouth_coords[:, 0])
+
+ source_face_egde = np.zeros_like(img, dtype=np.uint8)
+ # out_frame = img.copy()
+ frame = pixels_mouth.reshape(15, 30, 3).clip(0, 255).astype(np.uint8)
+
+ frame = cv2.resize(cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY), (150, 100))
+ sharpen_image = frame.astype(np.float32)
+ mean_ = int(np.mean(sharpen_image))
+ max_, min_ = mean_ + 60, mean_ - 60
+ sharpen_image = (sharpen_image - min_) / (max_ - min_) * 255.
+ sharpen_image = sharpen_image.clip(0, 255).astype(np.uint8)
+
+ sharpen_image = np.concatenate(
+ [sharpen_image[:, :, np.newaxis], sharpen_image[:, :, np.newaxis], sharpen_image[:, :, np.newaxis]], axis=2)
+ # sharpen_image = cv2.resize(sharpen_image, (150, 100))
+ source_face_egde[pixels_mouth_coords] = sharpen_image.reshape(-1, 3)
+ # cv2.imshow("sharpen_image", source_face_egde)
+ # cv2.waitKey(40)
+
+ source_face_egde = get_image(source_face_egde, crop_coords, input_type='image')
+ source_face_egde = draw_face_feature_maps(target_keypoints, mode = ["nose", "eye"], im_edges=source_face_egde)
+ # cv2.imshow("sharpen_image", source_face_egde)
+ # cv2.waitKey(40)
+
+
+ target_img = get_image(img, crop_coords, input_type='img')
+ target_mask_keypoints = get_image(mask_keypoints[:, :2], crop_coords, input_type='mediapipe')
+ # source_img信息:扣出嘴部区域
+ source_img = copy.deepcopy(target_img)
+ source_keypoints = target_keypoints
+ pts = source_keypoints.copy()
+ face_edge_start_index = 3
+ pts[INDEX_FACE_OVAL[face_edge_start_index:-face_edge_start_index], 1] = target_mask_keypoints[
+ face_edge_start_index:-face_edge_start_index,
+ 1]
+ pts = pts[INDEX_FACE_OVAL[face_edge_start_index:-face_edge_start_index] + INDEX_NOSE_EDGE[::-1], :2]
+ pts = pts.reshape((-1, 1, 2)).astype(np.int32)
+ cv2.fillPoly(source_img, [pts], color=(0, 0, 0))
+ source_img = np.concatenate([source_img, source_face_egde], axis=2)
+ return source_img, target_img, crop_coords
\ No newline at end of file
diff --git a/talkingface/face_pts_mean.txt b/talkingface/face_pts_mean.txt
new file mode 100644
index 0000000..c51c311
--- /dev/null
+++ b/talkingface/face_pts_mean.txt
@@ -0,0 +1,478 @@
+7.010000000000000000e+02 5.450000000000000000e+02 -5.500000000000000000e+01
+7.030000000000000000e+02 4.930000000000000000e+02 -1.010000000000000000e+02
+7.030000000000000000e+02 5.120000000000000000e+02 -5.600000000000000000e+01
+6.900000000000000000e+02 4.300000000000000000e+02 -7.600000000000000000e+01
+7.030000000000000000e+02 4.740000000000000000e+02 -1.070000000000000000e+02
+7.040000000000000000e+02 4.480000000000000000e+02 -9.900000000000000000e+01
+7.060000000000000000e+02 3.870000000000000000e+02 -4.900000000000000000e+01
+5.800000000000000000e+02 3.720000000000000000e+02 2.300000000000000000e+01
+7.070000000000000000e+02 3.380000000000000000e+02 -3.600000000000000000e+01
+7.080000000000000000e+02 3.120000000000000000e+02 -3.900000000000000000e+01
+7.100000000000000000e+02 2.190000000000000000e+02 -1.900000000000000000e+01
+7.000000000000000000e+02 5.530000000000000000e+02 -5.300000000000000000e+01
+7.010000000000000000e+02 5.610000000000000000e+02 -4.800000000000000000e+01
+7.010000000000000000e+02 5.660000000000000000e+02 -4.100000000000000000e+01
+7.000000000000000000e+02 6.200000000000000000e+02 -2.400000000000000000e+01
+6.990000000000000000e+02 6.280000000000000000e+02 -2.700000000000000000e+01
+6.990000000000000000e+02 6.390000000000000000e+02 -3.000000000000000000e+01
+6.990000000000000000e+02 6.510000000000000000e+02 -2.400000000000000000e+01
+7.000000000000000000e+02 6.680000000000000000e+02 -5.000000000000000000e+00
+7.030000000000000000e+02 5.040000000000000000e+02 -9.200000000000000000e+01
+6.870000000000000000e+02 5.030000000000000000e+02 -6.800000000000000000e+01
+5.220000000000000000e+02 3.030000000000000000e+02 1.080000000000000000e+02
+6.290000000000000000e+02 3.910000000000000000e+02 4.000000000000000000e+00
+6.110000000000000000e+02 3.930000000000000000e+02 6.000000000000000000e+00
+5.940000000000000000e+02 3.920000000000000000e+02 1.100000000000000000e+01
+5.730000000000000000e+02 3.790000000000000000e+02 2.600000000000000000e+01
+6.440000000000000000e+02 3.870000000000000000e+02 6.000000000000000000e+00
+6.040000000000000000e+02 3.310000000000000000e+02 -1.000000000000000000e+00
+6.250000000000000000e+02 3.340000000000000000e+02 -1.000000000000000000e+00
+5.840000000000000000e+02 3.350000000000000000e+02 5.000000000000000000e+00
+5.720000000000000000e+02 3.430000000000000000e+02 1.200000000000000000e+01
+5.590000000000000000e+02 3.910000000000000000e+02 3.400000000000000000e+01
+6.320000000000000000e+02 6.780000000000000000e+02 1.700000000000000000e+01
+5.740000000000000000e+02 3.660000000000000000e+02 2.900000000000000000e+01
+5.100000000000000000e+02 3.860000000000000000e+02 1.140000000000000000e+02
+5.410000000000000000e+02 3.760000000000000000e+02 5.200000000000000000e+01
+6.130000000000000000e+02 4.740000000000000000e+02 -1.500000000000000000e+01
+6.760000000000000000e+02 5.410000000000000000e+02 -5.200000000000000000e+01
+6.770000000000000000e+02 5.600000000000000000e+02 -4.500000000000000000e+01
+6.520000000000000000e+02 5.490000000000000000e+02 -4.000000000000000000e+01
+6.360000000000000000e+02 5.560000000000000000e+02 -2.200000000000000000e+01
+6.580000000000000000e+02 5.610000000000000000e+02 -3.500000000000000000e+01
+6.430000000000000000e+02 5.640000000000000000e+02 -1.900000000000000000e+01
+6.150000000000000000e+02 6.040000000000000000e+02 1.500000000000000000e+01
+6.880000000000000000e+02 4.930000000000000000e+02 -9.900000000000000000e+01
+6.870000000000000000e+02 4.730000000000000000e+02 -1.050000000000000000e+02
+5.480000000000000000e+02 3.260000000000000000e+02 1.800000000000000000e+01
+6.520000000000000000e+02 4.270000000000000000e+02 -1.700000000000000000e+01
+6.480000000000000000e+02 4.850000000000000000e+02 -5.500000000000000000e+01
+6.460000000000000000e+02 4.750000000000000000e+02 -5.000000000000000000e+01
+5.600000000000000000e+02 4.700000000000000000e+02 8.000000000000000000e+00
+6.880000000000000000e+02 4.500000000000000000e+02 -9.300000000000000000e+01
+5.880000000000000000e+02 3.060000000000000000e+02 -1.300000000000000000e+01
+5.640000000000000000e+02 3.120000000000000000e+02 1.000000000000000000e+00
+5.400000000000000000e+02 2.700000000000000000e+02 7.400000000000000000e+01
+6.670000000000000000e+02 3.250000000000000000e+02 -3.000000000000000000e+01
+6.430000000000000000e+02 3.440000000000000000e+02 4.000000000000000000e+00
+6.040000000000000000e+02 5.770000000000000000e+02 1.600000000000000000e+01
+5.270000000000000000e+02 5.710000000000000000e+02 1.590000000000000000e+02
+6.610000000000000000e+02 4.970000000000000000e+02 -4.800000000000000000e+01
+6.750000000000000000e+02 5.030000000000000000e+02 -5.000000000000000000e+01
+6.180000000000000000e+02 5.730000000000000000e+02 1.400000000000000000e+01
+6.230000000000000000e+02 5.740000000000000000e+02 1.000000000000000000e+01
+5.550000000000000000e+02 3.000000000000000000e+02 1.000000000000000000e+01
+6.470000000000000000e+02 4.940000000000000000e+02 -4.500000000000000000e+01
+6.210000000000000000e+02 3.080000000000000000e+02 -2.400000000000000000e+01
+6.190000000000000000e+02 2.930000000000000000e+02 -2.700000000000000000e+01
+6.100000000000000000e+02 2.270000000000000000e+02 5.000000000000000000e+00
+5.500000000000000000e+02 2.870000000000000000e+02 3.800000000000000000e+01
+6.180000000000000000e+02 2.620000000000000000e+02 -1.200000000000000000e+01
+5.390000000000000000e+02 3.180000000000000000e+02 3.300000000000000000e+01
+5.320000000000000000e+02 3.140000000000000000e+02 6.900000000000000000e+01
+6.760000000000000000e+02 5.510000000000000000e+02 -5.000000000000000000e+01
+6.550000000000000000e+02 5.550000000000000000e+02 -3.800000000000000000e+01
+6.400000000000000000e+02 5.600000000000000000e+02 -2.200000000000000000e+01
+6.650000000000000000e+02 5.000000000000000000e+02 -4.500000000000000000e+01
+6.210000000000000000e+02 5.730000000000000000e+02 1.200000000000000000e+01
+6.290000000000000000e+02 5.930000000000000000e+02 4.000000000000000000e+00
+6.250000000000000000e+02 5.740000000000000000e+02 9.000000000000000000e+00
+6.690000000000000000e+02 4.910000000000000000e+02 -7.300000000000000000e+01
+6.470000000000000000e+02 5.660000000000000000e+02 -1.700000000000000000e+01
+6.610000000000000000e+02 5.650000000000000000e+02 -2.900000000000000000e+01
+6.790000000000000000e+02 5.650000000000000000e+02 -3.800000000000000000e+01
+6.720000000000000000e+02 6.640000000000000000e+02 -4.000000000000000000e+00
+6.730000000000000000e+02 6.470000000000000000e+02 -2.200000000000000000e+01
+6.740000000000000000e+02 6.350000000000000000e+02 -2.600000000000000000e+01
+6.760000000000000000e+02 6.250000000000000000e+02 -2.400000000000000000e+01
+6.780000000000000000e+02 6.180000000000000000e+02 -2.100000000000000000e+01
+6.470000000000000000e+02 6.030000000000000000e+02 -4.000000000000000000e+00
+6.440000000000000000e+02 6.050000000000000000e+02 -6.000000000000000000e+00
+6.390000000000000000e+02 6.100000000000000000e+02 -8.000000000000000000e+00
+6.370000000000000000e+02 6.160000000000000000e+02 -4.000000000000000000e+00
+6.240000000000000000e+02 5.420000000000000000e+02 -1.700000000000000000e+01
+5.080000000000000000e+02 4.710000000000000000e+02 1.840000000000000000e+02
+7.030000000000000000e+02 5.080000000000000000e+02 -6.900000000000000000e+01
+6.370000000000000000e+02 5.920000000000000000e+02 5.000000000000000000e+00
+6.330000000000000000e+02 5.920000000000000000e+02 4.000000000000000000e+00
+6.790000000000000000e+02 5.110000000000000000e+02 -5.100000000000000000e+01
+6.520000000000000000e+02 5.050000000000000000e+02 -3.200000000000000000e+01
+6.770000000000000000e+02 5.070000000000000000e+02 -5.100000000000000000e+01
+6.320000000000000000e+02 4.370000000000000000e+02 -1.100000000000000000e+01
+6.020000000000000000e+02 4.480000000000000000e+02 -6.000000000000000000e+00
+6.430000000000000000e+02 4.840000000000000000e+02 -3.900000000000000000e+01
+5.680000000000000000e+02 2.430000000000000000e+02 3.800000000000000000e+01
+5.770000000000000000e+02 2.690000000000000000e+02 1.200000000000000000e+01
+5.820000000000000000e+02 2.910000000000000000e+02 -1.000000000000000000e+01
+6.280000000000000000e+02 6.270000000000000000e+02 9.000000000000000000e+00
+6.620000000000000000e+02 2.990000000000000000e+02 -3.600000000000000000e+01
+6.610000000000000000e+02 2.620000000000000000e+02 -2.500000000000000000e+01
+6.560000000000000000e+02 2.190000000000000000e+02 -1.400000000000000000e+01
+5.800000000000000000e+02 3.870000000000000000e+02 1.800000000000000000e+01
+5.410000000000000000e+02 4.050000000000000000e+02 4.400000000000000000e+01
+6.550000000000000000e+02 3.820000000000000000e+02 8.000000000000000000e+00
+5.560000000000000000e+02 3.520000000000000000e+02 2.800000000000000000e+01
+6.650000000000000000e+02 4.160000000000000000e+02 -2.300000000000000000e+01
+6.580000000000000000e+02 4.790000000000000000e+02 -7.300000000000000000e+01
+5.210000000000000000e+02 4.220000000000000000e+02 6.300000000000000000e+01
+5.520000000000000000e+02 4.200000000000000000e+02 2.800000000000000000e+01
+5.740000000000000000e+02 4.280000000000000000e+02 1.100000000000000000e+01
+6.070000000000000000e+02 4.250000000000000000e+02 3.000000000000000000e+00
+6.320000000000000000e+02 4.180000000000000000e+02 -1.000000000000000000e+00
+6.510000000000000000e+02 4.090000000000000000e+02 -6.000000000000000000e+00
+6.890000000000000000e+02 3.920000000000000000e+02 -4.200000000000000000e+01
+5.210000000000000000e+02 4.620000000000000000e+02 5.800000000000000000e+01
+5.430000000000000000e+02 3.490000000000000000e+02 3.600000000000000000e+01
+6.940000000000000000e+02 5.030000000000000000e+02 -9.100000000000000000e+01
+6.520000000000000000e+02 4.460000000000000000e+02 -2.600000000000000000e+01
+5.060000000000000000e+02 3.850000000000000000e+02 1.720000000000000000e+02
+6.650000000000000000e+02 3.990000000000000000e+02 -9.000000000000000000e+00
+6.410000000000000000e+02 4.840000000000000000e+02 -2.100000000000000000e+01
+5.660000000000000000e+02 3.670000000000000000e+02 3.300000000000000000e+01
+6.580000000000000000e+02 4.660000000000000000e+02 -6.600000000000000000e+01
+5.140000000000000000e+02 5.190000000000000000e+02 1.760000000000000000e+02
+6.550000000000000000e+02 3.760000000000000000e+02 1.300000000000000000e+01
+6.730000000000000000e+02 4.560000000000000000e+02 -8.300000000000000000e+01
+5.640000000000000000e+02 6.210000000000000000e+02 7.400000000000000000e+01
+5.640000000000000000e+02 6.450000000000000000e+02 1.020000000000000000e+02
+5.070000000000000000e+02 4.680000000000000000e+02 1.210000000000000000e+02
+5.420000000000000000e+02 5.930000000000000000e+02 9.100000000000000000e+01
+5.200000000000000000e+02 3.480000000000000000e+02 9.700000000000000000e+01
+6.300000000000000000e+02 6.970000000000000000e+02 2.500000000000000000e+01
+6.960000000000000000e+02 5.070000000000000000e+02 -6.700000000000000000e+01
+6.350000000000000000e+02 4.590000000000000000e+02 -1.900000000000000000e+01
+5.280000000000000000e+02 3.790000000000000000e+02 7.000000000000000000e+01
+5.960000000000000000e+02 3.800000000000000000e+02 1.200000000000000000e+01
+6.110000000000000000e+02 3.820000000000000000e+02 8.000000000000000000e+00
+6.260000000000000000e+02 5.950000000000000000e+02 7.000000000000000000e+00
+5.240000000000000000e+02 5.020000000000000000e+02 6.300000000000000000e+01
+6.610000000000000000e+02 7.280000000000000000e+02 3.000000000000000000e+01
+6.100000000000000000e+02 6.930000000000000000e+02 6.300000000000000000e+01
+5.890000000000000000e+02 6.730000000000000000e+02 8.000000000000000000e+01
+7.090000000000000000e+02 2.640000000000000000e+02 -3.000000000000000000e+01
+7.000000000000000000e+02 7.340000000000000000e+02 2.500000000000000000e+01
+6.260000000000000000e+02 3.810000000000000000e+02 7.000000000000000000e+00
+6.400000000000000000e+02 3.780000000000000000e+02 1.000000000000000000e+01
+6.500000000000000000e+02 3.770000000000000000e+02 1.300000000000000000e+01
+5.320000000000000000e+02 3.450000000000000000e+02 5.400000000000000000e+01
+6.390000000000000000e+02 3.590000000000000000e+02 7.000000000000000000e+00
+6.240000000000000000e+02 3.520000000000000000e+02 4.000000000000000000e+00
+6.080000000000000000e+02 3.500000000000000000e+02 5.000000000000000000e+00
+5.920000000000000000e+02 3.530000000000000000e+02 1.000000000000000000e+01
+5.830000000000000000e+02 3.580000000000000000e+02 1.600000000000000000e+01
+5.120000000000000000e+02 3.400000000000000000e+02 1.440000000000000000e+02
+5.860000000000000000e+02 3.770000000000000000e+02 1.800000000000000000e+01
+7.020000000000000000e+02 5.260000000000000000e+02 -5.100000000000000000e+01
+6.420000000000000000e+02 5.320000000000000000e+02 -3.000000000000000000e+01
+6.610000000000000000e+02 4.940000000000000000e+02 -5.500000000000000000e+01
+6.760000000000000000e+02 5.260000000000000000e+02 -4.800000000000000000e+01
+7.060000000000000000e+02 3.630000000000000000e+02 -3.600000000000000000e+01
+5.860000000000000000e+02 6.490000000000000000e+02 6.000000000000000000e+01
+6.070000000000000000e+02 6.730000000000000000e+02 4.400000000000000000e+01
+6.610000000000000000e+02 7.160000000000000000e+02 9.000000000000000000e+00
+5.450000000000000000e+02 6.140000000000000000e+02 1.310000000000000000e+02
+6.500000000000000000e+02 3.690000000000000000e+02 1.100000000000000000e+01
+6.770000000000000000e+02 4.210000000000000000e+02 -4.800000000000000000e+01
+6.990000000000000000e+02 7.220000000000000000e+02 5.000000000000000000e+00
+6.330000000000000000e+02 7.130000000000000000e+02 4.300000000000000000e+01
+5.120000000000000000e+02 5.120000000000000000e+02 1.180000000000000000e+02
+6.610000000000000000e+02 6.120000000000000000e+02 -1.400000000000000000e+01
+6.570000000000000000e+02 6.170000000000000000e+02 -1.600000000000000000e+01
+6.540000000000000000e+02 6.240000000000000000e+02 -1.700000000000000000e+01
+6.530000000000000000e+02 6.350000000000000000e+02 -1.300000000000000000e+01
+6.460000000000000000e+02 6.490000000000000000e+02 1.000000000000000000e+00
+6.310000000000000000e+02 5.680000000000000000e+02 -4.000000000000000000e+00
+6.280000000000000000e+02 5.660000000000000000e+02 -3.000000000000000000e+00
+6.250000000000000000e+02 5.640000000000000000e+02 -3.000000000000000000e+00
+6.110000000000000000e+02 5.570000000000000000e+02 0.000000000000000000e+00
+5.470000000000000000e+02 5.130000000000000000e+02 2.800000000000000000e+01
+6.770000000000000000e+02 4.020000000000000000e+02 -3.100000000000000000e+01
+6.680000000000000000e+02 3.600000000000000000e+02 0.000000000000000000e+00
+6.580000000000000000e+02 3.620000000000000000e+02 7.000000000000000000e+00
+6.350000000000000000e+02 5.690000000000000000e+02 -3.000000000000000000e+00
+5.480000000000000000e+02 5.630000000000000000e+02 5.800000000000000000e+01
+6.830000000000000000e+02 3.600000000000000000e+02 -2.300000000000000000e+01
+6.390000000000000000e+02 6.610000000000000000e+02 1.000000000000000000e+01
+7.050000000000000000e+02 4.280000000000000000e+02 -8.200000000000000000e+01
+6.890000000000000000e+02 4.120000000000000000e+02 -6.000000000000000000e+01
+7.050000000000000000e+02 4.090000000000000000e+02 -6.500000000000000000e+01
+6.630000000000000000e+02 4.500000000000000000e+02 -4.900000000000000000e+01
+7.000000000000000000e+02 7.040000000000000000e+02 -3.000000000000000000e+00
+7.000000000000000000e+02 6.840000000000000000e+02 -3.000000000000000000e+00
+6.670000000000000000e+02 6.790000000000000000e+02 1.000000000000000000e+00
+6.030000000000000000e+02 6.100000000000000000e+02 2.500000000000000000e+01
+6.260000000000000000e+02 5.000000000000000000e+02 -1.500000000000000000e+01
+6.180000000000000000e+02 6.380000000000000000e+02 1.900000000000000000e+01
+5.850000000000000000e+02 4.970000000000000000e+02 -6.000000000000000000e+00
+6.090000000000000000e+02 5.190000000000000000e+02 -8.000000000000000000e+00
+5.720000000000000000e+02 5.280000000000000000e+02 1.100000000000000000e+01
+6.630000000000000000e+02 6.980000000000000000e+02 2.000000000000000000e+00
+6.510000000000000000e+02 4.610000000000000000e+02 -3.700000000000000000e+01
+5.900000000000000000e+02 6.260000000000000000e+02 4.100000000000000000e+01
+6.110000000000000000e+02 6.530000000000000000e+02 3.200000000000000000e+01
+5.900000000000000000e+02 5.800000000000000000e+02 2.300000000000000000e+01
+5.300000000000000000e+02 5.370000000000000000e+02 7.100000000000000000e+01
+5.700000000000000000e+02 5.850000000000000000e+02 3.900000000000000000e+01
+5.230000000000000000e+02 5.540000000000000000e+02 1.110000000000000000e+02
+5.970000000000000000e+02 5.420000000000000000e+02 3.000000000000000000e+00
+6.650000000000000000e+02 4.330000000000000000e+02 -3.600000000000000000e+01
+6.640000000000000000e+02 4.880000000000000000e+02 -7.700000000000000000e+01
+6.530000000000000000e+02 4.920000000000000000e+02 -5.700000000000000000e+01
+6.720000000000000000e+02 4.750000000000000000e+02 -8.900000000000000000e+01
+6.540000000000000000e+02 3.400000000000000000e+02 -4.000000000000000000e+00
+6.240000000000000000e+02 3.250000000000000000e+02 -7.000000000000000000e+00
+5.970000000000000000e+02 3.230000000000000000e+02 -5.000000000000000000e+00
+5.760000000000000000e+02 3.270000000000000000e+02 2.000000000000000000e+00
+5.620000000000000000e+02 3.360000000000000000e+02 1.300000000000000000e+01
+5.550000000000000000e+02 3.710000000000000000e+02 4.000000000000000000e+01
+5.060000000000000000e+02 4.270000000000000000e+02 1.180000000000000000e+02
+5.680000000000000000e+02 4.000000000000000000e+02 2.500000000000000000e+01
+5.850000000000000000e+02 4.070000000000000000e+02 1.400000000000000000e+01
+6.090000000000000000e+02 4.070000000000000000e+02 7.000000000000000000e+00
+6.310000000000000000e+02 4.030000000000000000e+02 3.000000000000000000e+00
+6.490000000000000000e+02 3.970000000000000000e+02 2.000000000000000000e+00
+6.610000000000000000e+02 3.920000000000000000e+02 1.000000000000000000e+00
+5.060000000000000000e+02 4.270000000000000000e+02 1.840000000000000000e+02
+6.530000000000000000e+02 4.970000000000000000e+02 -4.900000000000000000e+01
+6.760000000000000000e+02 4.380000000000000000e+02 -6.300000000000000000e+01
+6.760000000000000000e+02 4.900000000000000000e+02 -9.100000000000000000e+01
+6.850000000000000000e+02 4.990000000000000000e+02 -8.400000000000000000e+01
+6.760000000000000000e+02 4.930000000000000000e+02 -8.200000000000000000e+01
+6.580000000000000000e+02 5.030000000000000000e+02 -4.200000000000000000e+01
+6.890000000000000000e+02 5.010000000000000000e+02 -8.900000000000000000e+01
+6.900000000000000000e+02 5.060000000000000000e+02 -6.700000000000000000e+01
+6.610000000000000000e+02 3.760000000000000000e+02 1.000000000000000000e+01
+6.700000000000000000e+02 3.810000000000000000e+02 -1.000000000000000000e+00
+6.760000000000000000e+02 3.850000000000000000e+02 -1.400000000000000000e+01
+5.780000000000000000e+02 3.620000000000000000e+02 2.200000000000000000e+01
+5.650000000000000000e+02 3.530000000000000000e+02 2.200000000000000000e+01
+7.190000000000000000e+02 4.310000000000000000e+02 -7.600000000000000000e+01
+8.360000000000000000e+02 3.780000000000000000e+02 1.900000000000000000e+01
+7.190000000000000000e+02 5.040000000000000000e+02 -6.800000000000000000e+01
+8.920000000000000000e+02 3.120000000000000000e+02 1.030000000000000000e+02
+7.850000000000000000e+02 3.950000000000000000e+02 2.000000000000000000e+00
+8.030000000000000000e+02 3.970000000000000000e+02 3.000000000000000000e+00
+8.200000000000000000e+02 3.970000000000000000e+02 7.000000000000000000e+00
+8.430000000000000000e+02 3.850000000000000000e+02 2.100000000000000000e+01
+7.700000000000000000e+02 3.910000000000000000e+02 4.000000000000000000e+00
+8.120000000000000000e+02 3.370000000000000000e+02 -4.000000000000000000e+00
+7.910000000000000000e+02 3.400000000000000000e+02 -3.000000000000000000e+00
+8.320000000000000000e+02 3.400000000000000000e+02 2.000000000000000000e+00
+8.440000000000000000e+02 3.490000000000000000e+02 8.000000000000000000e+00
+8.560000000000000000e+02 3.980000000000000000e+02 2.900000000000000000e+01
+7.700000000000000000e+02 6.810000000000000000e+02 1.500000000000000000e+01
+8.430000000000000000e+02 3.720000000000000000e+02 2.500000000000000000e+01
+9.050000000000000000e+02 3.960000000000000000e+02 1.070000000000000000e+02
+8.740000000000000000e+02 3.840000000000000000e+02 4.700000000000000000e+01
+7.960000000000000000e+02 4.780000000000000000e+02 -1.700000000000000000e+01
+7.260000000000000000e+02 5.420000000000000000e+02 -5.300000000000000000e+01
+7.250000000000000000e+02 5.610000000000000000e+02 -4.600000000000000000e+01
+7.530000000000000000e+02 5.500000000000000000e+02 -4.100000000000000000e+01
+7.710000000000000000e+02 5.580000000000000000e+02 -2.400000000000000000e+01
+7.470000000000000000e+02 5.630000000000000000e+02 -3.700000000000000000e+01
+7.640000000000000000e+02 5.660000000000000000e+02 -2.100000000000000000e+01
+7.910000000000000000e+02 6.080000000000000000e+02 1.200000000000000000e+01
+7.170000000000000000e+02 4.930000000000000000e+02 -1.000000000000000000e+02
+7.200000000000000000e+02 4.740000000000000000e+02 -1.050000000000000000e+02
+8.660000000000000000e+02 3.320000000000000000e+02 1.300000000000000000e+01
+7.590000000000000000e+02 4.290000000000000000e+02 -1.900000000000000000e+01
+7.600000000000000000e+02 4.880000000000000000e+02 -5.700000000000000000e+01
+7.620000000000000000e+02 4.780000000000000000e+02 -5.100000000000000000e+01
+8.500000000000000000e+02 4.770000000000000000e+02 4.000000000000000000e+00
+7.200000000000000000e+02 4.510000000000000000e+02 -9.400000000000000000e+01
+8.260000000000000000e+02 3.110000000000000000e+02 -1.600000000000000000e+01
+8.500000000000000000e+02 3.170000000000000000e+02 -3.000000000000000000e+00
+8.760000000000000000e+02 2.770000000000000000e+02 7.000000000000000000e+01
+7.470000000000000000e+02 3.300000000000000000e+02 -3.100000000000000000e+01
+7.720000000000000000e+02 3.490000000000000000e+02 2.000000000000000000e+00
+8.040000000000000000e+02 5.810000000000000000e+02 1.200000000000000000e+01
+8.880000000000000000e+02 5.820000000000000000e+02 1.550000000000000000e+02
+7.460000000000000000e+02 4.990000000000000000e+02 -4.900000000000000000e+01
+7.310000000000000000e+02 5.050000000000000000e+02 -5.100000000000000000e+01
+7.930000000000000000e+02 5.740000000000000000e+02 1.100000000000000000e+01
+7.880000000000000000e+02 5.750000000000000000e+02 7.000000000000000000e+00
+8.580000000000000000e+02 3.060000000000000000e+02 5.000000000000000000e+00
+7.610000000000000000e+02 4.960000000000000000e+02 -4.700000000000000000e+01
+7.930000000000000000e+02 3.140000000000000000e+02 -2.600000000000000000e+01
+7.960000000000000000e+02 2.990000000000000000e+02 -2.900000000000000000e+01
+8.100000000000000000e+02 2.310000000000000000e+02 3.000000000000000000e+00
+8.650000000000000000e+02 2.950000000000000000e+02 3.300000000000000000e+01
+7.990000000000000000e+02 2.670000000000000000e+02 -1.400000000000000000e+01
+8.750000000000000000e+02 3.240000000000000000e+02 2.800000000000000000e+01
+8.820000000000000000e+02 3.230000000000000000e+02 6.400000000000000000e+01
+7.260000000000000000e+02 5.520000000000000000e+02 -5.100000000000000000e+01
+7.500000000000000000e+02 5.570000000000000000e+02 -4.000000000000000000e+01
+7.670000000000000000e+02 5.620000000000000000e+02 -2.400000000000000000e+01
+7.410000000000000000e+02 5.020000000000000000e+02 -4.600000000000000000e+01
+7.900000000000000000e+02 5.750000000000000000e+02 9.000000000000000000e+00
+7.790000000000000000e+02 5.950000000000000000e+02 2.000000000000000000e+00
+7.860000000000000000e+02 5.760000000000000000e+02 7.000000000000000000e+00
+7.370000000000000000e+02 4.930000000000000000e+02 -7.400000000000000000e+01
+7.610000000000000000e+02 5.680000000000000000e+02 -1.900000000000000000e+01
+7.440000000000000000e+02 5.660000000000000000e+02 -3.000000000000000000e+01
+7.240000000000000000e+02 5.660000000000000000e+02 -3.900000000000000000e+01
+7.300000000000000000e+02 6.650000000000000000e+02 -5.000000000000000000e+00
+7.260000000000000000e+02 6.480000000000000000e+02 -2.300000000000000000e+01
+7.250000000000000000e+02 6.360000000000000000e+02 -2.700000000000000000e+01
+7.240000000000000000e+02 6.260000000000000000e+02 -2.500000000000000000e+01
+7.220000000000000000e+02 6.190000000000000000e+02 -2.200000000000000000e+01
+7.580000000000000000e+02 6.050000000000000000e+02 -6.000000000000000000e+00
+7.620000000000000000e+02 6.070000000000000000e+02 -8.000000000000000000e+00
+7.660000000000000000e+02 6.120000000000000000e+02 -1.000000000000000000e+01
+7.680000000000000000e+02 6.190000000000000000e+02 -6.000000000000000000e+00
+7.830000000000000000e+02 5.460000000000000000e+02 -1.900000000000000000e+01
+9.070000000000000000e+02 4.820000000000000000e+02 1.790000000000000000e+02
+7.710000000000000000e+02 5.950000000000000000e+02 3.000000000000000000e+00
+7.750000000000000000e+02 5.940000000000000000e+02 1.000000000000000000e+00
+7.260000000000000000e+02 5.120000000000000000e+02 -5.100000000000000000e+01
+7.550000000000000000e+02 5.070000000000000000e+02 -3.300000000000000000e+01
+7.290000000000000000e+02 5.080000000000000000e+02 -5.200000000000000000e+01
+7.780000000000000000e+02 4.400000000000000000e+02 -1.300000000000000000e+01
+8.080000000000000000e+02 4.530000000000000000e+02 -9.000000000000000000e+00
+7.650000000000000000e+02 4.860000000000000000e+02 -4.100000000000000000e+01
+8.510000000000000000e+02 2.500000000000000000e+02 3.400000000000000000e+01
+8.390000000000000000e+02 2.760000000000000000e+02 8.000000000000000000e+00
+8.320000000000000000e+02 2.970000000000000000e+02 -1.300000000000000000e+01
+7.770000000000000000e+02 6.300000000000000000e+02 6.000000000000000000e+00
+7.520000000000000000e+02 3.050000000000000000e+02 -3.700000000000000000e+01
+7.570000000000000000e+02 2.650000000000000000e+02 -2.600000000000000000e+01
+7.640000000000000000e+02 2.220000000000000000e+02 -1.500000000000000000e+01
+8.350000000000000000e+02 3.930000000000000000e+02 1.400000000000000000e+01
+8.740000000000000000e+02 4.120000000000000000e+02 3.900000000000000000e+01
+7.600000000000000000e+02 3.870000000000000000e+02 7.000000000000000000e+00
+8.590000000000000000e+02 3.580000000000000000e+02 2.300000000000000000e+01
+7.460000000000000000e+02 4.170000000000000000e+02 -2.500000000000000000e+01
+7.480000000000000000e+02 4.810000000000000000e+02 -7.400000000000000000e+01
+8.920000000000000000e+02 4.310000000000000000e+02 5.700000000000000000e+01
+8.630000000000000000e+02 4.260000000000000000e+02 2.300000000000000000e+01
+8.400000000000000000e+02 4.330000000000000000e+02 7.000000000000000000e+00
+8.060000000000000000e+02 4.290000000000000000e+02 -1.000000000000000000e+00
+7.810000000000000000e+02 4.210000000000000000e+02 -4.000000000000000000e+00
+7.620000000000000000e+02 4.120000000000000000e+02 -8.000000000000000000e+00
+7.220000000000000000e+02 3.920000000000000000e+02 -4.300000000000000000e+01
+8.910000000000000000e+02 4.710000000000000000e+02 5.200000000000000000e+01
+8.710000000000000000e+02 3.560000000000000000e+02 3.100000000000000000e+01
+7.110000000000000000e+02 5.030000000000000000e+02 -9.100000000000000000e+01
+7.570000000000000000e+02 4.480000000000000000e+02 -2.700000000000000000e+01
+9.090000000000000000e+02 3.950000000000000000e+02 1.670000000000000000e+02
+7.480000000000000000e+02 4.020000000000000000e+02 -1.000000000000000000e+01
+7.680000000000000000e+02 4.870000000000000000e+02 -2.200000000000000000e+01
+8.500000000000000000e+02 3.720000000000000000e+02 2.800000000000000000e+01
+7.500000000000000000e+02 4.680000000000000000e+02 -6.700000000000000000e+01
+9.010000000000000000e+02 5.300000000000000000e+02 1.710000000000000000e+02
+7.590000000000000000e+02 3.800000000000000000e+02 1.100000000000000000e+01
+7.350000000000000000e+02 4.580000000000000000e+02 -8.400000000000000000e+01
+8.470000000000000000e+02 6.300000000000000000e+02 6.900000000000000000e+01
+8.470000000000000000e+02 6.540000000000000000e+02 9.900000000000000000e+01
+9.070000000000000000e+02 4.780000000000000000e+02 1.150000000000000000e+02
+8.710000000000000000e+02 6.030000000000000000e+02 8.600000000000000000e+01
+8.940000000000000000e+02 3.570000000000000000e+02 9.100000000000000000e+01
+7.720000000000000000e+02 7.010000000000000000e+02 2.300000000000000000e+01
+7.090000000000000000e+02 5.080000000000000000e+02 -6.800000000000000000e+01
+7.740000000000000000e+02 4.620000000000000000e+02 -2.100000000000000000e+01
+8.880000000000000000e+02 3.870000000000000000e+02 6.500000000000000000e+01
+8.190000000000000000e+02 3.860000000000000000e+02 9.000000000000000000e+00
+8.040000000000000000e+02 3.870000000000000000e+02 5.000000000000000000e+00
+7.820000000000000000e+02 5.980000000000000000e+02 4.000000000000000000e+00
+8.880000000000000000e+02 5.120000000000000000e+02 5.800000000000000000e+01
+7.380000000000000000e+02 7.300000000000000000e+02 2.900000000000000000e+01
+7.950000000000000000e+02 6.990000000000000000e+02 6.000000000000000000e+01
+8.190000000000000000e+02 6.800000000000000000e+02 7.700000000000000000e+01
+7.890000000000000000e+02 3.850000000000000000e+02 4.000000000000000000e+00
+7.740000000000000000e+02 3.830000000000000000e+02 7.000000000000000000e+00
+7.640000000000000000e+02 3.820000000000000000e+02 1.100000000000000000e+01
+8.820000000000000000e+02 3.520000000000000000e+02 4.900000000000000000e+01
+7.760000000000000000e+02 3.640000000000000000e+02 5.000000000000000000e+00
+7.920000000000000000e+02 3.570000000000000000e+02 2.000000000000000000e+00
+8.090000000000000000e+02 3.550000000000000000e+02 2.000000000000000000e+00
+8.250000000000000000e+02 3.580000000000000000e+02 6.000000000000000000e+00
+8.340000000000000000e+02 3.640000000000000000e+02 1.200000000000000000e+01
+9.030000000000000000e+02 3.490000000000000000e+02 1.390000000000000000e+02
+8.290000000000000000e+02 3.830000000000000000e+02 1.400000000000000000e+01
+7.650000000000000000e+02 5.340000000000000000e+02 -3.200000000000000000e+01
+7.450000000000000000e+02 4.960000000000000000e+02 -5.600000000000000000e+01
+7.290000000000000000e+02 5.280000000000000000e+02 -4.900000000000000000e+01
+8.220000000000000000e+02 6.570000000000000000e+02 5.700000000000000000e+01
+7.980000000000000000e+02 6.780000000000000000e+02 4.100000000000000000e+01
+7.390000000000000000e+02 7.180000000000000000e+02 8.000000000000000000e+00
+8.680000000000000000e+02 6.240000000000000000e+02 1.270000000000000000e+02
+7.650000000000000000e+02 3.740000000000000000e+02 9.000000000000000000e+00
+7.330000000000000000e+02 4.230000000000000000e+02 -4.900000000000000000e+01
+7.690000000000000000e+02 7.160000000000000000e+02 4.100000000000000000e+01
+9.020000000000000000e+02 5.230000000000000000e+02 1.120000000000000000e+02
+7.420000000000000000e+02 6.140000000000000000e+02 -1.500000000000000000e+01
+7.450000000000000000e+02 6.180000000000000000e+02 -1.700000000000000000e+01
+7.470000000000000000e+02 6.270000000000000000e+02 -1.900000000000000000e+01
+7.490000000000000000e+02 6.370000000000000000e+02 -1.500000000000000000e+01
+7.570000000000000000e+02 6.510000000000000000e+02 -1.000000000000000000e+00
+7.780000000000000000e+02 5.700000000000000000e+02 -7.000000000000000000e+00
+7.810000000000000000e+02 5.680000000000000000e+02 -6.000000000000000000e+00
+7.840000000000000000e+02 5.660000000000000000e+02 -6.000000000000000000e+00
+7.960000000000000000e+02 5.610000000000000000e+02 -4.000000000000000000e+00
+8.640000000000000000e+02 5.210000000000000000e+02 2.300000000000000000e+01
+7.340000000000000000e+02 4.040000000000000000e+02 -3.200000000000000000e+01
+7.460000000000000000e+02 3.640000000000000000e+02 -1.000000000000000000e+00
+7.570000000000000000e+02 3.670000000000000000e+02 6.000000000000000000e+00
+7.750000000000000000e+02 5.710000000000000000e+02 -5.000000000000000000e+00
+8.640000000000000000e+02 5.720000000000000000e+02 5.300000000000000000e+01
+7.300000000000000000e+02 3.630000000000000000e+02 -2.400000000000000000e+01
+7.640000000000000000e+02 6.640000000000000000e+02 8.000000000000000000e+00
+7.210000000000000000e+02 4.130000000000000000e+02 -6.100000000000000000e+01
+7.460000000000000000e+02 4.520000000000000000e+02 -5.000000000000000000e+01
+7.340000000000000000e+02 6.800000000000000000e+02 0.000000000000000000e+00
+8.040000000000000000e+02 6.150000000000000000e+02 2.200000000000000000e+01
+7.820000000000000000e+02 5.030000000000000000e+02 -1.700000000000000000e+01
+7.870000000000000000e+02 6.420000000000000000e+02 1.700000000000000000e+01
+8.240000000000000000e+02 5.020000000000000000e+02 -1.000000000000000000e+01
+7.990000000000000000e+02 5.230000000000000000e+02 -1.100000000000000000e+01
+8.370000000000000000e+02 5.350000000000000000e+02 7.000000000000000000e+00
+7.370000000000000000e+02 7.000000000000000000e+02 0.000000000000000000e+00
+7.570000000000000000e+02 4.630000000000000000e+02 -3.800000000000000000e+01
+8.170000000000000000e+02 6.320000000000000000e+02 3.700000000000000000e+01
+7.950000000000000000e+02 6.580000000000000000e+02 2.900000000000000000e+01
+8.180000000000000000e+02 5.860000000000000000e+02 1.900000000000000000e+01
+8.830000000000000000e+02 5.470000000000000000e+02 6.500000000000000000e+01
+8.400000000000000000e+02 5.930000000000000000e+02 3.400000000000000000e+01
+8.910000000000000000e+02 5.650000000000000000e+02 1.060000000000000000e+02
+8.120000000000000000e+02 5.480000000000000000e+02 -1.000000000000000000e+00
+7.450000000000000000e+02 4.350000000000000000e+02 -3.700000000000000000e+01
+7.420000000000000000e+02 4.900000000000000000e+02 -7.800000000000000000e+01
+7.530000000000000000e+02 4.940000000000000000e+02 -5.900000000000000000e+01
+7.350000000000000000e+02 4.770000000000000000e+02 -9.000000000000000000e+01
+7.610000000000000000e+02 3.450000000000000000e+02 -6.000000000000000000e+00
+7.910000000000000000e+02 3.310000000000000000e+02 -9.000000000000000000e+00
+8.180000000000000000e+02 3.280000000000000000e+02 -8.000000000000000000e+00
+8.390000000000000000e+02 3.320000000000000000e+02 -1.000000000000000000e+00
+8.530000000000000000e+02 3.420000000000000000e+02 9.000000000000000000e+00
+8.600000000000000000e+02 3.780000000000000000e+02 3.500000000000000000e+01
+9.080000000000000000e+02 4.370000000000000000e+02 1.120000000000000000e+02
+8.470000000000000000e+02 4.070000000000000000e+02 2.100000000000000000e+01
+8.290000000000000000e+02 4.130000000000000000e+02 1.000000000000000000e+01
+8.050000000000000000e+02 4.120000000000000000e+02 4.000000000000000000e+00
+7.820000000000000000e+02 4.070000000000000000e+02 1.000000000000000000e+00
+7.650000000000000000e+02 4.010000000000000000e+02 0.000000000000000000e+00
+7.530000000000000000e+02 3.950000000000000000e+02 0.000000000000000000e+00
+9.080000000000000000e+02 4.380000000000000000e+02 1.790000000000000000e+02
+7.530000000000000000e+02 4.990000000000000000e+02 -5.000000000000000000e+01
+7.330000000000000000e+02 4.400000000000000000e+02 -6.400000000000000000e+01
+7.300000000000000000e+02 4.910000000000000000e+02 -9.100000000000000000e+01
+7.200000000000000000e+02 5.000000000000000000e+02 -8.400000000000000000e+01
+7.300000000000000000e+02 4.940000000000000000e+02 -8.300000000000000000e+01
+7.490000000000000000e+02 5.040000000000000000e+02 -4.300000000000000000e+01
+7.170000000000000000e+02 5.020000000000000000e+02 -8.900000000000000000e+01
+7.150000000000000000e+02 5.060000000000000000e+02 -6.800000000000000000e+01
+7.530000000000000000e+02 3.810000000000000000e+02 9.000000000000000000e+00
+7.430000000000000000e+02 3.850000000000000000e+02 -2.000000000000000000e+00
+7.370000000000000000e+02 3.880000000000000000e+02 -1.500000000000000000e+01
+8.390000000000000000e+02 3.680000000000000000e+02 1.800000000000000000e+01
+8.510000000000000000e+02 3.590000000000000000e+02 1.800000000000000000e+01
+6.140000000000000000e+02 3.650000000000000000e+02 1.300000000000000000e+01
+6.330000000000000000e+02 3.650000000000000000e+02 1.300000000000000000e+01
+6.140000000000000000e+02 3.480000000000000000e+02 1.300000000000000000e+01
+5.940000000000000000e+02 3.650000000000000000e+02 1.300000000000000000e+01
+6.140000000000000000e+02 3.820000000000000000e+02 1.300000000000000000e+01
+8.020000000000000000e+02 3.700000000000000000e+02 1.000000000000000000e+01
+8.210000000000000000e+02 3.700000000000000000e+02 1.000000000000000000e+01
+8.020000000000000000e+02 3.530000000000000000e+02 1.000000000000000000e+01
+7.830000000000000000e+02 3.690000000000000000e+02 1.000000000000000000e+01
+8.020000000000000000e+02 3.870000000000000000e+02 1.000000000000000000e+01
diff --git a/talkingface/mediapipe_utils.py b/talkingface/mediapipe_utils.py
new file mode 100644
index 0000000..77d05e9
--- /dev/null
+++ b/talkingface/mediapipe_utils.py
@@ -0,0 +1,38 @@
+import numpy as np
+import cv2
+import mediapipe as mp
+mp_face_mesh = mp.solutions.face_mesh
+mp_face_detection = mp.solutions.face_detection
+
+def detect_face_mesh(frames):
+ pts_3d = np.zeros([len(frames), 478, 3])
+ with mp_face_mesh.FaceMesh(
+ static_image_mode=True,
+ max_num_faces=1,
+ refine_landmarks=True,
+ min_detection_confidence=0.5) as face_mesh:
+ for frame_index, frame in enumerate(frames):
+ results = face_mesh.process(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
+ if results.multi_face_landmarks:
+ image_height, image_width = frame.shape[:2]
+ for face_landmarks in results.multi_face_landmarks:
+ for index_, i in enumerate(face_landmarks.landmark):
+ x_px = i.x * image_width
+ y_px = i.y * image_height
+ z_px = i.z * image_width
+ pts_3d[frame_index, index_] = np.array([x_px, y_px, z_px])
+ else:
+ break
+ return pts_3d
+def detect_face(frames):
+ rect_2d = np.zeros([len(frames), 4])
+ # 剔除掉多个人脸、大角度侧脸(鼻子不在两个眼之间)、部分人脸框在画面外、人脸像素低于80*80的
+ with mp_face_detection.FaceDetection(
+ model_selection=1, min_detection_confidence=0.5) as face_detection:
+ for frame_index, frame in enumerate(frames):
+ results = face_detection.process(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
+ if not results.detections or len(results.detections) > 1:
+ break
+ rect = results.detections[0].location_data.relative_bounding_box
+ rect_2d[frame_index] = np.array([rect.xmin, rect.xmin + rect.width, rect.ymin, rect.ymin + rect.height])
+ return rect_2d
\ No newline at end of file
diff --git a/talkingface/model_utils.py b/talkingface/model_utils.py
new file mode 100644
index 0000000..42adb0d
--- /dev/null
+++ b/talkingface/model_utils.py
@@ -0,0 +1,141 @@
+import sys
+import numpy as np
+import kaldi_native_fbank as knf
+from scipy.io import wavfile
+import torch
+import librosa
+import pickle
+device = "cuda" if torch.cuda.is_available() else "cpu"
+pca = None
+def LoadAudioModel(ckpt_path):
+ # if method == "lstm":
+ # ckpt_path = 'checkpoint/lstm/lstm_model_epoch_560.pth'
+ # Audio2FeatureModel = torch.load(model_path).to(device)
+ # Audio2FeatureModel.eval()
+ from talkingface.models.audio2bs_lstm import Audio2Feature
+ Audio2FeatureModel = Audio2Feature() # 调用模型Model
+ Audio2FeatureModel.load_state_dict(torch.load(ckpt_path))
+ Audio2FeatureModel = Audio2FeatureModel.to(device)
+ Audio2FeatureModel.eval()
+ return Audio2FeatureModel
+
+def LoadRenderModel(ckpt_path, model_name = "one_ref"):
+ if model_name == "one_ref":
+ from talkingface.models.DINet import LeeNet as DINet
+ n_ref = 1
+ source_channel = 3
+ ref_channel = n_ref * 6
+ else:
+ from talkingface.models.DINet import DINet_five_Ref as DINet
+ n_ref = 5
+ source_channel = 6
+ ref_channel = n_ref * 6
+ net_g = DINet(source_channel, ref_channel).cuda()
+ checkpoint = torch.load(ckpt_path)
+ net_g_static = checkpoint['state_dict']['net_g']
+ net_g.load_state_dict(net_g_static)
+ net_g.eval()
+ return net_g
+
+def find_silence_frame(wav):
+ audio_energy = librosa.feature.rms(y=wav, frame_length=800, hop_length=320,
+ center=False) # 对每一frame计算root-mean-square
+ audio_energy = np.transpose(audio_energy) # [t,1]
+ energy = audio_energy[:2 * (len(audio_energy) // 2)]
+ energy = energy.reshape([-1, 2]).max(axis=1) # downsample with max_pool
+ is_sil_mask = (energy < 1e-3).astype(int)
+ sil_index_list = []
+ for i in range(len(is_sil_mask)):
+ if i < 3 or i > len(is_sil_mask) - 4:
+ sil_index_list.append(is_sil_mask[i])
+ else:
+ if is_sil_mask[i] > 0:
+ sil_index_list.append(is_sil_mask[i])
+ else:
+ # 七帧里面有四帧都静音,且左右侧都有静音帧,则此帧判别为静音帧
+ if np.sum(is_sil_mask[i-3:i+4]) > 3 and np.sum(is_sil_mask[i-3:i+1]) > 0 and np.sum(is_sil_mask[i+1:i+4]) > 0:
+ sil_index_list.append(1)
+ else:
+ sil_index_list.append(0)
+ sil_index = np.where(sil_index_list)[0]
+ return sil_index
+
+
+def Audio2mouth(wavpath, Audio2FeatureModel, method = "lstm"):
+ rate, wav = wavfile.read(wavpath, mmap=False)
+ augmented_samples = wav
+ augmented_samples2 = augmented_samples.astype(np.float32, order='C') / 32768.0
+ print(augmented_samples2.shape, augmented_samples2.shape[0] / 16000)
+
+ opts = knf.FbankOptions()
+ opts.frame_opts.dither = 0
+ opts.frame_opts.frame_length_ms = 50
+ opts.frame_opts.frame_shift_ms = 20
+ opts.mel_opts.num_bins = 80
+ opts.frame_opts.snip_edges = False
+ opts.mel_opts.debug_mel = False
+ fbank = knf.OnlineFbank(opts)
+ # sss = augmented_samples2.tolist()
+ # for ii in range(0, len(sss), 10000):
+ # fbank.accept_waveform(16000, sss[ii:ii+10000])
+ fbank.accept_waveform(16000, augmented_samples2.tolist())
+ seq_len = fbank.num_frames_ready // 2
+ A2Lsamples = np.zeros([2 * seq_len, 80])
+ for i in range(2 * seq_len):
+ f2 = fbank.get_frame(i)
+ A2Lsamples[i] = f2
+
+ orig_mel = A2Lsamples
+ # print(orig_mel.shape)
+ input = torch.from_numpy(orig_mel).unsqueeze(0).float().to(device)
+ # print(input.shape)
+ h0 = torch.zeros(2, 1, 192).to(device)
+ c0 = torch.zeros(2, 1, 192).to(device)
+ bs_array, hn, cn = Audio2FeatureModel(input, h0, c0)
+ # print(bs_array.shape)
+ bs_array = bs_array[0].detach().cpu().float().numpy()
+ # print(bs_array.shape)
+ bs_array = bs_array[4:]
+ bs_array[:, :2] = bs_array[:, :2] / 8
+ bs_array[:, 2] = - bs_array[:, 2] / 8
+
+ return bs_array
+from scipy.signal import resample
+def Audio2bs(wavpath, Audio2FeatureModel):
+ rate, wav = wavfile.read(wavpath, mmap=False)
+ wav = resample(wav, len(wav) //2)
+ augmented_samples = wav
+ augmented_samples2 = augmented_samples.astype(np.float32, order='C') / 32768.0
+ # print(augmented_samples2.shape, augmented_samples2.shape[0] / 16000)
+
+ opts = knf.FbankOptions()
+ opts.frame_opts.dither = 0
+ opts.frame_opts.samp_freq = 8000
+ opts.frame_opts.frame_length_ms = 50
+ opts.frame_opts.frame_shift_ms = 20
+ opts.mel_opts.num_bins = 80
+ opts.frame_opts.snip_edges = False
+ opts.mel_opts.debug_mel = False
+ fbank = knf.OnlineFbank(opts)
+ # sss = augmented_samples2.tolist()
+ # for ii in range(0, len(sss), 10000):
+ # fbank.accept_waveform(16000, sss[ii:ii+10000])
+ fbank.accept_waveform(8000, augmented_samples2.tolist())
+ seq_len = fbank.num_frames_ready // 2
+ A2Lsamples = np.zeros([2 * seq_len, 80])
+ for i in range(2 * seq_len):
+ f2 = fbank.get_frame(i)
+ A2Lsamples[i] = f2
+
+ orig_mel = A2Lsamples
+ # print(orig_mel.shape)
+ input = torch.from_numpy(orig_mel).unsqueeze(0).float().to(device)
+ # print(input.shape)
+ h0 = torch.zeros(2, 1, 192).to(device)
+ c0 = torch.zeros(2, 1, 192).to(device)
+ bs_array, hn, cn = Audio2FeatureModel(input, h0, c0)
+ # print(bs_array.shape)
+ bs_array = bs_array[0].detach().cpu().float().numpy()
+ # print(bs_array.shape)
+ # bs_array = bs_array[4:]
+ return bs_array
\ No newline at end of file
diff --git a/talkingface/models/DINet.py b/talkingface/models/DINet.py
new file mode 100644
index 0000000..8450774
--- /dev/null
+++ b/talkingface/models/DINet.py
@@ -0,0 +1,315 @@
+import torch
+from torch import nn
+import torch.nn.functional as F
+import math
+import cv2
+import numpy as np
+from torch.nn import BatchNorm2d
+from torch.nn import BatchNorm1d
+
+def make_coordinate_grid_3d(spatial_size, type):
+ '''
+ generate 3D coordinate grid
+ '''
+ d, h, w = spatial_size
+ x = torch.arange(w).type(type)
+ y = torch.arange(h).type(type)
+ z = torch.arange(d).type(type)
+ x = (2 * (x / (w - 1)) - 1)
+ y = (2 * (y / (h - 1)) - 1)
+ z = (2 * (z / (d - 1)) - 1)
+ yy = y.view(1,-1, 1).repeat(d,1, w)
+ xx = x.view(1,1, -1).repeat(d,h, 1)
+ zz = z.view(-1,1,1).repeat(1,h,w)
+ meshed = torch.cat([xx.unsqueeze_(3), yy.unsqueeze_(3)], 3)
+ return meshed,zz
+
+class ResBlock1d(nn.Module):
+ '''
+ basic block
+ '''
+ def __init__(self, in_features,out_features, kernel_size, padding):
+ super(ResBlock1d, self).__init__()
+ self.in_features = in_features
+ self.out_features = out_features
+ self.conv1 = nn.Conv1d(in_channels=in_features, out_channels=in_features, kernel_size=kernel_size,
+ padding=padding)
+ self.conv2 = nn.Conv1d(in_channels=in_features, out_channels=out_features, kernel_size=kernel_size,
+ padding=padding)
+ if out_features != in_features:
+ self.channel_conv = nn.Conv1d(in_features,out_features,1)
+ self.norm1 = BatchNorm1d(in_features)
+ self.norm2 = BatchNorm1d(in_features)
+ self.relu = nn.ReLU()
+ def forward(self, x):
+ out = self.norm1(x)
+ out = self.relu(out)
+ out = self.conv1(out)
+ out = self.norm2(out)
+ out = self.relu(out)
+ out = self.conv2(out)
+ if self.in_features != self.out_features:
+ out += self.channel_conv(x)
+ else:
+ out += x
+ return out
+
+class ResBlock2d(nn.Module):
+ '''
+ basic block
+ '''
+ def __init__(self, in_features,out_features, kernel_size, padding):
+ super(ResBlock2d, self).__init__()
+ self.in_features = in_features
+ self.out_features = out_features
+ self.conv1 = nn.Conv2d(in_channels=in_features, out_channels=in_features, kernel_size=kernel_size,
+ padding=padding)
+ self.conv2 = nn.Conv2d(in_channels=in_features, out_channels=out_features, kernel_size=kernel_size,
+ padding=padding)
+ if out_features != in_features:
+ self.channel_conv = nn.Conv2d(in_features,out_features,1)
+ self.norm1 = BatchNorm2d(in_features)
+ self.norm2 = BatchNorm2d(in_features)
+ self.relu = nn.ReLU()
+ def forward(self, x):
+ out = self.norm1(x)
+ out = self.relu(out)
+ out = self.conv1(out)
+ out = self.norm2(out)
+ out = self.relu(out)
+ out = self.conv2(out)
+ if self.in_features != self.out_features:
+ out += self.channel_conv(x)
+ else:
+ out += x
+ return out
+
+class UpBlock2d(nn.Module):
+ '''
+ basic block
+ '''
+ def __init__(self, in_features, out_features, kernel_size=3, padding=1):
+ super(UpBlock2d, self).__init__()
+ self.conv = nn.Conv2d(in_channels=in_features, out_channels=out_features, kernel_size=kernel_size,
+ padding=padding)
+ self.norm = BatchNorm2d(out_features)
+ self.relu = nn.ReLU()
+ def forward(self, x):
+ out = F.interpolate(x, scale_factor=2)
+ out = self.conv(out)
+ out = self.norm(out)
+ out = F.relu(out)
+ return out
+
+class DownBlock1d(nn.Module):
+ '''
+ basic block
+ '''
+ def __init__(self, in_features, out_features, kernel_size, padding):
+ super(DownBlock1d, self).__init__()
+ self.conv = nn.Conv1d(in_channels=in_features, out_channels=out_features, kernel_size=kernel_size,
+ padding=padding,stride=2)
+ self.norm = BatchNorm1d(out_features)
+ self.relu = nn.ReLU()
+ def forward(self, x):
+ out = self.conv(x)
+ out = self.norm(out)
+ out = self.relu(out)
+ return out
+
+class DownBlock2d(nn.Module):
+ '''
+ basic block
+ '''
+ def __init__(self, in_features, out_features, kernel_size=3, padding=1, stride=2):
+ super(DownBlock2d, self).__init__()
+ self.conv = nn.Conv2d(in_channels=in_features, out_channels=out_features, kernel_size=kernel_size,
+ padding=padding, stride=stride)
+ self.norm = BatchNorm2d(out_features)
+ self.relu = nn.ReLU()
+ def forward(self, x):
+ out = self.conv(x)
+ out = self.norm(out)
+ out = self.relu(out)
+ return out
+
+class SameBlock1d(nn.Module):
+ '''
+ basic block
+ '''
+ def __init__(self, in_features, out_features, kernel_size, padding):
+ super(SameBlock1d, self).__init__()
+ self.conv = nn.Conv1d(in_channels=in_features, out_channels=out_features,
+ kernel_size=kernel_size, padding=padding)
+ self.norm = BatchNorm1d(out_features)
+ self.relu = nn.ReLU()
+ def forward(self, x):
+ out = self.conv(x)
+ out = self.norm(out)
+ out = self.relu(out)
+ return out
+
+class SameBlock2d(nn.Module):
+ '''
+ basic block
+ '''
+ def __init__(self, in_features, out_features, kernel_size=3, padding=1):
+ super(SameBlock2d, self).__init__()
+ self.conv = nn.Conv2d(in_channels=in_features, out_channels=out_features,
+ kernel_size=kernel_size, padding=padding)
+ self.norm = BatchNorm2d(out_features)
+ self.relu = nn.ReLU()
+ def forward(self, x):
+ out = self.conv(x)
+ out = self.norm(out)
+ out = self.relu(out)
+ return out
+
+class AdaAT(nn.Module):
+ '''
+ AdaAT operator
+ '''
+ def __init__(self, para_ch,feature_ch, cuda = True):
+ super(AdaAT, self).__init__()
+ self.para_ch = para_ch
+ self.feature_ch = feature_ch
+ self.commn_linear = nn.Sequential(
+ nn.Linear(para_ch, para_ch),
+ nn.ReLU()
+ )
+ self.scale = nn.Sequential(
+ nn.Linear(para_ch, feature_ch),
+ nn.Sigmoid()
+ )
+ self.rotation = nn.Sequential(
+ nn.Linear(para_ch, feature_ch),
+ nn.Tanh()
+ )
+ self.translation = nn.Sequential(
+ nn.Linear(para_ch, 2 * feature_ch),
+ nn.Tanh()
+ )
+ self.tanh = nn.Tanh()
+ self.sigmoid = nn.Sigmoid()
+
+ def forward(self, feature_map,para_code):
+ batch,d, h, w = feature_map.size(0), feature_map.size(1), feature_map.size(2), feature_map.size(3)
+ para_code = self.commn_linear(para_code)
+ scale = self.scale(para_code).unsqueeze(-1) * 2
+ angle = self.rotation(para_code).unsqueeze(-1) * 3.14159#
+ rotation_matrix = torch.cat([torch.cos(angle), -torch.sin(angle), torch.sin(angle), torch.cos(angle)], -1)
+ rotation_matrix = rotation_matrix.view(batch, self.feature_ch, 2, 2)
+ translation = self.translation(para_code).view(batch, self.feature_ch, 2)
+ grid_xy, grid_z = make_coordinate_grid_3d((d, h, w), feature_map.type())
+ grid_xy = grid_xy.unsqueeze(0).repeat(batch, 1, 1, 1, 1)
+ grid_z = grid_z.unsqueeze(0).repeat(batch, 1, 1, 1)
+ scale = scale.unsqueeze(2).unsqueeze(3).repeat(1, 1, h, w, 1)
+ rotation_matrix = rotation_matrix.unsqueeze(2).unsqueeze(3).repeat(1, 1, h, w, 1, 1)
+ translation = translation.unsqueeze(2).unsqueeze(3).repeat(1, 1, h, w, 1)
+ trans_grid = torch.matmul(rotation_matrix, grid_xy.unsqueeze(-1)).squeeze(-1) * scale + translation
+ full_grid = torch.cat([trans_grid, grid_z.unsqueeze(-1)], -1)
+ trans_feature = F.grid_sample(feature_map.unsqueeze(1), full_grid).squeeze(1)
+ return trans_feature
+
+class DINet_five_Ref(nn.Module):
+ def __init__(self, source_channel,ref_channel, cuda = True):
+ super(DINet_five_Ref, self).__init__()
+ self.source_in_conv = nn.Sequential(
+ SameBlock2d(source_channel,32,kernel_size=7, padding=3),
+ DownBlock2d(32, 64, kernel_size=3, padding=1),
+ DownBlock2d(64, 128,kernel_size=3, padding=1)
+ )
+ self.ref_in_conv = nn.Sequential(
+ SameBlock2d(ref_channel, 64, kernel_size=7, padding=3),
+ DownBlock2d(64, 128, kernel_size=3, padding=1),
+ DownBlock2d(128, 256, kernel_size=3, padding=1),
+ )
+ self.trans_conv = nn.Sequential(
+ # 20 →10
+ SameBlock2d(384, 128, kernel_size=3, padding=1),
+ # SameBlock2d(128, 128, kernel_size=11, padding=5),
+ SameBlock2d(128, 128, kernel_size=7, padding=3),
+ DownBlock2d(128, 128, kernel_size=3, padding=1),
+ # 10 →5
+ SameBlock2d(128, 128, kernel_size=7, padding=3),
+ # SameBlock2d(128, 128, kernel_size=7, padding=3),
+ DownBlock2d(128, 128, kernel_size=3, padding=1),
+ # 5 →3
+ SameBlock2d(128, 128, kernel_size=3, padding=1),
+ DownBlock2d(128, 128, kernel_size=3, padding=1),
+ # 3 →2
+ SameBlock2d(128, 128, kernel_size=3, padding=1),
+ DownBlock2d(128, 128, kernel_size=3, padding=1),
+
+ )
+
+ appearance_conv_list = []
+ for i in range(2):
+ appearance_conv_list.append(
+ nn.Sequential(
+ ResBlock2d(256, 256, 3, 1),
+ ResBlock2d(256, 256, 3, 1),
+ )
+ )
+ self.appearance_conv_list = nn.ModuleList(appearance_conv_list)
+ self.adaAT = AdaAT(128, 256, cuda)
+ self.out_conv = nn.Sequential(
+ SameBlock2d(384, 128, kernel_size=3, padding=1),
+ UpBlock2d(128,128,kernel_size=3, padding=1),
+ ResBlock2d(128, 128, 3, 1),
+ UpBlock2d(128, 128, kernel_size=3, padding=1),
+ nn.Conv2d(128, 3, kernel_size=3, padding=1),
+ nn.Sigmoid()
+ )
+ self.global_avg2d = nn.AdaptiveAvgPool2d(1)
+ self.global_avg1d = nn.AdaptiveAvgPool1d(1)
+ def ref_input(self, ref_img):
+ ## reference image encoder
+ self.ref_in_feature = self.ref_in_conv(ref_img)
+ # print(self.ref_in_feature.size(), self.ref_in_feature)
+ ## use AdaAT do spatial deformation on reference feature maps
+ self.ref_trans_feature0 = self.appearance_conv_list[0](self.ref_in_feature)
+ def interface(self, source_img, source_prompt):
+ self.source_img = torch.cat([source_img, source_prompt], dim=1)
+ ## source image encoder
+ source_in_feature = self.source_in_conv(self.source_img)
+ # print(source_in_feature.size(), source_in_feature)
+
+ ## alignment encoder
+ img_para = self.trans_conv(torch.cat([source_in_feature,self.ref_in_feature],1))
+ img_para = self.global_avg2d(img_para).squeeze(3).squeeze(2)
+ # print(img_para.size(), img_para)
+ ## concat alignment feature and audio feature
+ trans_para = img_para
+
+ ref_trans_feature = self.adaAT(self.ref_trans_feature0, trans_para)
+ ref_trans_feature = self.appearance_conv_list[1](ref_trans_feature)
+ # print(ref_trans_feature.size(), ref_trans_feature)
+ ## feature decoder
+ merge_feature = torch.cat([source_in_feature,ref_trans_feature],1)
+ # print(merge_feature.size(), merge_feature)
+ out = self.out_conv(merge_feature)
+ return out
+ def forward(self, source_img, source_prompt, ref_img):
+ self.ref_input(ref_img)
+ out = self.interface(source_img, source_prompt)
+ return out
+
+
+# from torch import nn
+# import time
+# import torch
+#
+# device = "cuda" if torch.cuda.is_available() else "cpu"
+# model_Generator = DINet_five_Ref(6, 30).to(device)
+# torch.save(model_Generator.state_dict(), "DINet_five_Ref.pth")
+#
+# source_img = torch.zeros([1,3,256,256]).cuda()
+# source_prompt = torch.zeros([1,3, 256,256]).cuda()
+# ref_img = torch.zeros([1,30,256,256]).cuda()
+#
+# model_Generator.ref_input(ref_img)
+# start_time = time.time()
+# for i in range(2000):
+# print(i, time.time() - start_time)
+# out = model_Generator.interface(source_img, source_prompt)
\ No newline at end of file
diff --git a/talkingface/models/DINet_mini.py b/talkingface/models/DINet_mini.py
new file mode 100644
index 0000000..814211d
--- /dev/null
+++ b/talkingface/models/DINet_mini.py
@@ -0,0 +1,414 @@
+import torch
+from torch import nn
+from torch.nn import BatchNorm2d
+import torch.nn.functional as F
+import cv2
+import numpy as np
+import os
+current_dir = os.path.dirname(os.path.abspath(__file__))
+
+class DownBlock(nn.Module):
+ def __init__(self, in_features, out_features, kernel_size=3, padding=1, groups=1, use_relu=True):
+ super(DownBlock, self).__init__()
+ self.conv = nn.Conv2d(in_channels=in_features, out_channels=out_features, kernel_size=kernel_size,
+ padding=padding, groups=groups, stride=2)
+ self.norm = nn.BatchNorm2d(out_features, affine=True)
+ self.use_relu = use_relu
+
+ def forward(self, x):
+ out = self.conv(x)
+ out = self.norm(out)
+ if self.use_relu:
+ out = F.relu(out)
+ return out
+
+
+class UpBlock(nn.Module):
+ def __init__(self, in_features, out_features, kernel_size=3, padding=1, groups=1, use_relu=True,
+ sample_mode='nearest'):
+ super(UpBlock, self).__init__()
+ self.conv = nn.Conv2d(in_channels=in_features, out_channels=out_features, kernel_size=kernel_size,
+ padding=padding, groups=groups)
+ self.norm = nn.BatchNorm2d(out_features, affine=True)
+ self.use_relu = use_relu
+ self.sample_mode = sample_mode
+
+ def forward(self, x):
+ out = F.interpolate(x, scale_factor=2, mode=self.sample_mode)
+ out = self.conv(out)
+ out = self.norm(out)
+ if self.use_relu:
+ out = F.relu(out)
+ return out
+
+
+class ResBlock(nn.Module):
+ """
+ Res block, preserve spatial resolution.
+ """
+
+ def __init__(self, in_features, kernel_size, padding):
+ super(ResBlock, self).__init__()
+ self.conv1 = nn.Conv2d(in_channels=in_features, out_channels=in_features, kernel_size=kernel_size,
+ padding=padding)
+ self.conv2 = nn.Conv2d(in_channels=in_features, out_channels=in_features, kernel_size=kernel_size,
+ padding=padding)
+ self.norm = nn.BatchNorm2d(in_features, affine=True)
+
+ def forward(self, x):
+ out = self.conv1(x)
+ out = self.norm(out)
+ out = F.relu(out)
+ out = self.conv2(out)
+ out += x
+ return out
+
+class ResBlock2d(nn.Module):
+ '''
+ basic block
+ '''
+ def __init__(self, in_features,out_features, kernel_size, padding):
+ super(ResBlock2d, self).__init__()
+ self.in_features = in_features
+ self.out_features = out_features
+ self.conv1 = nn.Conv2d(in_channels=in_features, out_channels=in_features, kernel_size=kernel_size,
+ padding=padding)
+ self.conv2 = nn.Conv2d(in_channels=in_features, out_channels=out_features, kernel_size=kernel_size,
+ padding=padding)
+ if out_features != in_features:
+ self.channel_conv = nn.Conv2d(in_features,out_features,1)
+ self.norm1 = BatchNorm2d(in_features)
+ self.norm2 = BatchNorm2d(in_features)
+ self.relu = nn.ReLU()
+ def forward(self, x):
+ out = self.norm1(x)
+ out = self.relu(out)
+ out = self.conv1(out)
+ out = self.norm2(out)
+ out = self.relu(out)
+ out = self.conv2(out)
+ if self.in_features != self.out_features:
+ out += self.channel_conv(x)
+ else:
+ out += x
+ return out
+
+class UpBlock2d(nn.Module):
+ '''
+ basic block
+ '''
+ def __init__(self, in_features, out_features, kernel_size=3, padding=1):
+ super(UpBlock2d, self).__init__()
+ self.conv = nn.Conv2d(in_channels=in_features, out_channels=out_features, kernel_size=kernel_size,
+ padding=padding)
+ self.norm = BatchNorm2d(out_features)
+ self.relu = nn.ReLU()
+ def forward(self, x):
+ out = F.interpolate(x, scale_factor=2)
+ out = self.conv(out)
+ out = self.norm(out)
+ out = F.relu(out)
+ return out
+
+class DownBlock2d(nn.Module):
+ '''
+ basic block
+ '''
+ def __init__(self, in_features, out_features, kernel_size=3, padding=1, stride=2):
+ super(DownBlock2d, self).__init__()
+ self.conv = nn.Conv2d(in_channels=in_features, out_channels=out_features, kernel_size=kernel_size,
+ padding=padding, stride=stride)
+ self.norm = BatchNorm2d(out_features)
+ self.relu = nn.ReLU()
+ def forward(self, x):
+ out = self.conv(x)
+ out = self.norm(out)
+ out = self.relu(out)
+ return out
+
+class SameBlock2d(nn.Module):
+ '''
+ basic block
+ '''
+ def __init__(self, in_features, out_features, kernel_size=3, padding=1):
+ super(SameBlock2d, self).__init__()
+ self.conv = nn.Conv2d(in_channels=in_features, out_channels=out_features,
+ kernel_size=kernel_size, padding=padding)
+ self.norm = BatchNorm2d(out_features)
+ self.relu = nn.ReLU()
+ def forward(self, x):
+ out = self.conv(x)
+ out = self.norm(out)
+ out = self.relu(out)
+ return out
+
+def make_coordinate_grid_3d(spatial_size, type):
+ '''
+ generate 3D coordinate grid
+ '''
+ d, h, w = spatial_size
+ x = torch.arange(w).type(type)
+ y = torch.arange(h).type(type)
+ z = torch.arange(d).type(type)
+ x = (2 * (x / (w - 1)) - 1)
+ y = (2 * (y / (h - 1)) - 1)
+ z = (2 * (z / (d - 1)) - 1)
+ yy = y.view(1,-1, 1).repeat(d,1, w)
+ xx = x.view(1,1, -1).repeat(d,h, 1)
+ zz = z.view(-1,1,1).repeat(1,h,w)
+ meshed = torch.cat([xx.unsqueeze_(3), yy.unsqueeze_(3)], 3)
+ return meshed,zz
+
+class AdaAT(nn.Module):
+ '''
+ AdaAT operator
+ '''
+ def __init__(self, para_ch,feature_ch, cuda = True):
+ super(AdaAT, self).__init__()
+ self.para_ch = para_ch
+ self.feature_ch = feature_ch
+ self.commn_linear = nn.Sequential(
+ nn.Linear(para_ch, para_ch),
+ nn.ReLU()
+ )
+ self.scale = nn.Sequential(
+ nn.Linear(para_ch, feature_ch),
+ nn.Sigmoid()
+ )
+ self.rotation = nn.Sequential(
+ nn.Linear(para_ch, feature_ch),
+ nn.Tanh()
+ )
+ self.translation = nn.Sequential(
+ nn.Linear(para_ch, 2 * feature_ch),
+ nn.Tanh()
+ )
+ self.tanh = nn.Tanh()
+ self.sigmoid = nn.Sigmoid()
+ self.cuda = cuda
+ self.f_dim = (20, 14, 18)
+ if cuda:
+ self.grid_xy, self.grid_z = make_coordinate_grid_3d(self.f_dim, torch.cuda.FloatTensor)
+ else:
+ self.grid_xy, self.grid_z = make_coordinate_grid_3d(self.f_dim, torch.FloatTensor)
+ batch = 1
+ self.grid_xy = self.grid_xy.unsqueeze(0).repeat(batch, 1, 1, 1, 1)
+ self.grid_z = self.grid_z.unsqueeze(0).repeat(batch, 1, 1, 1)
+
+
+ def forward(self, feature_map,para_code):
+ # batch,d, h, w = feature_map.size(0), feature_map.size(1), feature_map.size(2), feature_map.size(3)
+ # batch= feature_map.size(0)
+ if self.cuda:
+ batch, d, h, w = feature_map.size(0), feature_map.size(1), feature_map.size(2), feature_map.size(3)
+ # print(batch, d, h, w)
+ grid_xy = self.grid_xy.unsqueeze(0).repeat(batch, 1, 1, 1, 1).view(batch, d, h*w, 2)
+ grid_z = self.grid_z.unsqueeze(0).repeat(batch, 1, 1, 1)
+ else:
+ batch = 1
+ d, h, w = self.f_dim
+ grid_xy = self.grid_xy.view(batch, d, h*w, 2)
+ grid_z = self.grid_z
+ # print((d, h, w), feature_map.type())
+ para_code = self.commn_linear(para_code)
+ scale = self.scale(para_code).unsqueeze(-1) * 2
+ # print(scale.size(), scale)
+ angle = self.rotation(para_code).unsqueeze(-1) * 3.14159#
+ rotation_matrix = torch.cat([torch.cos(angle), -torch.sin(angle), torch.sin(angle), torch.cos(angle)], -1)
+ # rotation_matrix = rotation_matrix.view(batch, self.feature_ch, 2, 2)
+ translation = self.translation(para_code).view(batch, self.feature_ch, 2)
+ # grid_xy, grid_z = make_coordinate_grid_3d((d, h, w), feature_map.type())
+ # grid_xy = self.grid_xy.unsqueeze(0).repeat(batch, 1, 1, 1, 1)
+ # grid_z = self.grid_z.unsqueeze(0).repeat(batch, 1, 1, 1)
+ scale = scale.unsqueeze(2).repeat(1, 1, h*w, 1)
+ # print(scale.size(), scale)
+ # rotation_matrix = rotation_matrix.unsqueeze(2).repeat(1, 1, h*w, 1, 1)
+ rotation_matrix = rotation_matrix.unsqueeze(2).repeat(1, 1, h * w, 1) # torch.Size([bs, 256, 4096, 4])
+ translation = translation.unsqueeze(2).repeat(1, 1, h*w, 1)
+
+ # trans_grid = torch.matmul(rotation_matrix, grid_xy.unsqueeze(-1)).squeeze(-1) * scale + translation
+ trans_grid = torch.matmul(rotation_matrix.view(batch, d, h * w, 2, 2), grid_xy.unsqueeze(-1))
+
+ trans_grid = trans_grid.squeeze(-1) * scale + translation
+ # print(trans_grid.view(batch, d, h, w, 2).size(), grid_z.unsqueeze(-1).size())
+ # trans_grid = torch.matmul(rotation_matrix.view(batch, d, h * w, 2, 2), grid_xy.unsqueeze(-1)).squeeze(
+ # -1) * scale + translation
+ # print(trans_grid.view(batch, d, h, w, 2).size(), grid_z.unsqueeze(-1).size())
+ full_grid = torch.cat([trans_grid.view(batch, d, h, w, 2), grid_z.unsqueeze(-1)], -1)
+ # print(full_grid.size(), full_grid)
+
+ trans_feature = F.grid_sample(feature_map.unsqueeze(1), full_grid).squeeze(1)
+ # print("trans_feature", trans_feature.size())
+ return trans_feature
+
+class DINet_mini(nn.Module):
+ def __init__(self, source_channel,ref_channel, cuda = True):
+ super(DINet_mini, self).__init__()
+ f_dim = 20
+ self.source_in_conv = nn.Sequential(
+ SameBlock2d(source_channel, 12, kernel_size=3, padding=1),
+ DownBlock2d(12, 12, kernel_size=3, padding=1),
+ DownBlock2d(12, f_dim, kernel_size=3, padding=1),
+ )
+ self.ref_in_conv = nn.Sequential(
+ SameBlock2d(ref_channel, 16, kernel_size=3, padding=1),
+ DownBlock2d(16, 16, kernel_size=3, padding=1),
+ SameBlock2d(16, 16, kernel_size=3, padding=1),
+ DownBlock2d(16, f_dim, kernel_size=3, padding=1),
+ # DownBlock2d(ref_channel, 1, kernel_size=3, padding=1),
+ # DownBlock2d(1, f_dim, kernel_size=3, padding=1),
+ )
+ self.trans_conv = nn.Sequential(
+ # 16 →8
+ DownBlock2d(f_dim*2, f_dim, kernel_size=3, padding=1),
+ # 8 →4
+ DownBlock2d(f_dim, f_dim, kernel_size=3, padding=1),
+ )
+
+ self.appearance_conv = nn.Sequential(
+ ResBlock2d(f_dim, f_dim, 3, 1),
+ )
+ self.adaAT = AdaAT(f_dim, f_dim, cuda)
+ self.out_conv = nn.Sequential(
+ SameBlock2d(f_dim*2, f_dim, kernel_size=3, padding=1),
+ UpBlock2d(f_dim, f_dim, kernel_size=3, padding=1),
+ SameBlock2d(f_dim, 16, 3, 1),
+ UpBlock2d(16, 16, kernel_size=3, padding=1),
+ nn.Conv2d(16, 3, kernel_size=3, padding=1),
+ nn.Sigmoid()
+ )
+ self.global_avg2d = nn.AdaptiveAvgPool2d(1)
+
+ def ref_input(self, ref_img):
+ ## reference image encoder
+ self.ref_img = ref_img
+ self.ref_in_feature = self.ref_in_conv(self.ref_img)
+ # import pickle
+ # with open("xxx.pkl", "wb") as f:
+ # pickle.dump(self.ref_in_feature, f)
+ # print("ref_in_feature", self.ref_in_feature.size())
+
+ def interface(self, source_img):
+ self.source_img = source_img
+ ## source image encoder
+ source_in_feature = self.source_in_conv(self.source_img)
+ img_para = self.trans_conv(torch.cat([source_in_feature, self.ref_in_feature], 1))
+ img_para = self.global_avg2d(img_para).squeeze(3).squeeze(2)
+
+ ref_trans_feature = self.adaAT(self.ref_in_feature, img_para)
+ ref_trans_feature = self.appearance_conv(ref_trans_feature)
+ merge_feature = torch.cat([source_in_feature, ref_trans_feature], 1)
+ out = self.out_conv(merge_feature)
+ return out
+
+ def forward(self, ref_img, driving_img):
+ self.driving_img = driving_img
+ self.ref_input(ref_img)
+ out = self.interface(self.driving_img)
+ return out
+
+class DINet_mini_pipeline(nn.Module):
+ def __init__(self, source_channel,ref_channel, cuda = True):
+ super(DINet_mini_pipeline, self).__init__()
+ self.infer_model = DINet_mini(source_channel,ref_channel, cuda = cuda)
+
+ self.grid_tensor = F.affine_grid(torch.eye(2, 3).unsqueeze(0).float(), (1, 1, 128, 128), align_corners=False).to("cuda" if cuda else "cpu")
+
+ face_fusion_tensor = cv2.imread(os.path.join(current_dir, "../../mini_live/face_fusion_mask.png"))
+ face_fusion_tensor = torch.from_numpy(face_fusion_tensor[:,:,:1] / 255.).float().permute(2, 0, 1).unsqueeze(0)
+ mouth_fusion_tensor = cv2.imread(os.path.join(current_dir, "../../mini_live/mouth_fusion_mask.png"))
+ mouth_fusion_tensor = torch.from_numpy(mouth_fusion_tensor[:,:,:1] / 255.).float().permute(2, 0, 1).unsqueeze(0)
+
+ self.face_fusion_tensor = face_fusion_tensor.to("cuda" if cuda else "cpu")
+ self.mouth_fusion_tensor = mouth_fusion_tensor.to("cuda" if cuda else "cpu")
+
+ def ref_input(self, ref_tensor):
+ self.infer_model.ref_input(ref_tensor)
+
+ def interface(self, source_tensor, gl_tensor):
+ face_mask = F.relu(torch.abs(gl_tensor[:, 2:3] * 2 - 1) - 0.9)* 10
+ # face_mask = (gl_tensor[:, 2] == 1) | ((gl_tensor[:, 2] == 0))
+ # face_mask = face_mask.float()
+
+ deformation = gl_tensor[:, :2] * 2 - 1
+ # 假设deformation的前两通道分别代表X和Y方向的位移
+ # deformation的形状为[1, 2, H, W],而grid的形状为[1, H, W, 2]
+ deformation = deformation * self.face_fusion_tensor
+ deformation = deformation.permute(0, 2, 3, 1)
+
+ warped_grid = self.grid_tensor - deformation
+
+ # img0应该是一个形状为[1, C, H, W]的tensor
+ warped_img0 = F.grid_sample(source_tensor, warped_grid, mode='bilinear', padding_mode='zeros',
+ align_corners=False)
+
+ # print(warped_img0.size(), face_mask.size())
+ warped_tensor = warped_img0 * (1 - face_mask) + gl_tensor * face_mask
+ warped_tensor = F.interpolate(warped_tensor, (128, 128))
+ w_pad = int((128 - 72) / 2)
+ h_pad = int((128 - 56) / 2)
+
+ fake_mouth_tensor = warped_tensor[:, :3, h_pad:-h_pad, w_pad:-w_pad]
+ fake_out = self.infer_model.interface(fake_mouth_tensor)
+ # fake_out = fake_mouth_tensor
+ fake_out = fake_out * self.mouth_fusion_tensor + fake_mouth_tensor*(1-self.mouth_fusion_tensor)
+ warped_tensor[:, :3, h_pad:-h_pad, w_pad:-w_pad] = fake_out
+ return warped_tensor
+ def forward(self, source_tensor, gl_tensor, ref_tensor):
+ '''
+
+ Args:
+ source_tensor: [batch, 3, 128, 128]
+ gl_tensor: [batch, 3, 128, 128]
+ ref_tensor: [batch, 12, 128, 128]
+
+ Returns:
+ warped_tensor: [batch, 3, 128, 128]
+ '''
+ self.ref_input(ref_tensor)
+ warped_tensor = self.interface(source_tensor, gl_tensor)
+ return warped_tensor
+
+
+if __name__ == "__main__":
+ device = "cpu"
+ import torch.nn.functional as F
+ # size = (56, 72) # h, w
+ # model = DINet_mini(3, 4*3, cuda = device=="cuda")
+ # model.eval()
+ # model = model.to(device)
+ # driving_img = torch.zeros([1, 3, size[0], size[1]]).to(device)
+ # ref_img = torch.zeros([1, 4*3, size[0], size[1]]).to(device)
+ # from thop import profile
+ # from thop import clever_format
+ #
+ # flops, params = profile(model.to(device), inputs=(ref_img, driving_img))
+ # flops, params = clever_format([flops, params], "%.3f")
+ # print(flops, params)
+
+ size = (128, 128) # h, w
+ model = DINet_mini_pipeline(3, 4*3, cuda = device=="cuda")
+ model.eval()
+ model = model.to(device)
+ source_tensor = torch.ones([1, 3, size[0], size[1]]).to(device)
+ gl_tensor = torch.ones([1, 3, size[0], size[1]]).to(device)
+ ref_tensor = torch.ones([1, 4*3, 56, 72]).to(device)
+ face_fusion_tensor = torch.ones([1, 1, size[0], size[1]]).to(device)
+ mouth_fusion_tensor = torch.ones([1, 1, 56, 72]).to(device)
+
+ from thop import profile
+ from thop import clever_format
+
+ flops, params = profile(model.to(device), inputs=(source_tensor, gl_tensor, ref_tensor))
+ flops, params = clever_format([flops, params], "%.3f")
+ print(flops, params)
+
+ import cv2
+
+ out = model(source_tensor, gl_tensor, ref_tensor)
+ image_numpy = out.detach().squeeze(0).cpu().float().numpy()
+ image_numpy = np.transpose(image_numpy, (1, 2, 0)) * 255.0
+ image_numpy = image_numpy.clip(0, 255)
+ image_numpy = image_numpy.astype(np.uint8)
+ cv2.imwrite("sss1.png", image_numpy)
+
diff --git a/talkingface/models/__init__.py b/talkingface/models/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/talkingface/models/audio2bs_lstm.py b/talkingface/models/audio2bs_lstm.py
new file mode 100644
index 0000000..1e3c91d
--- /dev/null
+++ b/talkingface/models/audio2bs_lstm.py
@@ -0,0 +1,47 @@
+import torch.nn as nn
+import torch
+class Audio2Feature(nn.Module):
+ def __init__(self):
+ super(Audio2Feature, self).__init__()
+ num_pred = 1
+ self.output_size = 6
+ self.ndim = 80
+ APC_hidden_size = 80
+ # define networks
+ self.downsample = nn.Sequential(
+ nn.Linear(in_features=APC_hidden_size * 2, out_features=APC_hidden_size),
+ nn.BatchNorm1d(APC_hidden_size),
+ nn.LeakyReLU(0.2),
+ nn.Linear(APC_hidden_size, APC_hidden_size),
+ )
+ self.LSTM = nn.LSTM(input_size=APC_hidden_size,
+ hidden_size=192,
+ num_layers=2,
+ dropout=0,
+ bidirectional=False,
+ batch_first=True)
+ self.fc = nn.Sequential(
+ nn.Linear(in_features=192, out_features=256),
+ nn.BatchNorm1d(256),
+ nn.LeakyReLU(0.2),
+ nn.Linear(256, 256),
+ nn.BatchNorm1d(256),
+ nn.LeakyReLU(0.2),
+ nn.Linear(256, self.output_size))
+
+ def forward(self, audio_features, h0, c0):
+ '''
+ Args:
+ audio_features: [b, T, ndim]
+ '''
+ self.item_len = audio_features.size()[1]
+ # new in 0324
+ audio_features = audio_features.reshape(-1, self.ndim * 2)
+ down_audio_feats = self.downsample(audio_features)
+ # print(down_audio_feats)
+ down_audio_feats = down_audio_feats.reshape(-1, int(self.item_len / 2), self.ndim)
+ output, (hn, cn) = self.LSTM(down_audio_feats, (h0, c0))
+
+ # output, (hn, cn) = self.LSTM(audio_features)
+ pred = self.fc(output.reshape(-1, 192)).reshape(-1, int(self.item_len / 2), self.output_size)
+ return pred, hn, cn
diff --git a/talkingface/models/common/Discriminator.py b/talkingface/models/common/Discriminator.py
new file mode 100644
index 0000000..d397020
--- /dev/null
+++ b/talkingface/models/common/Discriminator.py
@@ -0,0 +1,39 @@
+from torch import nn
+import torch.nn.functional as F
+
+class DownBlock2d(nn.Module):
+ def __init__(self, in_features, out_features, kernel_size=4, pool=False):
+ super(DownBlock2d, self).__init__()
+ self.conv = nn.Conv2d(in_channels=in_features, out_channels=out_features, kernel_size=kernel_size)
+ self.pool = pool
+ def forward(self, x):
+ out = x
+ out = self.conv(out)
+ out = F.leaky_relu(out, 0.2)
+ if self.pool:
+ out = F.avg_pool2d(out, (2, 2))
+ return out
+
+
+class Discriminator(nn.Module):
+ """
+ Discriminator for GAN loss
+ """
+ def __init__(self, num_channels, block_expansion=64, num_blocks=4, max_features=512):
+ super(Discriminator, self).__init__()
+ down_blocks = []
+ for i in range(num_blocks):
+ down_blocks.append(
+ DownBlock2d(num_channels if i == 0 else min(max_features, block_expansion * (2 ** i)),
+ min(max_features, block_expansion * (2 ** (i + 1))),
+ kernel_size=4, pool=(i != num_blocks - 1)))
+ self.down_blocks = nn.ModuleList(down_blocks)
+ self.conv = nn.Conv2d(self.down_blocks[-1].conv.out_channels, out_channels=1, kernel_size=1)
+ def forward(self, x):
+ feature_maps = []
+ out = x
+ for down_block in self.down_blocks:
+ feature_maps.append(down_block(out))
+ out = feature_maps[-1]
+ out = self.conv(out)
+ return feature_maps, out
diff --git a/talkingface/models/common/VGG19.py b/talkingface/models/common/VGG19.py
new file mode 100644
index 0000000..98c1a09
--- /dev/null
+++ b/talkingface/models/common/VGG19.py
@@ -0,0 +1,47 @@
+import torch
+from torchvision import models
+import numpy as np
+
+
+class Vgg19(torch.nn.Module):
+ """
+ Vgg19 network for perceptual loss
+ """
+ def __init__(self, requires_grad=False):
+ super(Vgg19, self).__init__()
+ vgg_model = models.vgg19(pretrained=True)
+ vgg_pretrained_features = vgg_model.features
+ self.slice1 = torch.nn.Sequential()
+ self.slice2 = torch.nn.Sequential()
+ self.slice3 = torch.nn.Sequential()
+ self.slice4 = torch.nn.Sequential()
+ self.slice5 = torch.nn.Sequential()
+ for x in range(2):
+ self.slice1.add_module(str(x), vgg_pretrained_features[x])
+ for x in range(2, 7):
+ self.slice2.add_module(str(x), vgg_pretrained_features[x])
+ for x in range(7, 12):
+ self.slice3.add_module(str(x), vgg_pretrained_features[x])
+ for x in range(12, 21):
+ self.slice4.add_module(str(x), vgg_pretrained_features[x])
+ for x in range(21, 30):
+ self.slice5.add_module(str(x), vgg_pretrained_features[x])
+
+ self.mean = torch.nn.Parameter(data=torch.Tensor(np.array([0.485, 0.456, 0.406]).reshape((1, 3, 1, 1))),
+ requires_grad=False)
+ self.std = torch.nn.Parameter(data=torch.Tensor(np.array([0.229, 0.224, 0.225]).reshape((1, 3, 1, 1))),
+ requires_grad=False)
+
+ if not requires_grad:
+ for param in self.parameters():
+ param.requires_grad = False
+
+ def forward(self, X):
+ X = (X - self.mean) / self.std
+ h_relu1 = self.slice1(X)
+ h_relu2 = self.slice2(h_relu1)
+ h_relu3 = self.slice3(h_relu2)
+ h_relu4 = self.slice4(h_relu3)
+ h_relu5 = self.slice5(h_relu4)
+ out = [h_relu1, h_relu2, h_relu3, h_relu4, h_relu5]
+ return out
diff --git a/talkingface/models/speed_test.py b/talkingface/models/speed_test.py
new file mode 100644
index 0000000..57624fe
--- /dev/null
+++ b/talkingface/models/speed_test.py
@@ -0,0 +1,21 @@
+import torch
+from talkingface.models.audio2bs_lstm import Audio2Feature
+import time
+import random
+import numpy as np
+import cv2
+device = "cpu"
+
+model = Audio2Feature()
+model.eval()
+x = torch.ones((1, 2, 80))
+h0 = torch.zeros(2, 1, 192)
+c0 = torch.zeros(2, 1, 192)
+y, hn, cn = model(x, h0, c0)
+start_time = time.time()
+
+from thop import profile
+from thop import clever_format
+flops, params = profile(model.to(device), inputs=(x, h0, c0))
+flops, params = clever_format([flops, params], "%.3f")
+print(flops, params)
diff --git a/talkingface/models/sss1.png b/talkingface/models/sss1.png
new file mode 100644
index 0000000..e39bb91
Binary files /dev/null and b/talkingface/models/sss1.png differ
diff --git a/talkingface/preprocess.py b/talkingface/preprocess.py
new file mode 100644
index 0000000..9d212ab
--- /dev/null
+++ b/talkingface/preprocess.py
@@ -0,0 +1,205 @@
+import shutil
+import numpy as np
+import cv2
+import os
+import sys
+import time
+import argparse
+from talkingface.run_utils import video_pts_process, concat_output_2binfile
+from talkingface.mediapipe_utils import detect_face_mesh,detect_face
+from talkingface.utils import main_keypoints_index,INDEX_LIPS
+# 1、是否是mp4,宽高是否大于200,时长是否大于2s,可否成功转换为符合格式的mp4
+# 2、面部关键点检测及是否可以构成循环视频
+# 4、旋转矩阵、面部mask估计
+# 5、验证文件完整性
+
+dir_ = "data/asset/Actor"
+def print_log(task_id, progress, status, Error, mode = 0):
+ '''
+ status: -1代表未开始, 0代表处理中, 1代表已完成, 2代表出错中断
+ progress: 0-1000, 进度千分比
+ '''
+ print("task_id: {}. progress: {:0>4d}. status: {}. mode: {}. Error: {}".format(task_id, progress, status, mode, Error))
+ sys.stdout.flush()
+
+def check_step0(task_id, video_path):
+ try:
+ cap = cv2.VideoCapture(video_path)
+ vid_width = cap.get(cv2.CAP_PROP_FRAME_WIDTH) # 宽度
+ vid_height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT) # 高度
+ frames = cap.get(cv2.CAP_PROP_FRAME_COUNT)
+ fps = cap.get(cv2.CAP_PROP_FPS)
+ cap.release()
+ if vid_width < 200 or vid_height < 200:
+ print_log(task_id, 0, 2, "video width/height < 200")
+ return 0
+ if frames < 2*fps:
+ print_log(task_id, 0, 2, "video duration < 2s")
+ return 0
+ os.makedirs(os.path.join(dir_, task_id), exist_ok=True)
+ front_video_path = os.path.join("data", "front.mp4")
+ scale = max(vid_width / 720., vid_height / 1280.)
+ if scale > 1:
+ new_width = int(vid_width / scale + 0.1)//2 * 2
+ new_height = int(vid_height / scale + 0.1)//2 * 2
+ ffmpeg_cmd = "ffmpeg -i {} -r 25 -ss 00:00:00 -t 00:02:00 -vf scale={}:{} -an -loglevel quiet -y {}".format(
+ video_path,new_width,new_height,front_video_path)
+ else:
+ ffmpeg_cmd = "ffmpeg -i {} -r 25 -ss 00:00:00 -t 00:02:00 -an -loglevel quiet -y {}".format(
+ video_path, front_video_path)
+ os.system(ffmpeg_cmd)
+ if not os.path.isfile(front_video_path):
+ return 0
+ return 1
+ except:
+ print_log(task_id, 0, 2, "video cant be opened")
+ return 0
+
+def check_step1(task_id):
+ front_video_path = os.path.join("data", "front.mp4")
+ back_video_path = os.path.join("data", "back.mp4")
+ video_out_path = os.path.join(dir_, task_id, "video.mp4")
+ face_info_path = os.path.join(dir_, task_id, "video_info.bin")
+ preview_path = os.path.join(dir_, task_id, "preview.jpg")
+ if ExtractFromVideo(task_id, front_video_path) != 1:
+ shutil.rmtree(os.path.join(dir_, task_id))
+ return 0
+ ffmpeg_cmd = "ffmpeg -i {} -vf reverse -loglevel quiet -y {}".format(front_video_path, back_video_path)
+ os.system(ffmpeg_cmd)
+ ffmpeg_cmd = "ffmpeg -f concat -i {} -loglevel quiet -y {}".format("data/video_concat.txt", video_out_path)
+ os.system(ffmpeg_cmd)
+ ffmpeg_cmd = "ffmpeg -i {} -vf crop=w='min(iw\,ih)':h='min(iw\,ih)',scale=256:256,setsar=1 -vframes 1 {}".format(front_video_path, preview_path)
+ # ffmpeg_cmd = "ffmpeg -i {} -vf scale=256:-1 -loglevel quiet -y {}".format(front_video_path, preview_path)
+ os.system(ffmpeg_cmd)
+ if os.path.isfile(front_video_path):
+ os.remove(front_video_path)
+ if os.path.isfile(back_video_path):
+ os.remove(back_video_path)
+ if os.path.isfile(video_out_path) and os.path.isfile(face_info_path):
+ return 1
+ else:
+ return 0
+
+# def check_step2(task_id, ):
+# mat_list, pts_normalized_list, face_mask_pts = video_pts_process(pts_array_origin)
+
+
+def ExtractFromVideo(task_id, front_video_path):
+ cap = cv2.VideoCapture(front_video_path)
+ if not cap.isOpened():
+ print_log(task_id, 0, 2, "front_video cant be opened by opencv")
+ return -1
+
+ vid_width = cap.get(cv2.CAP_PROP_FRAME_WIDTH) # 宽度
+ vid_height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT) # 高度
+
+ totalFrames = cap.get(cv2.CAP_PROP_FRAME_COUNT) # 总帧数
+ totalFrames = int(totalFrames)
+ pts_3d = np.zeros([totalFrames, 478, 3])
+ frame_index = 0
+ face_rect_list = []
+ start_time = time.time()
+ while cap.isOpened():
+ ret, frame = cap.read() # 按帧读取视频
+ # #到视频结尾时终止
+ if ret is False:
+ break
+ rect_2d = detect_face([frame])
+ rect = rect_2d[0]
+ tag_ = 1 if np.sum(rect) > 0 else 0
+ if frame_index == 0 and tag_ != 1:
+ print_log(task_id, 0, 2, "no face detected in first frame")
+ cap.release() # 释放视频对象
+ return 0
+ elif tag_ == 0: # 有时候人脸检测会失败,就用上一帧的结果替代这一帧的结果
+ rect = face_rect_list[-1]
+
+ face_rect_list.append(rect)
+
+ x_min = rect[0] * vid_width
+ y_min = rect[2] * vid_height
+ x_max = rect[1] * vid_width
+ y_max = rect[3] * vid_height
+ seq_w, seq_h = x_max - x_min, y_max - y_min
+ x_mid, y_mid = (x_min + x_max) / 2, (y_min + y_max) / 2
+ x_min = int(max(0, x_mid - seq_w * 0.65))
+ y_min = int(max(0, y_mid - seq_h * 0.4))
+ x_max = int(min(vid_width, x_mid + seq_w * 0.65))
+ y_max = int(min(vid_height, y_mid + seq_h * 0.8))
+
+ frame_face = frame[y_min:y_max, x_min:x_max]
+ frame_kps = detect_face_mesh([frame_face])[0]
+ if np.sum(frame_kps) == 0:
+ print_log(task_id, 0, 2, "Frame num {} keypoint error".format(frame_index))
+ cap.release() # 释放视频对象
+ return 0
+ pts_3d[frame_index] = frame_kps + np.array([x_min, y_min, 0])
+ frame_index += 1
+
+ if time.time() - start_time > 0.5:
+ progress = int(1000 * frame_index / totalFrames * 0.99)
+ print_log(task_id, progress, 0, "handling...")
+ start_time = time.time()
+ cap.release() # 释放视频对象
+ if type(pts_3d) is np.ndarray and len(pts_3d) == totalFrames:
+ pts_3d_main = pts_3d[:, main_keypoints_index]
+ mat_list, pts_normalized_list, face_pts_mean_personal, face_mask_pts_normalized = video_pts_process(pts_3d_main)
+
+ output = concat_output_2binfile(mat_list, pts_3d, face_pts_mean_personal, face_mask_pts_normalized)
+ # print(output.shape)
+ pts_normalized_list = np.array(pts_normalized_list)[:, INDEX_LIPS]
+ # 找出此模特正面人脸的嘴巴区域范围
+ x_max, x_min = np.max(pts_normalized_list[:, :, 0]), np.min(pts_normalized_list[:, :, 0])
+ y_max, y_min = np.max(pts_normalized_list[:, :, 1]), np.min(pts_normalized_list[:, :, 1])
+ y_min = y_min + (y_max - y_min) / 10.
+
+ first_line = np.zeros([406])
+ first_line[:4] = np.array([x_min,x_max,y_min,y_max])
+ # print(first_line)
+ #
+ # pts_2d_main = pts_3d[:, main_keypoints_index, :2].reshape(len(pts_3d), -1)
+ # smooth_array_ = np.array(mat_list).reshape(-1, 16)*100
+ #
+ # output = np.concatenate([smooth_array_, pts_2d_main], axis=1).astype(np.float32)
+ output = np.concatenate([first_line.reshape(1,-1), output], axis=0).astype(np.float32)
+ # print(smooth_array_.shape, pts_2d_main.shape, first_line.shape, output.shape)
+ face_info_path = os.path.join(dir_, task_id, "video_info.bin")
+ # np.savetxt(face_info_path, output, fmt='%.1f')
+ # print(222)
+ output.tofile(face_info_path)
+ return 1
+ else:
+ print_log(task_id, 0, 2, "keypoint cant be saved")
+ return 0
+
+def check_step0_audio(task_id, video_path):
+ dir_ = "data/asset/Audio"
+ wav_path = os.path.join(dir_, task_id + ".wav")
+ ffmpeg_cmd = "ffmpeg -i {} -ac 1 -ar 16000 -loglevel quiet -y {}".format(
+ video_path, wav_path)
+ os.system(ffmpeg_cmd)
+ if not os.path.isfile(wav_path):
+ print_log(task_id, 0, 2, "audio convert failed", 2)
+ return 0
+ return 1
+
+def new_task(task_id, task_mode, video_path):
+ # print(task_id, task_mode, video_path)
+ if task_mode == "0": # "actor"
+ print_log(task_id, 0, 0, "handling...")
+ if check_step0(task_id, video_path):
+ print_log(task_id, 0, 0, "handling...")
+ if check_step1(task_id):
+ print_log(task_id, 1000, 1, "process finished, click to confirm")
+ if task_mode == "2": # "audio"
+ print_log(task_id, 0, 0, "handling...", 2)
+ if check_step0_audio(task_id, video_path):
+ print_log(task_id, 1000, 1, "process finished, click to confirm", 2)
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser(description='Inference code to preprocess videos')
+ parser.add_argument('--task_id', type=str, help='task_id')
+ parser.add_argument('--task_mode', type=str, help='task_mode')
+ parser.add_argument('--video_path', type=str, help='Filepath of video that contains faces to use')
+ args = parser.parse_args()
+ new_task(args.task_id, args.task_mode, args.video_path)
\ No newline at end of file
diff --git a/talkingface/render_model.py b/talkingface/render_model.py
new file mode 100644
index 0000000..4137beb
--- /dev/null
+++ b/talkingface/render_model.py
@@ -0,0 +1,116 @@
+import os.path
+import torch
+import os
+import numpy as np
+import time
+from talkingface.run_utils import smooth_array, video_pts_process
+from talkingface.run_utils import mouth_replace, prepare_video_data
+from talkingface.utils import generate_face_mask, INDEX_LIPS_OUTER
+from talkingface.data.few_shot_dataset import select_ref_index,get_ref_images_fromVideo,generate_input, generate_input_pixels
+device = "cuda" if torch.cuda.is_available() else "cpu"
+import pickle
+import cv2
+
+
+face_mask = generate_face_mask()
+
+
+class RenderModel:
+ def __init__(self):
+ self.__net = None
+
+ self.__pts_driven = None
+ self.__mat_list = None
+ self.__pts_normalized_list = None
+ self.__face_mask_pts = None
+ self.__ref_img = None
+ self.__cap_input = None
+ self.frame_index = 0
+ self.__mouth_coords_array = None
+
+ def loadModel(self, ckpt_path):
+ from talkingface.models.DINet import DINet_five_Ref as DINet
+ n_ref = 5
+ source_channel = 6
+ ref_channel = n_ref * 6
+ self.__net = DINet(source_channel, ref_channel).cuda()
+ checkpoint = torch.load(ckpt_path)
+ self.__net.load_state_dict(checkpoint)
+ self.__net.eval()
+
+ def reset_charactor(self, video_path, Path_pkl, ref_img_index_list = None):
+ if self.__cap_input is not None:
+ self.__cap_input.release()
+
+ self.__pts_driven, self.__mat_list,self.__pts_normalized_list, self.__face_mask_pts, self.__ref_img, self.__cap_input = \
+ prepare_video_data(video_path, Path_pkl, ref_img_index_list)
+
+ ref_tensor = torch.from_numpy(self.__ref_img / 255.).float().permute(2, 0, 1).unsqueeze(0).cuda()
+ self.__net.ref_input(ref_tensor)
+
+ x_min, x_max = np.min(self.__pts_normalized_list[:, INDEX_LIPS_OUTER, 0]), np.max(self.__pts_normalized_list[:, INDEX_LIPS_OUTER, 0])
+ y_min, y_max = np.min(self.__pts_normalized_list[:, INDEX_LIPS_OUTER, 1]), np.max(self.__pts_normalized_list[:, INDEX_LIPS_OUTER, 1])
+ z_min, z_max = np.min(self.__pts_normalized_list[:, INDEX_LIPS_OUTER, 2]), np.max(self.__pts_normalized_list[:, INDEX_LIPS_OUTER, 2])
+
+ x_mid,y_mid,z_mid = (x_min + x_max)/2, (y_min + y_max)/2, (z_min + z_max)/2
+ x_len, y_len, z_len = (x_max - x_min)/2, (y_max - y_min)/2, (z_max - z_min)/2
+ x_min, x_max = x_mid - x_len*0.9, x_mid + x_len*0.9
+ y_min, y_max = y_mid - y_len*0.9, y_mid + y_len*0.9
+ z_min, z_max = z_mid - z_len*0.9, z_mid + z_len*0.9
+
+ # print(face_personal.shape, x_min, x_max, y_min, y_max, z_min, z_max)
+ coords_array = np.zeros([100, 150, 4])
+ for i in range(100):
+ for j in range(150):
+ coords_array[i, j, 0] = j/149
+ coords_array[i, j, 1] = i/100
+ # coords_array[i, j, 2] = int((-75 + abs(j - 75))*(2./3))
+ coords_array[i, j, 2] = ((j - 75)/ 75) ** 2
+ coords_array[i, j, 3] = 1
+
+ coords_array = coords_array*np.array([x_max - x_min, y_max - y_min, z_max - z_min, 1]) + np.array([x_min, y_min, z_min, 0])
+ self.__mouth_coords_array = coords_array.reshape(-1, 4).transpose(1, 0)
+
+
+
+ def interface(self, mouth_frame):
+ vid_frame_count = self.__cap_input.get(cv2.CAP_PROP_FRAME_COUNT)
+ if self.frame_index % vid_frame_count == 0:
+ self.__cap_input.set(cv2.CAP_PROP_POS_FRAMES, 0) # 设置要获取的帧号
+ ret, frame = self.__cap_input.read() # 按帧读取视频
+
+ epoch = self.frame_index // len(self.__mat_list)
+ if epoch % 2 == 0:
+ new_index = self.frame_index % len(self.__mat_list)
+ else:
+ new_index = -1 - self.frame_index % len(self.__mat_list)
+
+ # print(self.__face_mask_pts.shape, "ssssssss")
+ source_img, target_img, crop_coords = generate_input_pixels(frame, self.__pts_driven[new_index], self.__mat_list[new_index],
+ mouth_frame, self.__face_mask_pts[new_index],
+ self.__mouth_coords_array)
+
+ # tensor
+ source_tensor = torch.from_numpy(source_img / 255.).float().permute(2, 0, 1).unsqueeze(0).cuda()
+ target_tensor = torch.from_numpy(target_img / 255.).float().permute(2, 0, 1).unsqueeze(0).cuda()
+
+ source_tensor, source_prompt_tensor = source_tensor[:, :3], source_tensor[:, 3:]
+ fake_out = self.__net.interface(source_tensor, source_prompt_tensor)
+
+ image_numpy = fake_out.detach().squeeze(0).cpu().float().numpy()
+ image_numpy = np.transpose(image_numpy, (1, 2, 0)) * 255.0
+ image_numpy = image_numpy.clip(0, 255)
+ image_numpy = image_numpy.astype(np.uint8)
+
+ image_numpy = target_img * face_mask + image_numpy * (1 - face_mask)
+
+ img_bg = frame
+ x_min, y_min, x_max, y_max = crop_coords
+
+ img_face = cv2.resize(image_numpy, (x_max - x_min, y_max - y_min))
+ img_bg[y_min:y_max, x_min:x_max] = img_face
+ self.frame_index += 1
+ return img_bg
+
+ def save(self, path):
+ torch.save(self.__net.state_dict(), path)
\ No newline at end of file
diff --git a/talkingface/render_model_mini.py b/talkingface/render_model_mini.py
new file mode 100644
index 0000000..72ed235
--- /dev/null
+++ b/talkingface/render_model_mini.py
@@ -0,0 +1,67 @@
+import os.path
+import torch
+import os
+import numpy as np
+import time
+from talkingface.utils import generate_face_mask, INDEX_LIPS_UPPER, INDEX_LIPS_LOWER, crop_mouth, main_keypoints_index
+import torch.nn.functional as F
+from talkingface.data.few_shot_dataset import select_ref_index
+device = "cuda" if torch.cuda.is_available() else "cpu"
+import pickle
+import cv2
+
+from talkingface.utils import draw_mouth_maps
+
+class RenderModel_Mini:
+ def __init__(self):
+ self.__net = None
+
+ def loadModel(self, ckpt_path):
+ from talkingface.models.DINet_mini import DINet_mini_pipeline as DINet
+ n_ref = 3
+ source_channel = 3
+ ref_channel = n_ref * 4
+ self.net = DINet(source_channel, ref_channel).cuda()
+ checkpoint = torch.load(ckpt_path)
+ net_g_static = checkpoint['state_dict']['net_g']
+ self.net.infer_model.load_state_dict(net_g_static)
+ self.net.eval()
+
+
+ def reset_charactor(self, img_list, driven_keypoints, standard_size = 256):
+ ref_img_index_list = select_ref_index(driven_keypoints, n_ref=3, ratio=0.33) # 从当前视频选n_ref个图片
+ ref_img_list = []
+ for i in ref_img_index_list:
+ ref_face_edge = draw_mouth_maps(driven_keypoints[i], size=(standard_size, standard_size))
+ ref_img = img_list[i]
+ ref_face_edge = cv2.resize(ref_face_edge, (128, 128))
+ ref_img = cv2.resize(ref_img, (128, 128))
+ w_pad = int((128 - 72) / 2)
+ h_pad = int((128 - 56) / 2)
+
+ ref_img = np.concatenate([ref_img[h_pad:-h_pad, w_pad:-w_pad,:3], ref_face_edge[h_pad:-h_pad, w_pad:-w_pad, :1]], axis=2)
+ # cv2.imshow("ss", ref_img[:,:,::-1])
+ # cv2.waitKey(-1)
+ ref_img_list.append(ref_img)
+ self.ref_img = np.concatenate(ref_img_list, axis=2)
+
+ ref_tensor = torch.from_numpy(self.ref_img / 255.).float().permute(2, 0, 1).unsqueeze(0).cuda()
+
+ self.net.ref_input(ref_tensor)
+
+
+ def interface(self, source_tensor, gl_tensor):
+ '''
+
+ Args:
+ source_tensor: [batch, 3, 128, 128]
+ gl_tensor: [batch, 3, 128, 128]
+
+ Returns:
+ warped_img: [batch, 3, 128, 128]
+ '''
+ warped_img = self.net.interface(source_tensor, gl_tensor)
+ return warped_img
+
+ def save(self, path):
+ torch.save(self.net.state_dict(), path)
\ No newline at end of file
diff --git a/talkingface/run_utils.py b/talkingface/run_utils.py
new file mode 100644
index 0000000..beb1089
--- /dev/null
+++ b/talkingface/run_utils.py
@@ -0,0 +1,276 @@
+from talkingface.utils import *
+import os
+import pickle
+import copy
+def Tensor2img(tensor_, channel_index):
+ frame = tensor_[channel_index:channel_index + 3, :, :].detach().squeeze(0).cpu().float().numpy()
+ frame = np.transpose(frame, (1, 2, 0)) * 255.0
+ frame = frame.clip(0, 255)
+ return frame.astype(np.uint8)
+
+
+def correct_rotation_matrix(R):
+ # Perform SVD on the 3x3 part of the matrix
+ U, S, VT = np.linalg.svd(R, full_matrices=True)
+
+ # Ensure the determinant is 1 to avoid reflection
+ det = np.linalg.det(U @ VT)
+ if det < 0:
+ VT[-1, :] *= -1 # or U[:, -1] *= -1
+ scale_matrix = np.diag(S)
+ # Combine scaling and rotation
+ scaled_rotation_matrix = U @ scale_matrix @ VT
+ # print("sssssssssssss", det)
+ return scaled_rotation_matrix
+def mat_A(pts):
+ A = np.zeros([len(pts) * 3, 12])
+ for i in range(len(pts)):
+ A[3 * i + 0, 0:3] = pts[i]
+ A[3 * i + 0, 3] = 1
+ A[3 * i + 1, 4:7] = pts[i]
+ A[3 * i + 1, 7] = 1
+ A[3 * i + 2, 8:11] = pts[i]
+ A[3 * i + 2, 11] = 1
+ return A
+from sklearn import decomposition
+def calc_face_mat(pts_array_origin, face_pts_mean):
+ '''
+
+ :param pts_array_origin: mediapipe检测出的人脸关键点
+ :return:
+ '''
+
+ A = mat_A(face_pts_mean)
+ A_inverse = np.linalg.pinv(A)
+ pts_normalized_list = []
+ mat_list = []
+ for i in pts_array_origin:
+ B = i.flatten()
+ x = A_inverse.dot(B)
+ rotationMatrix = np.zeros([4, 4])
+ rotationMatrix[:3, :] = x.reshape(3, 4)
+ rotationMatrix[3, 3] = 1
+
+ R = rotationMatrix[:3, :3]
+ # Correct the rotation part
+ corrected_R = correct_rotation_matrix(R)
+
+ centroid_src = np.mean(face_pts_mean, axis=0)
+ centroid_tgt = np.mean(i, axis=0)
+
+ # Step 4: Compute translation vector
+ T = centroid_tgt - corrected_R @ centroid_src
+ rotationMatrix[:3, :3] = corrected_R
+ rotationMatrix[:3, 3] = T
+ mat_list.append(rotationMatrix)
+
+ for index_, i in enumerate(pts_array_origin):
+ rotationMatrix = mat_list[index_]
+ keypoints = np.ones([4, len(i)])
+ keypoints[:3, :] = i.T
+ keypoints_normalized = np.linalg.inv(rotationMatrix).dot(keypoints).T
+ pts_normalized_list.append(keypoints_normalized[:, :3])
+
+ x = np.array(pts_normalized_list).reshape(len(pts_normalized_list), -1)
+ # print(x.shape)
+ n_components = min(25, len(pts_array_origin)//20)
+ pca = decomposition.PCA(n_components=n_components)
+ pca.fit(x)
+ y = pca.transform(x)
+ x_new = pca.inverse_transform(y)
+ x_new = x_new.reshape(len(x_new), -1, 3)
+
+ pts_normalized_list = []
+ mat_list = []
+ for index, x in enumerate(x_new):
+ A = mat_A(x)
+ A_inverse = np.linalg.pinv(A)
+
+ B = pts_array_origin[index].flatten()
+ x = A_inverse.dot(B)
+ rotationMatrix = np.zeros([4, 4])
+ rotationMatrix[:3, :] = x.reshape(3, 4)
+ rotationMatrix[3, 3] = 1
+ R = rotationMatrix[:3, :3]
+ # Correct the rotation part
+ corrected_R = correct_rotation_matrix(R)
+
+ centroid_src = np.mean(x_new[index], axis=0)
+ centroid_tgt = np.mean(pts_array_origin[index], axis=0)
+
+ # Step 4: Compute translation vector
+ T = centroid_tgt - corrected_R @ centroid_src
+ rotationMatrix[:3, :3] = corrected_R
+ rotationMatrix[:3, 3] = T
+
+ mat_list.append(rotationMatrix)
+
+ mat_list = np.array(mat_list)
+ # mat_list必须要平滑,注意是针对每个视频分别平滑
+ sub_mat_list = mat_list
+ smooth_array_ = sub_mat_list.reshape(-1, 16)
+ import pandas as pd
+
+ smooth_array_ = smooth_array(smooth_array_, weight = [0.04,0.08,0.13,0.5,0.13,0.08,0.04])
+ # pd.DataFrame(smooth_array_[200:400]).to_csv("sad.csv")
+ # exit(-1)
+ # print(smooth_array_, smooth_array_.shape)
+ smooth_array_ = smooth_array_.reshape(-1, 4, 4)
+ mat_list = smooth_array_
+ mat_list = [hh for hh in mat_list]
+
+ for index_,i in enumerate(pts_array_origin):
+ rotationMatrix = mat_list[index_]
+ keypoints = np.ones([4, len(i)])
+ keypoints[:3, :] = i.T
+ keypoints_normalized = np.linalg.inv(rotationMatrix).dot(keypoints).T
+ pts_normalized_list.append(keypoints_normalized[:,:3])
+
+ face_pts_mean_personal = pca.mean_.reshape(-1, 3)
+ return mat_list,pts_normalized_list,face_pts_mean_personal
+face_pts_mean = None
+def video_pts_process(pts_array_origin):
+ global face_pts_mean
+ if face_pts_mean is None:
+ current_dir = os.path.dirname(os.path.abspath(__file__))
+ face_pts_mean = np.loadtxt(os.path.join(current_dir, "../data/face_pts_mean_mainKps.txt"))
+ # 先根据pts_array_origin计算出旋转矩阵、去除旋转后的人脸关键点、面部mask、
+ mat_list, pts_normalized_list, face_pts_mean_personal = calc_face_mat(pts_array_origin, face_pts_mean)
+ pts_normalized_list = np.array(pts_normalized_list)
+ face_mask_pts_normalized = face_pts_mean_personal[INDEX_FACE_OVAL].copy()
+ face_mask_pts_normalized[:10, 1] = np.max(pts_normalized_list[:, INDEX_FACE_OVAL[:10], 1],
+ axis=0) + np.arange(5, 25, 2)
+ face_mask_pts_normalized[:10, 0] = np.max(pts_normalized_list[:, INDEX_FACE_OVAL[:10], 0],
+ axis=0) - (9 - np.arange(0, 10))
+ face_mask_pts_normalized[-10:, 1] = np.max(pts_normalized_list[:, INDEX_FACE_OVAL[-10:], 1],
+ axis=0) - np.arange(5, 25, 2) + 28
+ face_mask_pts_normalized[-10:, 0] = np.min(pts_normalized_list[:, INDEX_FACE_OVAL[-10:], 0],
+ axis=0) + np.arange(0, 10)
+ face_mask_pts_normalized[10, 1] = np.max(pts_normalized_list[:, INDEX_FACE_OVAL[10], 1], axis=0) + 25
+
+ face_mask_pts = np.zeros([len(mat_list), len(face_mask_pts_normalized), 2])
+ for index_ in range(len(mat_list)):
+ rotationMatrix = mat_list[index_]
+
+ keypoints = np.ones([4, len(face_mask_pts_normalized)])
+ keypoints[:3, :] = face_mask_pts_normalized.T
+ driving_mask = rotationMatrix.dot(keypoints).T
+ face_mask_pts[index_] = driving_mask[:,:2]
+
+ return mat_list, pts_normalized_list, face_pts_mean_personal, face_mask_pts
+
+def mouth_replace(pts_array_origin, frames_num):
+ '''
+
+ :param pts_array_origin: mediapipe检测出的人脸关键点
+ :return:
+ '''
+ if os.path.isfile("face_pts_mean_mainKps.txt"):
+ face_pts_mean = np.loadtxt("face_pts_mean_mainKps.txt")
+ else:
+ face_pts_mean = np.loadtxt("data/face_pts_mean_mainKps.txt")
+ mat_list,pts_normalized_list,face_pts_mean_personal = calc_face_mat(pts_array_origin, face_pts_mean)
+ face_personal = face_pts_mean_personal.copy()
+ pts_normalized_list = np.array(pts_normalized_list)
+ # face_pts_mean_personal[INDEX_FACE_OVAL[:10], 1] = np.max(pts_normalized_list[:,INDEX_FACE_OVAL[:10], 1], axis = 0) + 20
+ # face_pts_mean_personal[INDEX_FACE_OVAL[:10], 0] = np.max(pts_normalized_list[:, INDEX_FACE_OVAL[:10], 0], axis=0) + 10
+ # face_pts_mean_personal[INDEX_FACE_OVAL[-10:], 1] = np.max(pts_normalized_list[:, INDEX_FACE_OVAL[-10:], 1], axis=0) + 20
+ # face_pts_mean_personal[INDEX_FACE_OVAL[-10:], 0] = np.min(pts_normalized_list[:, INDEX_FACE_OVAL[-10:], 0], axis=0) - 10
+ # face_pts_mean_personal[INDEX_FACE_OVAL[10], 1] = np.max(pts_normalized_list[:, INDEX_FACE_OVAL[10], 1], axis=0) + 20
+ face_pts_mean_personal[INDEX_FACE_OVAL[:10], 1] = np.max(pts_normalized_list[:,INDEX_FACE_OVAL[:10], 1], axis = 0) + np.arange(5,25,2)
+ face_pts_mean_personal[INDEX_FACE_OVAL[:10], 0] = np.max(pts_normalized_list[:, INDEX_FACE_OVAL[:10], 0], axis=0) - (9 - np.arange(0,10))
+ face_pts_mean_personal[INDEX_FACE_OVAL[-10:], 1] = np.max(pts_normalized_list[:, INDEX_FACE_OVAL[-10:], 1], axis=0) - np.arange(5,25,2) + 28
+ face_pts_mean_personal[INDEX_FACE_OVAL[-10:], 0] = np.min(pts_normalized_list[:, INDEX_FACE_OVAL[-10:], 0], axis=0) + np.arange(0,10)
+
+ face_pts_mean_personal[INDEX_FACE_OVAL[10], 1] = np.max(pts_normalized_list[:, INDEX_FACE_OVAL[10], 1], axis=0) + 25
+
+ face_pts_mean_personal = face_pts_mean_personal[INDEX_FACE_OVAL]
+ face_mask_pts = np.zeros([len(mat_list), len(face_pts_mean_personal), 2])
+ for index_ in range(len(mat_list)):
+ rotationMatrix = mat_list[index_]
+
+ keypoints = np.ones([4, len(face_pts_mean_personal)])
+ keypoints[:3, :] = face_pts_mean_personal.T
+ driving_mask = rotationMatrix.dot(keypoints).T
+ face_mask_pts[index_] = driving_mask[:,:2]
+
+ iteration = frames_num // len(pts_array_origin) + 1
+ if iteration == 1:
+ pass
+ else:
+ pts_array_origin2 = copy.deepcopy(pts_array_origin)
+ mat_list2 = copy.deepcopy(mat_list)
+ face_mask_pts2 = copy.deepcopy(face_mask_pts)
+ for i in range(iteration - 1):
+ if i % 2 == 0:
+ pts_array_origin2 = np.concatenate(
+ [pts_array_origin2, pts_array_origin[::-1]], axis=0)
+ mat_list2 += mat_list[::-1]
+ face_mask_pts2 = np.concatenate(
+ [face_mask_pts2, face_mask_pts[::-1]], axis=0)
+ else:
+ pts_array_origin2 = np.concatenate(
+ [pts_array_origin2, pts_array_origin], axis=0)
+ mat_list2 += mat_list
+ face_mask_pts2 = np.concatenate(
+ [face_mask_pts2, face_mask_pts], axis=0)
+ pts_array_origin = pts_array_origin2
+ mat_list = mat_list2
+ face_mask_pts = face_mask_pts2
+
+ pts_array_origin, mat_list, face_mask_pts = pts_array_origin[:frames_num], mat_list[:frames_num], face_mask_pts[:frames_num]
+ return pts_array_origin, mat_list, face_mask_pts, face_personal, pts_normalized_list
+
+
+def concat_output_2binfile(mat_list, pts_3d, face_pts_mean_personal, face_mask_pts_normalized):
+ face_stable_pts_2d = np.zeros([len(mat_list), len(INDEX_FACE_OVAL + INDEX_MUSCLE), 2]) # 法令纹和脸部外轮廓关键点
+ face_mask_pts_2d = np.zeros([len(mat_list), face_mask_pts_normalized.shape[0], 2])
+ for index_, i in enumerate(mat_list):
+ rotationMatrix = i
+ # 法令纹和脸部外轮廓关键点
+ driving_mouth_pts = face_pts_mean_personal[INDEX_FACE_OVAL + INDEX_MUSCLE]
+ keypoints = np.ones([4, len(driving_mouth_pts)])
+ keypoints[:3, :] = driving_mouth_pts.T
+ driving_mouth_pts = rotationMatrix.dot(keypoints).T
+ face_stable_pts_2d[index_] = driving_mouth_pts[:, :2]
+
+ # 脸部mask关键点
+ driving_mouth_pts = face_mask_pts_normalized
+ keypoints = np.ones([4, len(driving_mouth_pts)])
+ keypoints[:3, :] = driving_mouth_pts.T
+ driving_mouth_pts = rotationMatrix.dot(keypoints).T
+ face_mask_pts_2d[index_] = driving_mouth_pts[:, :2]
+
+
+ pts_2d_main = pts_3d[:, main_keypoints_index, :2].reshape(len(pts_3d), -1)
+ smooth_array_ = np.array(mat_list).reshape(-1, 16) * 100
+ face_mask_pts_2d = face_mask_pts_2d.reshape(len(face_mask_pts_2d), -1)
+ face_stable_pts_2d = face_stable_pts_2d.reshape(len(face_stable_pts_2d), -1)
+
+ output = np.concatenate([smooth_array_, pts_2d_main, face_mask_pts_2d, face_stable_pts_2d], axis=1).astype(np.float32)
+ return output
+from talkingface.data.few_shot_dataset import select_ref_index,get_ref_images_fromVideo
+def prepare_video_data(video_path, Path_pkl, ref_img_index_list, ref_img = None,save_ref = None):
+ with open(Path_pkl, "rb") as f:
+ images_info = pickle.load(f)[:, main_keypoints_index, :]
+
+ pts_driven = images_info.reshape(len(images_info), -1)
+ pts_driven = smooth_array(pts_driven).reshape(len(pts_driven), -1, 3)
+ cap_input = cv2.VideoCapture(video_path)
+ if ref_img is not None:
+ ref_img = cv2.imread(ref_img).reshape(256, -1, 256, 3).transpose(0, 2, 1, 3).reshape(256, 256, -1)
+ else:
+ if ref_img_index_list is None:
+ ref_img_index_list = select_ref_index(pts_driven, n_ref=5, ratio=1 / 2.)
+ ref_img = get_ref_images_fromVideo(cap_input, ref_img_index_list, pts_driven[:, :, :2])
+
+ mat_list, pts_normalized_list, face_pts_mean_personal, face_mask_pts = video_pts_process(pts_driven)
+
+ if save_ref is not None:
+ h, w, c = ref_img.shape
+ ref_img_ = ref_img.reshape(h, w, -1, 3).transpose(0, 2, 1, 3).reshape(h, -1, 3)
+ # ref_path = "ref2.png"
+ cv2.imwrite(save_ref, ref_img_)
+ # logger.info("参考图片已存至{}.".format(ref_path))
+
+ return pts_driven, mat_list, pts_normalized_list, face_mask_pts, ref_img, cap_input
\ No newline at end of file
diff --git a/talkingface/util/__init__.py b/talkingface/util/__init__.py
new file mode 100644
index 0000000..ae36f63
--- /dev/null
+++ b/talkingface/util/__init__.py
@@ -0,0 +1 @@
+"""This package includes a miscellaneous collection of useful helper functions."""
diff --git a/talkingface/util/get_data.py b/talkingface/util/get_data.py
new file mode 100644
index 0000000..97edc3c
--- /dev/null
+++ b/talkingface/util/get_data.py
@@ -0,0 +1,110 @@
+from __future__ import print_function
+import os
+import tarfile
+import requests
+from warnings import warn
+from zipfile import ZipFile
+from bs4 import BeautifulSoup
+from os.path import abspath, isdir, join, basename
+
+
+class GetData(object):
+ """A Python script for downloading CycleGAN or pix2pix datasets.
+
+ Parameters:
+ technique (str) -- One of: 'cyclegan' or 'pix2pix'.
+ verbose (bool) -- If True, print additional information.
+
+ Examples:
+ >>> from util.get_data import GetData
+ >>> gd = GetData(technique='cyclegan')
+ >>> new_data_path = gd.get(save_path='./datasets') # options will be displayed.
+
+ Alternatively, You can use bash scripts: 'scripts/download_pix2pix_model.sh'
+ and 'scripts/download_cyclegan_model.sh'.
+ """
+
+ def __init__(self, technique='cyclegan', verbose=True):
+ url_dict = {
+ 'pix2pix': 'http://efrosgans.eecs.berkeley.edu/pix2pix/datasets/',
+ 'cyclegan': 'https://people.eecs.berkeley.edu/~taesung_park/CycleGAN/datasets'
+ }
+ self.url = url_dict.get(technique.lower())
+ self._verbose = verbose
+
+ def _print(self, text):
+ if self._verbose:
+ print(text)
+
+ @staticmethod
+ def _get_options(r):
+ soup = BeautifulSoup(r.text, 'lxml')
+ options = [h.text for h in soup.find_all('a', href=True)
+ if h.text.endswith(('.zip', 'tar.gz'))]
+ return options
+
+ def _present_options(self):
+ r = requests.get(self.url)
+ options = self._get_options(r)
+ print('Options:\n')
+ for i, o in enumerate(options):
+ print("{0}: {1}".format(i, o))
+ choice = input("\nPlease enter the number of the "
+ "dataset above you wish to download:")
+ return options[int(choice)]
+
+ def _download_data(self, dataset_url, save_path):
+ if not isdir(save_path):
+ os.makedirs(save_path)
+
+ base = basename(dataset_url)
+ temp_save_path = join(save_path, base)
+
+ with open(temp_save_path, "wb") as f:
+ r = requests.get(dataset_url)
+ f.write(r.content)
+
+ if base.endswith('.tar.gz'):
+ obj = tarfile.open(temp_save_path)
+ elif base.endswith('.zip'):
+ obj = ZipFile(temp_save_path, 'r')
+ else:
+ raise ValueError("Unknown File Type: {0}.".format(base))
+
+ self._print("Unpacking Data...")
+ obj.extractall(save_path)
+ obj.close()
+ os.remove(temp_save_path)
+
+ def get(self, save_path, dataset=None):
+ """
+
+ Download a dataset.
+
+ Parameters:
+ save_path (str) -- A directory to save the data to.
+ dataset (str) -- (optional). A specific dataset to download.
+ Note: this must include the file extension.
+ If None, options will be presented for you
+ to choose from.
+
+ Returns:
+ save_path_full (str) -- the absolute path to the downloaded data.
+
+ """
+ if dataset is None:
+ selected_dataset = self._present_options()
+ else:
+ selected_dataset = dataset
+
+ save_path_full = join(save_path, selected_dataset.split('.')[0])
+
+ if isdir(save_path_full):
+ warn("\n'{0}' already exists. Voiding Download.".format(
+ save_path_full))
+ else:
+ self._print('Downloading Data...')
+ url = "{0}/{1}".format(self.url, selected_dataset)
+ self._download_data(url, save_path=save_path)
+
+ return abspath(save_path_full)
diff --git a/talkingface/util/html.py b/talkingface/util/html.py
new file mode 100644
index 0000000..cc3262a
--- /dev/null
+++ b/talkingface/util/html.py
@@ -0,0 +1,86 @@
+import dominate
+from dominate.tags import meta, h3, table, tr, td, p, a, img, br
+import os
+
+
+class HTML:
+ """This HTML class allows us to save images and write texts into a single HTML file.
+
+ It consists of functions such as (add a text header to the HTML file),
+ (add a row of images to the HTML file), and (save the HTML to the disk).
+ It is based on Python library 'dominate', a Python library for creating and manipulating HTML documents using a DOM API.
+ """
+
+ def __init__(self, web_dir, title, refresh=0):
+ """Initialize the HTML classes
+
+ Parameters:
+ web_dir (str) -- a directory that stores the webpage. HTML file will be created at /index.html; images will be saved at 0:
+ with self.doc.head:
+ meta(http_equiv="refresh", content=str(refresh))
+
+ def get_image_dir(self):
+ """Return the directory that stores images"""
+ return self.img_dir
+
+ def add_header(self, text):
+ """Insert a header to the HTML file
+
+ Parameters:
+ text (str) -- the header text
+ """
+ with self.doc:
+ h3(text)
+
+ def add_images(self, ims, txts, links, width=400):
+ """add images to the HTML file
+
+ Parameters:
+ ims (str list) -- a list of image paths
+ txts (str list) -- a list of image names shown on the website
+ links (str list) -- a list of hyperref links; when you click an image, it will redirect you to a new page
+ """
+ self.t = table(border=1, style="table-layout: fixed;") # Insert a table
+ self.doc.add(self.t)
+ with self.t:
+ with tr():
+ for im, txt, link in zip(ims, txts, links):
+ with td(style="word-wrap: break-word;", halign="center", valign="top"):
+ with p():
+ with a(href=os.path.join('images', link)):
+ img(style="width:%dpx" % width, src=os.path.join('images', im))
+ br()
+ p(txt)
+
+ def save(self):
+ """save the current content to the HMTL file"""
+ html_file = '%s/index.html' % self.web_dir
+ f = open(html_file, 'wt')
+ f.write(self.doc.render())
+ f.close()
+
+
+if __name__ == '__main__': # we show an example usage here.
+ html = HTML('web/', 'test_html')
+ html.add_header('hello world')
+
+ ims, txts, links = [], [], []
+ for n in range(4):
+ ims.append('image_%d.png' % n)
+ txts.append('text_%d' % n)
+ links.append('image_%d.png' % n)
+ html.add_images(ims, txts, links)
+ html.save()
diff --git a/talkingface/util/image_pool.py b/talkingface/util/image_pool.py
new file mode 100644
index 0000000..6d086f8
--- /dev/null
+++ b/talkingface/util/image_pool.py
@@ -0,0 +1,54 @@
+import random
+import torch
+
+
+class ImagePool():
+ """This class implements an image buffer that stores previously generated images.
+
+ This buffer enables us to update discriminators using a history of generated images
+ rather than the ones produced by the latest generators.
+ """
+
+ def __init__(self, pool_size):
+ """Initialize the ImagePool class
+
+ Parameters:
+ pool_size (int) -- the size of image buffer, if pool_size=0, no buffer will be created
+ """
+ self.pool_size = pool_size
+ if self.pool_size > 0: # create an empty pool
+ self.num_imgs = 0
+ self.images = []
+
+ def query(self, images):
+ """Return an image from the pool.
+
+ Parameters:
+ images: the latest generated images from the generator
+
+ Returns images from the buffer.
+
+ By 50/100, the buffer will return input images.
+ By 50/100, the buffer will return images previously stored in the buffer,
+ and insert the current images to the buffer.
+ """
+ if self.pool_size == 0: # if the buffer size is 0, do nothing
+ return images
+ return_images = []
+ for image in images:
+ image = torch.unsqueeze(image.data, 0)
+ if self.num_imgs < self.pool_size: # if the buffer is not full; keep inserting current images to the buffer
+ self.num_imgs = self.num_imgs + 1
+ self.images.append(image)
+ return_images.append(image)
+ else:
+ p = random.uniform(0, 1)
+ if p > 0.5: # by 50% chance, the buffer will return a previously stored image, and insert the current image into the buffer
+ random_id = random.randint(0, self.pool_size - 1) # randint is inclusive
+ tmp = self.images[random_id].clone()
+ self.images[random_id] = image
+ return_images.append(tmp)
+ else: # by another 50% chance, the buffer will return the current image
+ return_images.append(image)
+ return_images = torch.cat(return_images, 0) # collect all the images and return
+ return return_images
diff --git a/talkingface/util/log_board.py b/talkingface/util/log_board.py
new file mode 100644
index 0000000..dd528d8
--- /dev/null
+++ b/talkingface/util/log_board.py
@@ -0,0 +1,17 @@
+def log(
+ logger, step=None, losses=None, fig=None, audio=None, sampling_rate=22050, tag=""
+):
+ if losses is not None:
+ logger.add_scalar("Loss/d_loss", losses[0], step)
+ logger.add_scalar("Loss/g_gan_loss", losses[1], step)
+ logger.add_scalar("Loss/g_l1_loss", losses[2], step)
+
+ if fig is not None:
+ logger.add_image(tag, fig, 2, dataformats='HWC')
+
+ if audio is not None:
+ logger.add_audio(
+ tag,
+ audio / max(abs(audio)),
+ sample_rate=sampling_rate,
+ )
\ No newline at end of file
diff --git a/talkingface/util/smooth.py b/talkingface/util/smooth.py
new file mode 100644
index 0000000..6a731db
--- /dev/null
+++ b/talkingface/util/smooth.py
@@ -0,0 +1,44 @@
+import numpy as np
+import torch
+import torch.nn as nn
+import torch.nn.functional as F
+
+def smooth_array(array, weight = [0.1,0.8,0.1]):
+ '''
+
+ Args:
+ array: [n_frames, n_values], 需要转换为[n_values, 1, n_frames]
+ weight: Conv1d.weight, 一维卷积核权重
+ Returns:
+ array: [n_frames, n_values], 光滑后的array
+ '''
+ input = torch.Tensor(np.transpose(array[:,np.newaxis,:], (2, 1, 0)))
+ smooth_length = len(weight)
+ assert smooth_length%2 == 1, "卷积核权重个数必须使用奇数"
+ pad = (smooth_length//2, smooth_length//2) # 当pad只有两个参数时,仅改变最后一个维度, 左边扩充1列,右边扩充1列
+ input = F.pad(input, pad, "replicate")
+
+ with torch.no_grad():
+ conv1 = nn.Conv1d(in_channels=1, out_channels=1, kernel_size=smooth_length)
+ # 卷积核的元素值初始化
+ weight = torch.tensor(weight).view(1, 1, -1)
+ conv1.weight = torch.nn.Parameter(weight)
+ nn.init.constant_(conv1.bias, 0) # 偏置值为0
+ # print(conv1.weight)
+ out = conv1(input)
+ return out.permute(2,1,0).squeeze().numpy()
+
+if __name__ == '__main__':
+ model_id = "new_case"
+ Path_output_pkl = "../preparation/{}/mouth_info.pkl".format(model_id + "/00001")
+ import pickle
+ with open(Path_output_pkl, "rb") as f:
+ images_info = pickle.load(f)
+ pts_array_normalized = np.array(images_info[2])
+ pts_array_normalized = pts_array_normalized.reshape(-1, 16)
+ smooth_array_ = smooth_array(pts_array_normalized)
+ print(smooth_array_, smooth_array_.shape)
+ smooth_array_ = smooth_array_.reshape(-1, 4, 4)
+ import pandas as pd
+
+ pd.DataFrame(smooth_array_[:, :, 0]).to_csv("mat2.csv")
\ No newline at end of file
diff --git a/talkingface/util/util.py b/talkingface/util/util.py
new file mode 100644
index 0000000..b050c13
--- /dev/null
+++ b/talkingface/util/util.py
@@ -0,0 +1,103 @@
+"""This module contains simple helper functions """
+from __future__ import print_function
+import torch
+import numpy as np
+from PIL import Image
+import os
+
+
+def tensor2im(input_image, imtype=np.uint8):
+ """"Converts a Tensor array into a numpy image array.
+
+ Parameters:
+ input_image (tensor) -- the input image tensor array
+ imtype (type) -- the desired type of the converted numpy array
+ """
+ if not isinstance(input_image, np.ndarray):
+ if isinstance(input_image, torch.Tensor): # get the data from a variable
+ image_tensor = input_image.data
+ else:
+ return input_image
+ image_numpy = image_tensor[0].cpu().float().numpy() # convert it into a numpy array
+ if image_numpy.shape[0] == 1: # grayscale to RGB
+ image_numpy = np.tile(image_numpy, (3, 1, 1))
+ image_numpy = (np.transpose(image_numpy, (1, 2, 0)) + 1) / 2.0 * 255.0 # post-processing: tranpose and scaling
+ else: # if it is a numpy array, do nothing
+ image_numpy = input_image
+ return image_numpy.astype(imtype)
+
+
+def diagnose_network(net, name='network'):
+ """Calculate and print the mean of average absolute(gradients)
+
+ Parameters:
+ net (torch network) -- Torch network
+ name (str) -- the name of the network
+ """
+ mean = 0.0
+ count = 0
+ for param in net.parameters():
+ if param.grad is not None:
+ mean += torch.mean(torch.abs(param.grad.data))
+ count += 1
+ if count > 0:
+ mean = mean / count
+ print(name)
+ print(mean)
+
+
+def save_image(image_numpy, image_path, aspect_ratio=1.0):
+ """Save a numpy image to the disk
+
+ Parameters:
+ image_numpy (numpy array) -- input numpy array
+ image_path (str) -- the path of the image
+ """
+
+ image_pil = Image.fromarray(image_numpy)
+ h, w, _ = image_numpy.shape
+
+ if aspect_ratio > 1.0:
+ image_pil = image_pil.resize((h, int(w * aspect_ratio)), Image.BICUBIC)
+ if aspect_ratio < 1.0:
+ image_pil = image_pil.resize((int(h / aspect_ratio), w), Image.BICUBIC)
+ image_pil.save(image_path)
+
+
+def print_numpy(x, val=True, shp=False):
+ """Print the mean, min, max, median, std, and size of a numpy array
+
+ Parameters:
+ val (bool) -- if print the values of the numpy array
+ shp (bool) -- if print the shape of the numpy array
+ """
+ x = x.astype(np.float64)
+ if shp:
+ print('shape,', x.shape)
+ if val:
+ x = x.flatten()
+ print('mean = %3.3f, min = %3.3f, max = %3.3f, median = %3.3f, std=%3.3f' % (
+ np.mean(x), np.min(x), np.max(x), np.median(x), np.std(x)))
+
+
+def mkdirs(paths):
+ """create empty directories if they don't exist
+
+ Parameters:
+ paths (str list) -- a list of directory paths
+ """
+ if isinstance(paths, list) and not isinstance(paths, str):
+ for path in paths:
+ mkdir(path)
+ else:
+ mkdir(paths)
+
+
+def mkdir(path):
+ """create a single empty directory if it didn't exist
+
+ Parameters:
+ path (str) -- a single directory path
+ """
+ if not os.path.exists(path):
+ os.makedirs(path)
diff --git a/talkingface/util/utils.py b/talkingface/util/utils.py
new file mode 100644
index 0000000..0a56885
--- /dev/null
+++ b/talkingface/util/utils.py
@@ -0,0 +1,132 @@
+from torch.optim import lr_scheduler
+
+import torch.nn as nn
+import torch
+
+######################################################### training utils##########################################################
+
+def get_scheduler(optimizer, niter,niter_decay,lr_policy='lambda',lr_decay_iters=50):
+ '''
+ scheduler in training stage
+ '''
+ if lr_policy == 'lambda':
+ def lambda_rule(epoch):
+ lr_l = 1.0 - max(0, epoch - niter) / float(niter_decay + 1)
+ return lr_l
+ scheduler = lr_scheduler.LambdaLR(optimizer, lr_lambda=lambda_rule)
+ elif lr_policy == 'step':
+ scheduler = lr_scheduler.StepLR(optimizer, step_size=lr_decay_iters, gamma=0.1)
+ elif lr_policy == 'plateau':
+ scheduler = lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0.2, threshold=0.01, patience=5)
+ elif lr_policy == 'cosine':
+ scheduler = lr_scheduler.CosineAnnealingLR(optimizer, T_max=niter, eta_min=0)
+ else:
+ return NotImplementedError('learning rate policy [%s] is not implemented', lr_policy)
+ return scheduler
+
+def update_learning_rate(scheduler, optimizer):
+ scheduler.step()
+ lr = optimizer.param_groups[0]['lr']
+ print('learning rate = %.7f' % lr)
+
+class GANLoss(nn.Module):
+ '''
+ GAN loss
+ '''
+ def __init__(self, use_lsgan=True, target_real_label=1.0, target_fake_label=0.0):
+ super(GANLoss, self).__init__()
+ self.register_buffer('real_label', torch.tensor(target_real_label))
+ self.register_buffer('fake_label', torch.tensor(target_fake_label))
+ if use_lsgan:
+ self.loss = nn.MSELoss()
+ else:
+ self.loss = nn.BCELoss()
+
+ def get_target_tensor(self, input, target_is_real):
+ if target_is_real:
+ target_tensor = self.real_label
+ else:
+ target_tensor = self.fake_label
+ return target_tensor.expand_as(input)
+
+ def forward(self, input, target_is_real):
+ target_tensor = self.get_target_tensor(input, target_is_real)
+ return self.loss(input, target_tensor)
+
+
+
+import tqdm
+import numpy as np
+import cv2
+import glob
+import os
+import math
+import pickle
+import mediapipe as mp
+mp_face_mesh = mp.solutions.face_mesh
+landmark_points_68 = [162,234,93,58,172,136,149,148,152,377,378,365,397,288,323,454,389,
+ 71,63,105,66,107,336,296,334,293,301,
+ 168,197,5,4,75,97,2,326,305,
+ 33,160,158,133,153,144,362,385,387,263,373,
+ 380,61,39,37,0,267,269,291,405,314,17,84,181,78,82,13,312,308,317,14,87]
+def ExtractFaceFromFrameList(frames_list, vid_height, vid_width, out_size = 256):
+ pts_3d = np.zeros([len(frames_list), 478, 3])
+ with mp_face_mesh.FaceMesh(
+ static_image_mode=True,
+ max_num_faces=1,
+ refine_landmarks=True,
+ min_detection_confidence=0.5) as face_mesh:
+
+ for index, frame in tqdm.tqdm(enumerate(frames_list)):
+ results = face_mesh.process(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
+ if not results.multi_face_landmarks:
+ print("****** WARNING! No face detected! ******")
+ pts_3d[index] = 0
+ return
+ # continue
+ image_height, image_width = frame.shape[:2]
+ for face_landmarks in results.multi_face_landmarks:
+ for index_, i in enumerate(face_landmarks.landmark):
+ x_px = min(math.floor(i.x * image_width), image_width - 1)
+ y_px = min(math.floor(i.y * image_height), image_height - 1)
+ z_px = min(math.floor(i.z * image_height), image_height - 1)
+ pts_3d[index, index_] = np.array([x_px, y_px, z_px])
+
+ # 计算整个视频中人脸的范围
+
+ x_min, y_min, x_max, y_max = np.min(pts_3d[:, :, 0]), np.min(
+ pts_3d[:, :, 1]), np.max(
+ pts_3d[:, :, 0]), np.max(pts_3d[:, :, 1])
+ new_w = int((x_max - x_min) * 0.55)*2
+ new_h = int((y_max - y_min) * 0.6)*2
+ center_x = int((x_max + x_min) / 2.)
+ center_y = int(y_min + (y_max - y_min) * 0.6)
+ size = max(new_h, new_w)
+ x_min, y_min, x_max, y_max = int(center_x - size // 2), int(center_y - size // 2), int(
+ center_x + size // 2), int(center_y + size // 2)
+
+ # 确定裁剪区域上边top和左边left坐标
+ top = y_min
+ left = x_min
+ # 裁剪区域与原图的重合区域
+ top_coincidence = int(max(top, 0))
+ bottom_coincidence = int(min(y_max, vid_height))
+ left_coincidence = int(max(left, 0))
+ right_coincidence = int(min(x_max, vid_width))
+
+ scale = out_size / size
+ pts_3d = (pts_3d - np.array([left, top, 0])) * scale
+ pts_3d = pts_3d
+
+ face_rect = np.array([center_x, center_y, size])
+ print(np.array([x_min, y_min, x_max, y_max]))
+
+ img_array = np.zeros([len(frames_list), out_size, out_size, 3], dtype = np.uint8)
+ for index, frame in tqdm.tqdm(enumerate(frames_list)):
+ img_new = np.zeros([size, size, 3], dtype=np.uint8)
+ img_new[top_coincidence - top:bottom_coincidence - top, left_coincidence - left:right_coincidence - left,:] = \
+ frame[top_coincidence:bottom_coincidence, left_coincidence:right_coincidence, :]
+ img_new = cv2.resize(img_new, (out_size, out_size))
+ img_array[index] = img_new
+ return pts_3d,img_array, face_rect
+
diff --git a/talkingface/util/visualizer.py b/talkingface/util/visualizer.py
new file mode 100644
index 0000000..b6bb884
--- /dev/null
+++ b/talkingface/util/visualizer.py
@@ -0,0 +1,257 @@
+import numpy as np
+import os
+import sys
+import ntpath
+import time
+from . import util, html
+from subprocess import Popen, PIPE
+
+
+try:
+ import wandb
+except ImportError:
+ print('Warning: wandb package cannot be found. The option "--use_wandb" will result in error.')
+
+if sys.version_info[0] == 2:
+ VisdomExceptionBase = Exception
+else:
+ VisdomExceptionBase = ConnectionError
+
+
+def save_images(webpage, visuals, image_path, aspect_ratio=1.0, width=256, use_wandb=False):
+ """Save images to the disk.
+
+ Parameters:
+ webpage (the HTML class) -- the HTML webpage class that stores these imaegs (see html.py for more details)
+ visuals (OrderedDict) -- an ordered dictionary that stores (name, images (either tensor or numpy) ) pairs
+ image_path (str) -- the string is used to create image paths
+ aspect_ratio (float) -- the aspect ratio of saved images
+ width (int) -- the images will be resized to width x width
+
+ This function will save images stored in 'visuals' to the HTML file specified by 'webpage'.
+ """
+ image_dir = webpage.get_image_dir()
+ short_path = ntpath.basename(image_path[0])
+ name = os.path.splitext(short_path)[0]
+
+ webpage.add_header(name)
+ ims, txts, links = [], [], []
+ ims_dict = {}
+ for label, im_data in visuals.items():
+ im = util.tensor2im(im_data)
+ image_name = '%s_%s.png' % (name, label)
+ save_path = os.path.join(image_dir, image_name)
+ util.save_image(im, save_path, aspect_ratio=aspect_ratio)
+ ims.append(image_name)
+ txts.append(label)
+ links.append(image_name)
+ if use_wandb:
+ ims_dict[label] = wandb.Image(im)
+ webpage.add_images(ims, txts, links, width=width)
+ if use_wandb:
+ wandb.log(ims_dict)
+
+
+class Visualizer():
+ """This class includes several functions that can display/save images and print/save logging information.
+
+ It uses a Python library 'visdom' for display, and a Python library 'dominate' (wrapped in 'HTML') for creating HTML files with images.
+ """
+
+ def __init__(self, opt):
+ """Initialize the Visualizer class
+
+ Parameters:
+ opt -- stores all the experiment flags; needs to be a subclass of BaseOptions
+ Step 1: Cache the training/test options
+ Step 2: connect to a visdom server
+ Step 3: create an HTML object for saveing HTML filters
+ Step 4: create a logging file to store training losses
+ """
+ self.opt = opt # cache the option
+ self.display_id = opt.display_id
+ self.use_html = opt.isTrain and not opt.no_html
+ self.win_size = opt.display_winsize
+ self.name = opt.name
+ self.port = opt.display_port
+ self.saved = False
+ self.use_wandb = opt.use_wandb
+ self.wandb_project_name = opt.wandb_project_name
+ self.current_epoch = 0
+ self.ncols = opt.display_ncols
+
+ if self.display_id > 0: # connect to a visdom server given and
+ import visdom
+ self.vis = visdom.Visdom(server=opt.display_server, port=opt.display_port, env=opt.display_env)
+ if not self.vis.check_connection():
+ self.create_visdom_connections()
+
+ if self.use_wandb:
+ self.wandb_run = wandb.init(project=self.wandb_project_name, name=opt.name, config=opt) if not wandb.run else wandb.run
+ self.wandb_run._label(repo='CycleGAN-and-pix2pix')
+
+ if self.use_html: # create an HTML object at /web/; images will be saved under /web/images/
+ self.web_dir = os.path.join(opt.checkpoints_dir, opt.name, 'web')
+ self.img_dir = os.path.join(self.web_dir, 'images')
+ print('create web directory %s...' % self.web_dir)
+ util.mkdirs([self.web_dir, self.img_dir])
+ # create a logging file to store training losses
+ self.log_name = os.path.join(opt.checkpoints_dir, opt.name, 'loss_log.txt')
+ with open(self.log_name, "a") as log_file:
+ now = time.strftime("%c")
+ log_file.write('================ Training Loss (%s) ================\n' % now)
+
+ def reset(self):
+ """Reset the self.saved status"""
+ self.saved = False
+
+ def create_visdom_connections(self):
+ """If the program could not connect to Visdom server, this function will start a new server at port < self.port > """
+ cmd = sys.executable + ' -m visdom.server -p %d &>/dev/null &' % self.port
+ print('\n\nCould not connect to Visdom server. \n Trying to start a server....')
+ print('Command: %s' % cmd)
+ Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE)
+
+ def display_current_results(self, visuals, epoch, save_result):
+ """Display current results on visdom; save current results to an HTML file.
+
+ Parameters:
+ visuals (OrderedDict) - - dictionary of images to display or save
+ epoch (int) - - the current epoch
+ save_result (bool) - - if save the current results to an HTML file
+ """
+ if self.display_id > 0: # show images in the browser using visdom
+ ncols = self.ncols
+ if ncols > 0: # show all the images in one visdom panel
+ ncols = min(ncols, len(visuals))
+ h, w = next(iter(visuals.values())).shape[:2]
+ table_css = """""" % (w, h) # create a table css
+ # create a table of images.
+ title = self.name
+ label_html = ''
+ label_html_row = ''
+ images = []
+ idx = 0
+ for label, image in visuals.items():
+ image_numpy = util.tensor2im(image)
+ label_html_row += '%s | ' % label
+ images.append(image_numpy.transpose([2, 0, 1]))
+ idx += 1
+ if idx % ncols == 0:
+ label_html += '%s
' % label_html_row
+ label_html_row = ''
+ white_image = np.ones_like(image_numpy.transpose([2, 0, 1])) * 255
+ while idx % ncols != 0:
+ images.append(white_image)
+ label_html_row += ' | '
+ idx += 1
+ if label_html_row != '':
+ label_html += '%s
' % label_html_row
+ try:
+ self.vis.images(images, nrow=ncols, win=self.display_id + 1,
+ padding=2, opts=dict(title=title + ' images'))
+ label_html = '' % label_html
+ self.vis.text(table_css + label_html, win=self.display_id + 2,
+ opts=dict(title=title + ' labels'))
+ except VisdomExceptionBase:
+ self.create_visdom_connections()
+
+ else: # show each image in a separate visdom panel;
+ idx = 1
+ try:
+ for label, image in visuals.items():
+ image_numpy = util.tensor2im(image)
+ self.vis.image(image_numpy.transpose([2, 0, 1]), opts=dict(title=label),
+ win=self.display_id + idx)
+ idx += 1
+ except VisdomExceptionBase:
+ self.create_visdom_connections()
+
+ if self.use_wandb:
+ columns = [key for key, _ in visuals.items()]
+ columns.insert(0, 'epoch')
+ result_table = wandb.Table(columns=columns)
+ table_row = [epoch]
+ ims_dict = {}
+ for label, image in visuals.items():
+ image_numpy = util.tensor2im(image)
+ wandb_image = wandb.Image(image_numpy)
+ table_row.append(wandb_image)
+ ims_dict[label] = wandb_image
+ self.wandb_run.log(ims_dict)
+ if epoch != self.current_epoch:
+ self.current_epoch = epoch
+ result_table.add_data(*table_row)
+ self.wandb_run.log({"Result": result_table})
+
+ if self.use_html and (save_result or not self.saved): # save images to an HTML file if they haven't been saved.
+ self.saved = True
+ # save images to the disk
+ for label, image in visuals.items():
+ image_numpy = util.tensor2im(image)
+ img_path = os.path.join(self.img_dir, 'epoch%.3d_%s.png' % (epoch, label))
+ util.save_image(image_numpy, img_path)
+
+ # update website
+ webpage = html.HTML(self.web_dir, 'Experiment name = %s' % self.name, refresh=1)
+ for n in range(epoch, 0, -1):
+ webpage.add_header('epoch [%d]' % n)
+ ims, txts, links = [], [], []
+
+ for label, image_numpy in visuals.items():
+ image_numpy = util.tensor2im(image)
+ img_path = 'epoch%.3d_%s.png' % (n, label)
+ ims.append(img_path)
+ txts.append(label)
+ links.append(img_path)
+ webpage.add_images(ims, txts, links, width=self.win_size)
+ webpage.save()
+
+ def plot_current_losses(self, epoch, counter_ratio, losses):
+ """display the current losses on visdom display: dictionary of error labels and values
+
+ Parameters:
+ epoch (int) -- current epoch
+ counter_ratio (float) -- progress (percentage) in the current epoch, between 0 to 1
+ losses (OrderedDict) -- training losses stored in the format of (name, float) pairs
+ """
+ if not hasattr(self, 'plot_data'):
+ self.plot_data = {'X': [], 'Y': [], 'legend': list(losses.keys())}
+ self.plot_data['X'].append(epoch + counter_ratio)
+ self.plot_data['Y'].append([losses[k] for k in self.plot_data['legend']])
+ try:
+ self.vis.line(
+ X=np.stack([np.array(self.plot_data['X'])] * len(self.plot_data['legend']), 1),
+ Y=np.array(self.plot_data['Y']),
+ opts={
+ 'title': self.name + ' loss over time',
+ 'legend': self.plot_data['legend'],
+ 'xlabel': 'epoch',
+ 'ylabel': 'loss'},
+ win=self.display_id)
+ except VisdomExceptionBase:
+ self.create_visdom_connections()
+ if self.use_wandb:
+ self.wandb_run.log(losses)
+
+ # losses: same format as |losses| of plot_current_losses
+ def print_current_losses(self, epoch, iters, losses, t_comp, t_data):
+ """print current losses on console; also save the losses to the disk
+
+ Parameters:
+ epoch (int) -- current epoch
+ iters (int) -- current training iteration during this epoch (reset to 0 at the end of every epoch)
+ losses (OrderedDict) -- training losses stored in the format of (name, float) pairs
+ t_comp (float) -- computational time per data point (normalized by batch_size)
+ t_data (float) -- data loading time per data point (normalized by batch_size)
+ """
+ message = '(epoch: %d, iters: %d, time: %.3f, data: %.3f) ' % (epoch, iters, t_comp, t_data)
+ for k, v in losses.items():
+ message += '%s: %.3f ' % (k, v)
+
+ print(message) # print the message
+ with open(self.log_name, "a") as log_file:
+ log_file.write('%s\n' % message) # save the message
diff --git a/talkingface/utils.py b/talkingface/utils.py
new file mode 100644
index 0000000..60c23c5
--- /dev/null
+++ b/talkingface/utils.py
@@ -0,0 +1,329 @@
+import numpy as np
+import random
+import cv2
+
+INDEX_LEFT_EYEBROW = [276, 283, 282, 295, 285, 336, 296, 334, 293, 300]
+INDEX_RIGHT_EYEBROW = [46, 53, 52, 65, 55, 107, 66, 105, 63, 70]
+INDEX_EYEBROW = INDEX_LEFT_EYEBROW + INDEX_RIGHT_EYEBROW
+
+INDEX_NOSE_EDGE = [343, 355, 358, 327, 326, 2, 97, 98, 129, 126, 114]
+INDEX_NOSE_MID = [6, 197,195,5,4]
+INDEX_NOSE = INDEX_NOSE_EDGE + INDEX_NOSE_MID
+
+INDEX_LIPS_INNER = [78, 95, 88, 178, 87, 14, 317, 402, 318, 324,308,415,310,311,312,13,82,81,80,191]
+INDEX_LIPS_OUTER = [61, 146, 91, 181, 84, 17, 314, 405, 321, 375, 291,409,270,269,267,0,37,39,40,185,]
+INDEX_LIPS = INDEX_LIPS_INNER + INDEX_LIPS_OUTER
+
+INDEX_LEFT_EYE = [263, 249, 390, 373, 374, 380, 381, 382, 362, 398, 384, 385, 386, 387, 388, 466]
+INDEX_RIGHT_EYE = [33, 7, 163, 144, 145, 153, 154, 155, 133, 173, 157, 158, 159, 160, 161, 246]
+INDEX_EYE = INDEX_LEFT_EYE + INDEX_RIGHT_EYE
+# 下半边脸的轮廓
+INDEX_FACE_OVAL = [
+ 454, 323, 361, 288, 397, 365,
+ 379, 378, 400, 377, 152, 148, 176, 149, 150,
+ 136, 172, 58, 132, 93, 234,
+ # 206, 426
+]
+
+INDEX_MUSCLE = [
+ 371,266,425,427,434,394,
+ 169,214,207,205,36,142
+]
+
+main_keypoints_index = INDEX_EYEBROW + INDEX_NOSE + INDEX_LIPS + INDEX_EYE + INDEX_FACE_OVAL + INDEX_MUSCLE
+
+rotate_ref_index = INDEX_EYEBROW + INDEX_NOSE + INDEX_EYE + INDEX_FACE_OVAL + INDEX_MUSCLE
+# print(len(main_keypoints_index))
+Normalized = True
+if Normalized:
+ tmp = 0
+ list_ = []
+ for i in [INDEX_LEFT_EYEBROW, INDEX_RIGHT_EYEBROW, INDEX_NOSE_EDGE, INDEX_NOSE_MID, INDEX_LIPS_INNER, INDEX_LIPS_OUTER, INDEX_LEFT_EYE, INDEX_RIGHT_EYE, INDEX_FACE_OVAL, INDEX_MUSCLE]:
+ i = (tmp + np.arange(len(i))).tolist()
+ list_.append(i)
+ tmp += len(i)
+[INDEX_LEFT_EYEBROW, INDEX_RIGHT_EYEBROW, INDEX_NOSE_EDGE, INDEX_NOSE_MID, INDEX_LIPS_INNER, INDEX_LIPS_OUTER, INDEX_LEFT_EYE, INDEX_RIGHT_EYE, INDEX_FACE_OVAL, INDEX_MUSCLE] = list_
+INDEX_EYEBROW = INDEX_LEFT_EYEBROW + INDEX_RIGHT_EYEBROW
+INDEX_NOSE = INDEX_NOSE_EDGE + INDEX_NOSE_MID
+INDEX_LIPS = INDEX_LIPS_INNER + INDEX_LIPS_OUTER
+INDEX_EYE = INDEX_LEFT_EYE + INDEX_RIGHT_EYE
+
+INDEX_LIPS_LOWER = INDEX_LIPS_INNER[:11] + INDEX_LIPS_OUTER[:11][::-1]
+INDEX_LIPS_UPPER = INDEX_LIPS_INNER[10:] + [INDEX_LIPS_INNER[0], INDEX_LIPS_OUTER[0]] + INDEX_LIPS_OUTER[10:][::-1]
+
+FACE_MASK_INDEX = INDEX_FACE_OVAL[2:-2]
+def crop_face(keypoints, is_train = False, size = [512, 512]):
+ """
+ x_ratio: 裁剪出一个正方形,边长根据keypoints的宽度 * x_ratio决定
+ """
+ x_min, y_min, x_max, y_max = np.min(keypoints[FACE_MASK_INDEX, 0]), np.min(keypoints[FACE_MASK_INDEX, 1]), np.max(keypoints[FACE_MASK_INDEX, 0]), np.max(
+ keypoints[FACE_MASK_INDEX, 1])
+ y_min = keypoints[33, 1] # 两眼间的点开始y轴裁剪
+ border_width_half = max(x_max - x_min, y_max - y_min) * 0.6
+ center_x = int((x_min + x_max) / 2.0)
+ center_y = int((y_min + y_max) / 2.0)
+ if is_train:
+ w_offset = random.randint(-2, 2)
+ h_offset = random.randint(-2, 2)
+ center_x = center_x + w_offset
+ center_y = center_y + h_offset
+ x_min, y_min, x_max, y_max = int(center_x - border_width_half), int(center_y - border_width_half), int(
+ center_x + border_width_half), int(center_y + border_width_half)
+ x_min = max(0, x_min)
+ y_min = max(0, y_min)
+ x_max = min(size[1], x_max)
+ y_max = min(size[0], y_max)
+ return [x_min, y_min, x_max, y_max]
+
+def crop_mouth(pts_array_origin, img_w, img_h, is_train = False):
+ center_x = np.mean(pts_array_origin[INDEX_LIPS_OUTER, 0])
+ center_y = np.mean(pts_array_origin[INDEX_LIPS_OUTER, 1])
+ x_min, y_min, x_max, y_max = np.min(pts_array_origin[INDEX_FACE_OVAL[2:-2], 0]), np.min(
+ pts_array_origin[INDEX_FACE_OVAL[2:-2], 1]), np.max(
+ pts_array_origin[INDEX_FACE_OVAL[2:-2], 0]), np.max(pts_array_origin[INDEX_FACE_OVAL[2:-2], 1])
+ x_min = max(0, x_min)
+ y_min = max(0, y_min)
+ x_max = min(x_max, img_w)
+ y_max = min(y_max, img_h)
+ new_size = max((x_max - x_min), (y_max - y_min))*0.46
+
+ if is_train:
+ h_offset = int(new_size * 0.04)
+ h_offset = random.randint(-h_offset, h_offset)
+ center_y = center_y + h_offset
+
+ x_min, y_min, x_max, y_max = int(center_x - new_size), int(center_y - new_size*0.89), int(
+ center_x + new_size), int(center_y + new_size*1.11)
+
+ x_min = max(0, x_min)
+ y_min = max(0, y_min)
+ x_max = min(img_w, x_max)
+ y_max = min(img_h, y_max)
+ return np.array([x_min, y_min, x_max, y_max])
+
+def draw_mouth_maps(keypoints, size=(256, 256), im_edges = None):
+ w, h = size
+ # edge map for face region from keypoints
+ if im_edges is None:
+ im_edges = np.zeros((h, w, 3), np.uint8) # edge map for all edges
+ pts = keypoints[INDEX_LIPS_OUTER, :2]
+ pts = pts.reshape((-1, 1, 2)).astype(np.int32)
+ cv2.fillPoly(im_edges, [pts], color=(0, 0, 0))
+
+ pts = keypoints[INDEX_LIPS_UPPER, :2]
+ pts = pts.reshape((-1, 1, 2)).astype(np.int32)
+ cv2.fillPoly(im_edges, [pts], color=(255, 0, 0))
+ pts = keypoints[INDEX_LIPS_LOWER, :2]
+ pts = pts.reshape((-1, 1, 2)).astype(np.int32)
+ cv2.fillPoly(im_edges, [pts], color=(127, 0, 0))
+ return im_edges
+
+def draw_face_feature_maps(keypoints, mode = ["mouth", "nose", "eye", "oval"], size=(256, 256), im_edges = None, mouth_width = None, mouth_height = None):
+ w, h = size
+ # edge map for face region from keypoints
+ if im_edges is None:
+ im_edges = np.zeros((h, w, 3), np.uint8) # edge map for all edges
+
+ if "mouth_bias" in mode:
+
+ w0, w1, h0, h1 = (int(keypoints[INDEX_NOSE_EDGE[5], 0] - mouth_width / 2),
+ int(keypoints[INDEX_NOSE_EDGE[5], 0] + mouth_width / 2),
+ int(keypoints[INDEX_NOSE_EDGE[5], 1] + mouth_height / 4),
+ int(keypoints[INDEX_NOSE_EDGE[5], 1] + mouth_height / 4 + mouth_height))
+ w0, h0 = max(0, w0), max(h0, 0)
+ # print(w0, w1, h0, h1)
+ mouth_mask = np.zeros((h, w, 3), np.uint8) # edge map for all edges
+ mouth_mask[h0:h1, w0:w1] = 255
+ mouth_index = np.where(mouth_mask == 255)
+ blur = (10, 10)
+ img_mouth = cv2.cvtColor(im_edges, cv2.COLOR_BGR2GRAY)
+ img_mouth = cv2.blur(img_mouth, blur)
+ # print(mouth_index)
+ mean_ = int(np.mean(img_mouth[(mouth_index[0], mouth_index[1])]))
+ max_, min_ = random.randint(mean_ + 40, mean_ + 70), random.randint(mean_ - 70, mean_ - 40)
+ img_mouth = (img_mouth.astype(np.float32) - min_) / (max_ - min_) * 255.
+ img_mouth = img_mouth.clip(0, 255).astype(np.uint8)
+ # print(img_mouth.shape[0], img_mouth.shape[1])
+ img_mouth = cv2.resize(img_mouth, (100, 50))
+
+ # 定义噪声的标准差
+ sigma = 8 # 你可以根据需要调整这个值
+ # 生成与图片相同大小和类型的噪声
+ noise = sigma * np.random.randn(img_mouth.shape[0], img_mouth.shape[1])
+ # 将噪声添加到图片上
+ img_mouth = img_mouth + noise
+ img_mouth = cv2.resize(img_mouth.clip(0, 255).astype(np.uint8), (im_edges.shape[0], im_edges.shape[1]))
+
+ img_mouth = np.concatenate(
+ [img_mouth[:, :, np.newaxis], img_mouth[:, :, np.newaxis], img_mouth[:, :, np.newaxis]], axis=2)
+
+ # bias_x = int(min(size[0] - max(mouth_index[0]), min(mouth_index[0])))
+ # bias_y = int(min(size[0] - max(mouth_index[1]), min(mouth_index[1])))
+ # print(bias_x, bias_y)
+ # bias_x = random.randint(-bias_x // 10, bias_x // 10)
+ # bias_y = random.randint(-bias_y // 10, bias_y // 10)
+ #
+ # mouth_index2 = np.array(mouth_index)
+ # # print(mouth_index)
+ # mouth_index2[0] = mouth_index[0] + bias_x
+ # mouth_index2[1] = mouth_index[1] + bias_y
+ # mouth_index2 = (mouth_index2[0], mouth_index2[1], mouth_index2[2])
+ # # print(mouth_index2.T, mouth_index2.shape)
+ #
+ output = np.zeros((h, w, 3), np.uint8)
+ # output[mouth_index2] = img_mouth[mouth_index]
+ # return im_edges
+ output[mouth_index] = img_mouth[mouth_index]
+ im_edges = output
+ if "nose" in mode:
+ for ii in range(len(INDEX_NOSE_EDGE) - 1):
+ pt1 = [int(flt) for flt in keypoints[INDEX_NOSE_EDGE[ii]]][:2]
+ pt2 = [int(flt) for flt in keypoints[INDEX_NOSE_EDGE[ii+1]]][:2]
+ cv2.line(im_edges, tuple(pt1), tuple(pt2), (0, 255, 0), 2)
+ for ii in range(len(INDEX_NOSE_MID) -1):
+ pt1 = [int(flt) for flt in keypoints[INDEX_NOSE_MID[ii]]][:2]
+ pt2 = [int(flt) for flt in keypoints[INDEX_NOSE_MID[ii + 1]]][:2]
+ cv2.line(im_edges, tuple(pt1), tuple(pt2), (0, 255, 0), 2)
+ if "eye" in mode:
+ for ii in range(len(INDEX_LEFT_EYE)):
+ pt1 = [int(flt) for flt in keypoints[INDEX_LEFT_EYE[ii]]][:2]
+ pt2 = [int(flt) for flt in keypoints[INDEX_LEFT_EYE[(ii + 1)%len(INDEX_LEFT_EYE)]]][:2]
+ cv2.line(im_edges, tuple(pt1), tuple(pt2), (0, 255, 0), 2)
+ for ii in range(len(INDEX_RIGHT_EYE)):
+ pt1 = [int(flt) for flt in keypoints[INDEX_RIGHT_EYE[ii]]][:2]
+ pt2 = [int(flt) for flt in keypoints[INDEX_RIGHT_EYE[(ii + 1) % len(INDEX_RIGHT_EYE)]]][:2]
+ cv2.line(im_edges, tuple(pt1), tuple(pt2), (0, 255, 0), 2)
+ if "oval" in mode:
+ tmp = INDEX_FACE_OVAL[:6]
+ for ii in range(len(tmp) -1):
+ pt1 = [int(flt) for flt in keypoints[tmp[ii]]][:2]
+ pt2 = [int(flt) for flt in keypoints[tmp[ii + 1]]][:2]
+ cv2.line(im_edges, tuple(pt1), tuple(pt2), (0, 0, 255), 2)
+ tmp = INDEX_FACE_OVAL[-6:]
+ for ii in range(len(tmp) - 1):
+ pt1 = [int(flt) for flt in keypoints[tmp[ii]]][:2]
+ pt2 = [int(flt) for flt in keypoints[tmp[ii + 1]]][:2]
+ cv2.line(im_edges, tuple(pt1), tuple(pt2), (0, 0, 255), 2)
+
+ # if "mouth_outer" in mode:
+ # pts = keypoints[INDEX_LIPS_OUTER]
+ # pts = pts.reshape((-1, 1, 2)).astype(np.int32)
+ # cv2.fillPoly(im_edges, [pts], color=(255, 0, 0))
+ # if "mouth" in mode:
+ # pts = keypoints[INDEX_LIPS_OUTER][:,2]
+ # pts = pts.reshape((-1, 1, 2)).astype(np.int32)
+ # cv2.fillPoly(im_edges, [pts], color=(255, 0, 0))
+ # pts = keypoints[INDEX_LIPS_INNER][:,2]
+ # pts = pts.reshape((-1, 1, 2)).astype(np.int32)
+ # cv2.fillPoly(im_edges, [pts], color=(0, 0, 0))
+ # if "mouth_outer" in mode:
+ # for ii in range(len(INDEX_LIPS_OUTER)):
+ # pt1 = [int(flt) for flt in keypoints[INDEX_LIPS_OUTER[ii]]][:2]
+ # pt2 = [int(flt) for flt in keypoints[INDEX_LIPS_OUTER[(ii + 1)%len(INDEX_LIPS_OUTER)]]][:2]
+ # cv2.line(im_edges, tuple(pt1), tuple(pt2), (255, 0, 0), 2)
+
+
+
+ if "mouth" in mode:
+ for ii in range(len(INDEX_LIPS_OUTER)):
+ pt1 = [int(flt) for flt in keypoints[INDEX_LIPS_OUTER[ii]]][:2]
+ pt2 = [int(flt) for flt in keypoints[INDEX_LIPS_OUTER[(ii + 1)%len(INDEX_LIPS_OUTER)]]][:2]
+ cv2.line(im_edges, tuple(pt1), tuple(pt2), (255, 0, 0), 2)
+ for ii in range(len(INDEX_LIPS_INNER)):
+ pt1 = [int(flt) for flt in keypoints[INDEX_LIPS_INNER[ii]]][:2]
+ pt2 = [int(flt) for flt in keypoints[INDEX_LIPS_INNER[(ii + 1)%len(INDEX_LIPS_INNER)]]][:2]
+ cv2.line(im_edges, tuple(pt1), tuple(pt2), (255, 0, 0), 2)
+ if "muscle" in mode:
+ for ii in range(len(INDEX_MUSCLE) - 1):
+ pt1 = [int(flt) for flt in keypoints[INDEX_MUSCLE[ii]]][:2]
+ pt2 = [int(flt) for flt in keypoints[INDEX_MUSCLE[(ii + 1) % len(INDEX_MUSCLE)]]][:2]
+ cv2.line(im_edges, tuple(pt1), tuple(pt2), (255, 255, 255), 2)
+
+ if "oval_all" in mode:
+ tmp = INDEX_FACE_OVAL
+ for ii in range(len(tmp) -1):
+ pt1 = [int(flt) for flt in keypoints[tmp[ii]]][:2]
+ pt2 = [int(flt) for flt in keypoints[tmp[ii + 1]]][:2]
+ cv2.line(im_edges, tuple(pt1), tuple(pt2), (0, 0, 255), 2)
+
+ return im_edges
+
+def smooth_array(array, weight = [0.1,0.8,0.1], mode = "numpy"):
+ '''
+
+ Args:
+ array: [n_frames, n_values], 需要转换为[n_values, 1, n_frames]
+ weight: Conv1d.weight, 一维卷积核权重
+ Returns:
+ array: [n_frames, n_values], 光滑后的array
+ '''
+ if mode == "torch":
+ import torch
+ import torch.nn as nn
+ import torch.nn.functional as F
+ input = torch.Tensor(np.transpose(array[:, np.newaxis, :], (2, 1, 0)))
+ smooth_length = len(weight)
+ assert smooth_length % 2 == 1, "卷积核权重个数必须使用奇数"
+ pad = (smooth_length // 2, smooth_length // 2) # 当pad只有两个参数时,仅改变最后一个维度, 左边扩充1列,右边扩充1列
+ input = F.pad(input, pad, "replicate")
+
+ with torch.no_grad():
+ conv1 = nn.Conv1d(in_channels=1, out_channels=1, kernel_size=smooth_length)
+ # 卷积核的元素值初始化
+ weight = torch.tensor(weight).view(1, 1, -1)
+ conv1.weight = torch.nn.Parameter(weight)
+ nn.init.constant_(conv1.bias, 0) # 偏置值为0
+ # print(conv1.weight)
+ out = conv1(input)
+ return out.permute(2, 1, 0).squeeze().numpy()
+ else:
+ # out = np.zeros([array.shape[0] + 2, array.shape[1]])
+ # input = np.zeros([array.shape[0] + 2, array.shape[1]])
+ # input[0] = array[0]
+ # input[-1] = array[-1]
+ # input[1:-1] = array
+ # for i in range(out.shape[1]):
+ # out[:, i] = np.convolve(input[:, i], weight, mode="same")
+ # out0 = out[1:-1]
+ smooth_length = len(weight)
+ assert smooth_length % 2 == 1, "卷积核权重个数必须使用奇数"
+ pad = smooth_length // 2
+ fliter = np.array([weight]).T
+ x0 = array
+ fliter = np.repeat(fliter, x0.shape[1], axis=1)
+ out0 = np.zeros_like(x0)
+ for i in range(len(x0)):
+ if i < pad or i >= len(x0) - pad:
+ out0[i] = x0[i]
+ else:
+ tmp = x0[i - pad:i + pad + 1] * fliter
+ out0[i] = np.sum(tmp, axis=0)
+ return out0
+
+def generate_face_mask():
+ face_mask = np.zeros([256, 256], dtype=np.uint8)
+ for i in range(20):
+ ii = 19 - i
+ face_mask[ii, :] = 13 * i
+ face_mask[255 - ii, :] = 13 * i
+ face_mask[:, ii] = 13 * i
+ face_mask[:, 255 - ii] = 13 * i
+ face_mask = np.array([face_mask, face_mask, face_mask]).transpose(1, 2, 0).astype(float) / 255.
+ print(face_mask.shape)
+ return face_mask
+
+from math import cos,sin,radians
+def RotateAngle2Matrix(tmp): #tmp为xyz的旋转角,角度值
+ tmp = [radians(i) for i in tmp]
+ matX = np.array([[1.0, 0, 0],
+ [0.0, cos(tmp[0]), -sin(tmp[0])],
+ [0.0, sin(tmp[0]), cos(tmp[0])]])
+ matY = np.array([[cos(tmp[1]), 0, sin(tmp[1])],
+ [0.0, 1, 0],
+ [-sin(tmp[1]), 0, cos(tmp[1])]])
+ matZ = np.array([[cos(tmp[2]), -sin(tmp[2]), 0],
+ [sin(tmp[2]), cos(tmp[2]), 0],
+ [0, 0, 1]])
+ matRotate = np.matmul(matZ, matY)
+ matRotate = np.matmul(matRotate, matX)
+ return matRotate
\ No newline at end of file
diff --git a/train/README.md b/train/README.md
new file mode 100644
index 0000000..b1d2c90
--- /dev/null
+++ b/train/README.md
@@ -0,0 +1,60 @@
+## Overview
+This project involves training two separate models for a face generation system: an audio model to extract mouth movement patterns and a rendering model to generate the final face. Each model requires its own data preparation and training process.
+## Audio Model Training (LSTM)
+The audio model is distilled from other models and is designed to extract mouth movement patterns from audio input. The code for this model will be released soon.
+## Render Model Training (simplified DiNet)
+### Original Data Structure
+Please ensure that your data directory structure is organized as follows:
+```bash
+|--/dir_to_data
+| |--/video0.mp4
+| |--/video1.mp4
+| |--/video2.mp4
+```
+### Data Preparation
+Next, prepare your video using the data_preparation script. Replace YOUR_VIDEO_PATH with the path to your video:
+```bash
+python train/data_preparation_face.py dir_to_data
+```
+After running the script, your data directory structure should be updated to:
+```bash
+|--/dir_to_data
+| |--/video0
+| | |--/keypoint_rotate.pkl
+| | |--/face_mat_mask.pkl
+| | |--/image
+| | |--/000000.png
+| | |--/000001.png
+| | |--/...
+| |--/video1
+| | |--/keypoint_rotate.pkl
+| | |--/face_mat_mask.pkl
+| | |--/image
+| | |--/000000.png
+| | |--/000001.png
+| | |--/...
+```
+### Data Validation
+Verify the prepared data using the following script:
+```bash
+python train/train_input_validation_render_model.py dir_to_data
+```
+you will get the following image:
+![](validation.jpg)
+### Training
+```bash
+python train/train_render_model.py --train_data dir_to_data
+```
+### Monitoring Training Progress
+Monitor the training progress using TensorBoard.
+```bash
+tensorboard --logdir=checkpoint/Dinet_five_ref
+```
+Then, open http://localhost:6006/ in your web browser to view the training metrics.
+
+### Downloading the Pre-trained Model
+A pre-trained model can be accessed via both Baidu Netdisk and Google Drive.
+
+ [Baidu Netdisk](https://pan.baidu.com/s/1oB7kJl6xf70t1P3rVkypRQ?pwd=ym7k) Extraction Code: ym7k
+
+ [Google Drive](https://drive.google.com/file/d/108-cmzzDglGROMwi-CQ91Eijx1aBGur-/view?usp=drive_link)
diff --git a/train/data_preparation_face.py b/train/data_preparation_face.py
new file mode 100644
index 0000000..e1aea76
--- /dev/null
+++ b/train/data_preparation_face.py
@@ -0,0 +1,269 @@
+import os
+os.environ["KMP_DUPLICATE_LIB_OK"] = "true"
+current_dir = os.path.dirname(os.path.abspath(__file__))
+import sys
+sys.path.append(os.path.join(current_dir, ".."))
+# sys.path.append("..")
+import uuid
+import tqdm
+import numpy as np
+import cv2
+import glob
+import math
+import pickle
+from talkingface.util.smooth import smooth_array
+from talkingface.run_utils import calc_face_mat
+import tqdm
+from talkingface.utils import *
+import mediapipe as mp
+
+mp_face_mesh = mp.solutions.face_mesh
+mp_face_detection = mp.solutions.face_detection
+point_size = 1
+point_color = (0, 0, 255) # BGR
+thickness = 4 # 0 、4、8
+def detect_face(frame):
+ # 剔除掉多个人脸、大角度侧脸(鼻子不在两个眼之间)、部分人脸框在画面外、人脸像素低于80*80的
+ with mp_face_detection.FaceDetection(
+ model_selection=1, min_detection_confidence=0.5) as face_detection:
+ results = face_detection.process(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
+ if not results.detections or len(results.detections) > 1:
+ return -1, None
+ rect = results.detections[0].location_data.relative_bounding_box
+ out_rect = [rect.xmin, rect.xmin + rect.width, rect.ymin, rect.ymin + rect.height]
+ nose_ = mp_face_detection.get_key_point(
+ results.detections[0], mp_face_detection.FaceKeyPoint.NOSE_TIP)
+ l_eye_ = mp_face_detection.get_key_point(
+ results.detections[0], mp_face_detection.FaceKeyPoint.LEFT_EYE)
+ r_eye_ = mp_face_detection.get_key_point(
+ results.detections[0], mp_face_detection.FaceKeyPoint.RIGHT_EYE)
+ # print(nose_, l_eye_, r_eye_)
+ if nose_.x > l_eye_.x or nose_.x < r_eye_.x:
+ return -2, out_rect
+
+ h, w = frame.shape[:2]
+ # print(frame.shape)
+ if rect.xmin < 0 or rect.ymin < 0 or rect.xmin + rect.width > w or rect.ymin + rect.height > h:
+ return -3, out_rect
+ if rect.width * w < 100 or rect.height * h < 100:
+ return -4, out_rect
+ return 1, out_rect
+
+
+def calc_face_interact(face0, face1):
+ x_min = min(face0[0], face1[0])
+ x_max = max(face0[1], face1[1])
+ y_min = min(face0[2], face1[2])
+ y_max = max(face0[3], face1[3])
+ tmp0 = ((face0[1] - face0[0]) * (face0[3] - face0[2])) / ((x_max - x_min) * (y_max - y_min))
+ tmp1 = ((face1[1] - face1[0]) * (face1[3] - face1[2])) / ((x_max - x_min) * (y_max - y_min))
+ return min(tmp0, tmp1)
+
+
+def detect_face_mesh(frame):
+ with mp_face_mesh.FaceMesh(
+ static_image_mode=True,
+ max_num_faces=1,
+ refine_landmarks=True,
+ min_detection_confidence=0.5) as face_mesh:
+ results = face_mesh.process(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
+ pts_3d = np.zeros([478, 3])
+ if not results.multi_face_landmarks:
+ print("****** WARNING! No face detected! ******")
+ else:
+ image_height, image_width = frame.shape[:2]
+ for face_landmarks in results.multi_face_landmarks:
+ for index_, i in enumerate(face_landmarks.landmark):
+ x_px = min(math.floor(i.x * image_width), image_width - 1)
+ y_px = min(math.floor(i.y * image_height), image_height - 1)
+ z_px = min(math.floor(i.z * image_width), image_width - 1)
+ pts_3d[index_] = np.array([x_px, y_px, z_px])
+ return pts_3d
+
+
+def ExtractFromVideo(video_path, circle = False):
+ cap = cv2.VideoCapture(video_path)
+ if not cap.isOpened():
+ return 0
+
+ dir_path = os.path.dirname(video_path)
+ vid_width = cap.get(cv2.CAP_PROP_FRAME_WIDTH) # 宽度
+ vid_height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT) # 高度
+
+ totalFrames = cap.get(cv2.CAP_PROP_FRAME_COUNT) # 总帧数
+ totalFrames = int(totalFrames)
+ pts_3d = np.zeros([totalFrames, 478, 3])
+ face_rect_list = []
+
+ # os.makedirs("../preparation/{}/image".format(model_name))
+ for frame_index in tqdm.tqdm(range(totalFrames)):
+ ret, frame = cap.read() # 按帧读取视频
+ # #到视频结尾时终止
+ if ret is False:
+ break
+ # cv2.imwrite("../preparation/{}/image/{:0>6d}.png".format(model_name, frame_index), frame)
+ tag_, rect = detect_face(frame)
+ if frame_index == 0 and tag_ != 1:
+ print("第一帧人脸检测异常,请剔除掉多个人脸、大角度侧脸(鼻子不在两个眼之间)、部分人脸框在画面外、人脸像素低于80*80")
+ pts_3d = -1
+ break
+ elif tag_ == -1: # 有时候人脸检测会失败,就用上一帧的结果替代这一帧的结果
+ rect = face_rect_list[-1]
+ elif tag_ != 1:
+ print("第{}帧人脸检测异常,请剔除掉多个人脸、大角度侧脸(鼻子不在两个眼之间)、部分人脸框在画面外、人脸像素低于80*80, tag: {}".format(frame_index, tag_))
+ # exit()
+ if len(face_rect_list) > 0:
+ face_area_inter = calc_face_interact(face_rect_list[-1], rect)
+ # print(frame_index, face_area_inter)
+ if face_area_inter < 0.6:
+ print("人脸区域变化幅度太大,请复查,超出值为{}, frame_num: {}".format(face_area_inter, frame_index))
+ pts_3d = -2
+ break
+
+ face_rect_list.append(rect)
+
+ x_min = rect[0] * vid_width
+ y_min = rect[2] * vid_height
+ x_max = rect[1] * vid_width
+ y_max = rect[3] * vid_height
+ seq_w, seq_h = x_max - x_min, y_max - y_min
+ x_mid, y_mid = (x_min + x_max) / 2, (y_min + y_max) / 2
+ # x_min = int(max(0, x_mid - seq_w * 0.65))
+ # y_min = int(max(0, y_mid - seq_h * 0.4))
+ # x_max = int(min(vid_width, x_mid + seq_w * 0.65))
+ # y_max = int(min(vid_height, y_mid + seq_h * 0.8))
+ crop_size = int(max(seq_w * 1.35, seq_h * 1.35))
+ x_min = int(max(0, x_mid - crop_size * 0.5))
+ y_min = int(max(0, y_mid - crop_size * 0.45))
+ x_max = int(min(vid_width, x_min + crop_size))
+ y_max = int(min(vid_height, y_min + crop_size))
+
+ frame_face = frame[y_min:y_max, x_min:x_max]
+ # cv2.imshow("s", frame_face)
+ # cv2.waitKey(20)
+ frame_kps = detect_face_mesh(frame_face)
+ pts_3d[frame_index] = frame_kps + np.array([x_min, y_min, 0])
+ cap.release() # 释放视频对象
+ return pts_3d
+
+
+def run(video_path, export_imgs = True):
+ cap = cv2.VideoCapture(video_path)
+ if not cap.isOpened():
+ return 0
+ vid_width = cap.get(cv2.CAP_PROP_FRAME_WIDTH) # 宽度
+ vid_height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT) # 高度
+
+ totalFrames = cap.get(cv2.CAP_PROP_FRAME_COUNT) # 总帧数
+ totalFrames = int(totalFrames)
+ cap.release()
+ pts_3d = ExtractFromVideo(video_path)
+ if type(pts_3d) is np.ndarray and len(pts_3d) == totalFrames:
+ print("关键点已提取")
+ else:
+ print("error in video: {}!!!".format(video_path))
+ return
+
+ video_name = os.path.basename(video_path).split(".")[0]
+ video_data_path = os.path.join(os.path.dirname(video_path), video_name)
+ os.makedirs(video_data_path, exist_ok=True)
+
+ if export_imgs:
+ # 计算整个视频中人脸的范围
+ x_min, y_min, x_max, y_max = np.min(pts_3d[:, :, 0]), np.min(
+ pts_3d[:, :, 1]), np.max(
+ pts_3d[:, :, 0]), np.max(pts_3d[:, :, 1])
+ new_w = int((x_max - x_min) * 0.55) * 2
+ new_h = int((y_max - y_min) * 0.6) * 2
+ center_x = int((x_max + x_min) / 2.)
+ center_y = int(y_min + (y_max - y_min) * 0.6)
+ size = max(new_h, new_w)
+ x_min, y_min, x_max, y_max = int(center_x - size // 2), int(center_y - size // 2), int(
+ center_x + size // 2), int(center_y + size // 2)
+
+ # 确定裁剪区域上边top和左边left坐标
+ top = y_min
+ left = x_min
+ # 裁剪区域与原图的重合区域
+ top_coincidence = int(max(top, 0))
+ bottom_coincidence = int(min(y_max, vid_height))
+ left_coincidence = int(max(left, 0))
+ right_coincidence = int(min(x_max, vid_width))
+ print("人脸活动范围:{}:{}, {}:{}".format(top_coincidence, bottom_coincidence, left_coincidence, right_coincidence))
+ out_size = 512
+ scale = 512. / size
+ pts_3d = (pts_3d - np.array([left_coincidence, top_coincidence, 0])) * scale
+ Path_output_pkl = "{}/keypoint_rotate.pkl".format(video_data_path)
+ with open(Path_output_pkl, "wb") as f:
+ pickle.dump(pts_3d, f)
+ os.makedirs("{}/image".format(video_data_path), exist_ok=True)
+ ffmpeg_cmd = "ffmpeg -i {} -vf crop={}:{}:{}:{},scale=512:512:flags=neighbor -loglevel quiet -y {}/image/%06d.png".format(
+ video_path,
+ right_coincidence - left_coincidence,
+ bottom_coincidence - top_coincidence,
+ left_coincidence,
+ top_coincidence,
+ video_data_path
+ )
+ os.system(ffmpeg_cmd)
+
+
+ img_filelist = glob.glob("{}/image/*.png".format(video_data_path))
+ img_filelist.sort()
+
+ Path_output_pkl = "{}/keypoint_rotate.pkl".format(video_data_path)
+
+ with open(Path_output_pkl, "rb") as f:
+ images_info = pickle.load(f)[:, main_keypoints_index, :]
+ pts_driven = images_info.reshape(len(images_info), -1)
+ pts_driven = smooth_array(pts_driven).reshape(len(pts_driven), -1, 3)
+
+
+ face_pts_mean = np.loadtxt(os.path.join(current_dir, "../data/face_pts_mean_mainKps.txt"))
+ mat_list, pts_normalized_list, face_pts_mean_personal = calc_face_mat(pts_driven, face_pts_mean)
+ pts_normalized_list = np.array(pts_normalized_list)
+ # print(face_pts_mean_personal[INDEX_FACE_OVAL[:10], 1])
+ # print(np.max(pts_normalized_list[:,INDEX_FACE_OVAL[:10], 1], axis = 1))
+ face_pts_mean_personal[INDEX_FACE_OVAL[:10], 1] = np.max(pts_normalized_list[:, INDEX_FACE_OVAL[:10], 1],
+ axis=0) + np.arange(5, 25, 2)
+ face_pts_mean_personal[INDEX_FACE_OVAL[:10], 0] = np.max(pts_normalized_list[:, INDEX_FACE_OVAL[:10], 0],
+ axis=0) - (9 - np.arange(0, 10))
+ face_pts_mean_personal[INDEX_FACE_OVAL[-10:], 1] = np.max(pts_normalized_list[:, INDEX_FACE_OVAL[-10:], 1],
+ axis=0) - np.arange(5, 25, 2) + 28
+ face_pts_mean_personal[INDEX_FACE_OVAL[-10:], 0] = np.min(pts_normalized_list[:, INDEX_FACE_OVAL[-10:], 0],
+ axis=0) + np.arange(0, 10)
+
+ face_pts_mean_personal[INDEX_FACE_OVAL[10], 1] = np.max(pts_normalized_list[:, INDEX_FACE_OVAL[10], 1], axis=0) + 25
+
+ # for keypoints_normalized in pts_normalized_list:
+ # img = np.zeros([1000,1000,3], dtype=np.uint8)
+ # for coor in face_pts_mean_personal:
+ # # coor = (coor +1 )/2.
+ # cv2.circle(img, (int(coor[0]), int(coor[1])), point_size, (255, 0, 0), thickness)
+ # for coor in keypoints_normalized:
+ # # coor = (coor +1 )/2.
+ # cv2.circle(img, (int(coor[0]), int(coor[1])), point_size, point_color, thickness)
+ # cv2.imshow("a", img)
+ # cv2.waitKey(30)
+
+ with open("{}/face_mat_mask.pkl".format(video_data_path), "wb") as f:
+ pickle.dump([mat_list, face_pts_mean_personal], f)
+
+
+
+def main():
+ # 检查命令行参数的数量
+ if len(sys.argv) != 2:
+ print("Usage: python data_preparation.py ")
+ sys.exit(1) # 参数数量不正确时退出程序
+
+ # 获取video_name参数
+ data_dir = sys.argv[1]
+ print(f"Video dir is set to: {data_dir}")
+ # data_dir = r"F:\C\AI\CV\88"
+ video_files = glob.glob("{}/*.mp4".format(data_dir))
+ for video_path in tqdm.tqdm(video_files):
+ run(video_path)
+
+if __name__ == "__main__":
+ main()
diff --git a/train/train_input_validation_render_model.py b/train/train_input_validation_render_model.py
new file mode 100644
index 0000000..0199071
--- /dev/null
+++ b/train/train_input_validation_render_model.py
@@ -0,0 +1,59 @@
+import os
+os.environ["KMP_DUPLICATE_LIB_OK"] = "true"
+current_dir = os.path.dirname(os.path.abspath(__file__))
+import sys
+sys.path.append(os.path.join(current_dir, ".."))
+import pickle
+import cv2
+import numpy as np
+import random
+
+import glob
+import sys
+import torch
+from torch.utils.data import DataLoader
+from talkingface.data.few_shot_dataset import Few_Shot_Dataset,data_preparation
+from talkingface.utils import *
+
+def main():
+ # 检查命令行参数的数量
+ if len(sys.argv) != 2:
+ print("Usage: python train_input_validation_render_model.py ")
+ sys.exit(1) # 参数数量不正确时退出程序
+
+ # 获取video_name参数
+ data_dir = sys.argv[1]
+ # data_dir = r"F:\C\AI\CV\88"
+ print(f"Video dir is set to: {data_dir}")
+
+ video_list = [os.path.join(data_dir, i) for i in os.listdir(data_dir)]
+ dict_info = data_preparation(video_list)
+ device = torch.device("cuda:0")
+ test_set = Few_Shot_Dataset(dict_info, is_train=True, n_ref=1)
+ testing_data_loader = DataLoader(dataset=test_set, num_workers=0, batch_size=1, shuffle=False)
+
+ def Tensor2img(tensor_, channel_index):
+ frame = tensor_[channel_index:channel_index + 3, :, :].detach().squeeze(0).cpu().float().numpy()
+ frame = np.transpose(frame, (1, 2, 0)) * 255.0
+ frame = frame.clip(0, 255)
+ return frame.astype(np.uint8)
+
+ for iteration, batch in enumerate(testing_data_loader):
+ # source_tensor, source_prompt_tensor, ref_tensor, ref_prompt_tensor, target_tensor = [iii.to(device) for iii in batch]
+ source_tensor, ref_tensor, target_tensor = [iii.to(device) for iii in batch]
+ print(source_tensor.size(), ref_tensor.size(), target_tensor.size())
+
+ frame0 = Tensor2img(source_tensor[0], 0)
+ frame1 = Tensor2img(source_tensor[0], 3)
+ frame2 = Tensor2img(ref_tensor[0], 0)
+ frame3 = Tensor2img(ref_tensor[0], 3)
+ frame4 = Tensor2img(target_tensor[0], 0)
+ frame = np.concatenate([frame0, frame1, frame2, frame3, frame4], axis=1)
+
+ cv2.imshow("ss", frame)
+ cv2.waitKey(-1)
+ # break
+ cv2.destroyAllWindows()
+
+if __name__ == "__main__":
+ main()
\ No newline at end of file
diff --git a/train/train_render_model.py b/train/train_render_model.py
new file mode 100644
index 0000000..ecaa7a1
--- /dev/null
+++ b/train/train_render_model.py
@@ -0,0 +1,197 @@
+import os
+os.environ["KMP_DUPLICATE_LIB_OK"] = "true"
+current_dir = os.path.dirname(os.path.abspath(__file__))
+import sys
+sys.path.append(os.path.join(current_dir, ".."))
+from talkingface.models.common.Discriminator import Discriminator
+from talkingface.models.common.VGG19 import Vgg19
+from talkingface.models.DINet import DINet_five_Ref
+from talkingface.util.utils import GANLoss,get_scheduler, update_learning_rate
+from talkingface.config.config import DINetTrainingOptions
+from torch.utils.tensorboard import SummaryWriter
+from talkingface.util.log_board import log
+import torch
+import torch.nn as nn
+import torch.optim as optim
+from torch.utils.data import DataLoader
+import random
+import numpy as np
+import os
+import sys
+import torch.nn.functional as F
+import cv2
+from talkingface.data.few_shot_dataset import Few_Shot_Dataset,data_preparation
+
+def Tensor2img(tensor_, channel_index):
+ frame = tensor_[channel_index:channel_index + 3, :, :].detach().squeeze(0).cpu().float().numpy()
+ frame = np.transpose(frame, (1, 2, 0)) * 255.0
+ frame = frame.clip(0, 255)
+ return frame.astype(np.uint8)
+
+if __name__ == "__main__":
+ '''
+ training code of person image generation
+ '''
+ # load config
+ opt = DINetTrainingOptions().parse_args()
+ n_ref = 5
+ opt.source_channel = 3 * 2
+ opt.target_channel = 3
+ opt.ref_channel = n_ref * 3 * 2
+ opt.batch_size = 4
+ opt.result_path = "checkpoint/Dinet_five_ref"
+ opt.resume = False
+ opt.resume_path = None
+
+ # set seed
+ random.seed(opt.seed)
+ np.random.seed(opt.seed)
+ torch.cuda.manual_seed(opt.seed)
+
+
+ video_list = []
+ # path_ = r"../preparation_bilibili"
+ path_ = opt.train_data
+ video_list += [os.path.join(path_, i) for i in os.listdir(path_)]
+
+ print("video_selected final: ", len(video_list))
+ video_list.sort()
+ train_dict_info = data_preparation(video_list[:])
+ train_set = Few_Shot_Dataset(train_dict_info, n_ref=n_ref, is_train=True)
+ training_data_loader = DataLoader(dataset=train_set, num_workers=0, batch_size=opt.batch_size, shuffle=True)
+ train_log_path = "train_log.txt"
+ train_data_length = len(training_data_loader)
+ # init network
+ net_g = DINet_five_Ref(opt.source_channel,opt.ref_channel).cuda()
+ net_d = Discriminator(opt.target_channel, opt.D_block_expansion, opt.D_num_blocks, opt.D_max_features).cuda()
+ net_vgg = Vgg19().cuda()
+
+ # set optimizer
+ optimizer_g = optim.Adam(net_g.parameters(), lr=opt.lr_g)
+ optimizer_d = optim.Adam(net_d.parameters(), lr=opt.lr_d)
+
+ if opt.resume:
+ print('loading checkpoint {}'.format(opt.resume_path))
+ checkpoint = torch.load(opt.resume_path)
+ # opt.start_epoch = checkpoint['epoch']
+ # opt.start_epoch = 200
+ net_g_static = checkpoint['state_dict']['net_g']
+ net_g.load_state_dict(net_g_static)
+ net_d.load_state_dict(checkpoint['state_dict']['net_d'])
+ optimizer_g.load_state_dict(checkpoint['optimizer']['net_g'])
+ optimizer_d.load_state_dict(checkpoint['optimizer']['net_d'])
+
+ # set criterion
+ criterionGAN = GANLoss().cuda()
+ criterionL1 = nn.L1Loss().cuda()
+ # set scheduler
+ net_g_scheduler = get_scheduler(optimizer_g, opt.non_decay, opt.decay)
+ net_d_scheduler = get_scheduler(optimizer_d, opt.non_decay, opt.decay)
+
+
+
+ train_log_path = os.path.join("checkpoint/{}/log".format("DiNet_five_ref"), "train")
+ os.makedirs(train_log_path, exist_ok=True)
+ train_logger = SummaryWriter(train_log_path)
+
+ # start train
+ for epoch in range(opt.start_epoch, opt.non_decay + opt.decay + 1):
+ net_g.train()
+ avg_loss_g_perception = 0
+ avg_Loss_DI = 0
+ avg_Loss_GI = 0
+ for iteration, data in enumerate(training_data_loader):
+ # read data
+ source_tensor, ref_tensor, target_tensor = data
+ source_tensor = source_tensor.float().cuda()
+ ref_tensor = ref_tensor.float().cuda()
+ target_tensor = target_tensor.float().cuda()
+
+ source_tensor, source_prompt_tensor = source_tensor[:, :3], source_tensor[:, 3:]
+ # network forward
+ fake_out = net_g(source_tensor, source_prompt_tensor, ref_tensor)
+ # down sample output image and real image
+ fake_out_half = F.avg_pool2d(fake_out, 3, 2, 1, count_include_pad=False)
+ target_tensor_half = F.interpolate(target_tensor, scale_factor=0.5, mode='bilinear')
+ # (1) Update D network
+ optimizer_d.zero_grad()
+ # compute fake loss
+ _,pred_fake_d = net_d(fake_out)
+ loss_d_fake = criterionGAN(pred_fake_d, False)
+ # compute real loss
+ _,pred_real_d = net_d(target_tensor)
+ loss_d_real = criterionGAN(pred_real_d, True)
+ # Combine D loss
+ loss_dI = (loss_d_fake + loss_d_real) * 0.5
+ loss_dI.backward(retain_graph=True)
+ optimizer_d.step()
+ # (2) Update G network
+ _, pred_fake_dI = net_d(fake_out)
+ optimizer_g.zero_grad()
+ # compute perception loss
+ perception_real = net_vgg(target_tensor)
+ perception_fake = net_vgg(fake_out)
+ perception_real_half = net_vgg(target_tensor_half)
+ perception_fake_half = net_vgg(fake_out_half)
+ loss_g_perception = 0
+ for i in range(len(perception_real)):
+ loss_g_perception += criterionL1(perception_fake[i], perception_real[i])
+ loss_g_perception += criterionL1(perception_fake_half[i], perception_real_half[i])
+ loss_g_perception = (loss_g_perception / (len(perception_real) * 2)) * opt.lamb_perception
+ # gan dI loss
+ loss_g_dI = criterionGAN(pred_fake_dI, True)
+ # combine perception loss and gan loss
+ loss_g = loss_g_perception + loss_g_dI
+ loss_g.backward()
+ optimizer_g.step()
+ message = "===> Epoch[{}]({}/{}): Loss_DI: {:.4f} Loss_GI: {:.4f} Loss_perception: {:.4f} lr_g = {:.7f} lr_d = {:.7f}".format(
+ epoch, iteration, len(training_data_loader), float(loss_dI), float(loss_g_dI),
+ float(loss_g_perception), optimizer_g.param_groups[0]['lr'], optimizer_d.param_groups[0]['lr'])
+ print(message)
+ # with open("train_log.txt", "a") as f:
+ # f.write(message + "\n")
+
+ if iteration%200 == 0:
+ inference_out = fake_out * 255
+ inference_out = inference_out[0].cpu().permute(1, 2, 0).float().detach().numpy().astype(np.uint8)
+ inference_in = (target_tensor[0, :3]* 255).cpu().permute(1, 2, 0).float().detach().numpy().astype(np.uint8)
+ inference_in_prompt = (source_prompt_tensor[0, :3] * 255).cpu().permute(1, 2, 0).float().detach().numpy().astype(
+ np.uint8)
+ frame2 = Tensor2img(ref_tensor[0], 0)
+ frame3 = Tensor2img(ref_tensor[0], 3)
+ inference_out = np.concatenate([inference_in, inference_in_prompt, inference_out, frame2, frame3], axis=1)
+ inference_out = cv2.cvtColor(inference_out, cv2.COLOR_RGB2BGR)
+
+ log(train_logger, fig=inference_out, tag="Training/epoch_{}_{}".format(epoch, iteration))
+
+ real_iteration = epoch * len(training_data_loader) + iteration
+ message1 = "Step {}/{}, ".format(real_iteration, (epoch + 1) * len(training_data_loader))
+ message2 = ""
+ losses = [loss_dI.item(), loss_g_perception.item(), loss_g_dI.item()]
+ train_logger.add_scalar("Loss/loss_dI", losses[0], real_iteration)
+ train_logger.add_scalar("Loss/loss_g_perception", losses[1], real_iteration)
+ train_logger.add_scalar("Loss/loss_g_dI", losses[2], real_iteration)
+
+ avg_loss_g_perception += loss_g_perception.item()
+ avg_Loss_DI += loss_dI.item()
+ avg_Loss_GI += loss_g_dI.item()
+ train_logger.add_scalar("Loss/{}".format("epoch_g_perception"), avg_loss_g_perception / len(training_data_loader), epoch)
+ train_logger.add_scalar("Loss/{}".format("epoch_DI"),
+ avg_Loss_DI / len(training_data_loader), epoch)
+ train_logger.add_scalar("Loss/{}".format("epoch_GI"),
+ avg_Loss_GI / len(training_data_loader), epoch)
+ update_learning_rate(net_g_scheduler, optimizer_g)
+ update_learning_rate(net_d_scheduler, optimizer_d)
+
+ # checkpoint
+ if epoch % opt.checkpoint == 0:
+ if not os.path.exists(opt.result_path):
+ os.mkdir(opt.result_path)
+ model_out_path = os.path.join(opt.result_path, 'epoch_{}.pth'.format(epoch))
+ states = {
+ 'epoch': epoch + 1,
+ 'state_dict': {'net_g': net_g.state_dict(), 'net_d': net_d.state_dict()},
+ 'optimizer': {'net_g': optimizer_g.state_dict(), 'net_d': optimizer_d.state_dict()}
+ }
+ torch.save(states, model_out_path)
+ print("Checkpoint saved to {}".format(epoch))
\ No newline at end of file
diff --git a/train/validation.jpg b/train/validation.jpg
new file mode 100644
index 0000000..5986c8a
Binary files /dev/null and b/train/validation.jpg differ
diff --git a/train_audio/README.md b/train_audio/README.md
new file mode 100644
index 0000000..e56cbb7
--- /dev/null
+++ b/train_audio/README.md
@@ -0,0 +1,56 @@
+# LSTM Training Notes
+
+## Data Preparation
+- Use over 10,000 short audio clips with diverse speakers, each at least 5 seconds long, in 16k single-channel wav format.
+- Place these files in the `train_audio/train_data` folder.
+- Download `wav2lip.pth` from the wav2lip project (https://github.com/Rudrabha/Wav2Lip) and place it in the `train_audio/checkpoints` folder.
+
+#### Notes
+Audio files must be in 16k single-channel wav format.
+
+## Steps
+
+### 1. Face Video Generation
+```bash
+python preparation_step0.py
+# Example: preparation_step0.py face.jpg train_data
+```
+
+### 2. Mouth Region Extraction and PCA Modeling
+```bash
+python preparation_step1.py
+# Example: preparation_step1.py train_data
+```
+
+Now ensure the file directory is as follows:
+```bash
+|--/train_audio
+| |--/checkpoints
+| | |--/wav2lip.pth
+| | |--/pca.pkl
+| | |--/wav2lip_pca_all.gif
+| |--/train_data
+| | |--/000001.wav
+| | |--/000001.avi
+| | |--/000001.txt
+| | |--/000002.wav
+| | |--/000002.avi
+| | |--/000002.txt
+| | |--/000003.wav
+| | |--/000003.avi
+| | |--/000003.txt
+```
+
+### 3. Training LSTM Model
+```bash
+python train_lstm.py
+# Example: train_lstm.py train_data
+```
+
+### 4. Testing Audio Accuracy
+```bash
+python test.py
+# Example: python test.py D:/Code/py/test_wav/0013.wav checkpoints/audio.pkl
+```
+
+
diff --git a/train_audio/audio.py b/train_audio/audio.py
new file mode 100644
index 0000000..d7b0e8c
--- /dev/null
+++ b/train_audio/audio.py
@@ -0,0 +1,137 @@
+import librosa
+import librosa.filters
+import numpy as np
+# import tensorflow as tf
+from scipy import signal
+from scipy.io import wavfile
+from hparams import hparams as hp
+import os
+os.environ['KMP_DUPLICATE_LIB_OK']='True'
+def load_wav(path, sr):
+ return librosa.core.load(path, sr=sr)[0]
+
+def save_wav(wav, path, sr):
+ wav *= 32767 / max(0.01, np.max(np.abs(wav)))
+ #proposed by @dsmiller
+ wavfile.write(path, sr, wav.astype(np.int16))
+
+def save_wavenet_wav(wav, path, sr):
+ librosa.output.write_wav(path, wav, sr=sr)
+
+def preemphasis(wav, k, preemphasize=True):
+ if preemphasize:
+ return signal.lfilter([1, -k], [1], wav)
+ return wav
+
+def inv_preemphasis(wav, k, inv_preemphasize=True):
+ if inv_preemphasize:
+ return signal.lfilter([1], [1, -k], wav)
+ return wav
+
+def get_hop_size():
+ hop_size = hp.hop_size
+ if hop_size is None:
+ assert hp.frame_shift_ms is not None
+ hop_size = int(hp.frame_shift_ms / 1000 * hp.sample_rate)
+ return hop_size
+
+def linearspectrogram(wav):
+ D = _stft(preemphasis(wav, hp.preemphasis, hp.preemphasize))
+ S = _amp_to_db(np.abs(D)) - hp.ref_level_db
+
+ if hp.signal_normalization:
+ return _normalize(S)
+ return S
+
+def melspectrogram(wav):
+ D = _stft(preemphasis(wav, hp.preemphasis, hp.preemphasize))
+ S = _amp_to_db(_linear_to_mel(np.abs(D))) - hp.ref_level_db
+
+ if hp.signal_normalization:
+ return _normalize(S)
+ return S
+
+def _lws_processor():
+ import lws
+ return lws.lws(hp.n_fft, get_hop_size(), fftsize=hp.win_size, mode="speech")
+
+def _stft(y):
+ if hp.use_lws:
+ return _lws_processor(hp).stft(y).T
+ else:
+ return librosa.stft(y=y, n_fft=hp.n_fft, hop_length=get_hop_size(), win_length=hp.win_size)
+
+##########################################################
+#Those are only correct when using lws!!! (This was messing with Wavenet quality for a long time!)
+def num_frames(length, fsize, fshift):
+ """Compute number of time frames of spectrogram
+ """
+ pad = (fsize - fshift)
+ if length % fshift == 0:
+ M = (length + pad * 2 - fsize) // fshift + 1
+ else:
+ M = (length + pad * 2 - fsize) // fshift + 2
+ return M
+
+
+def pad_lr(x, fsize, fshift):
+ """Compute left and right padding
+ """
+ M = num_frames(len(x), fsize, fshift)
+ pad = (fsize - fshift)
+ T = len(x) + 2 * pad
+ r = (M - 1) * fshift + fsize - T
+ return pad, pad + r
+##########################################################
+#Librosa correct padding
+def librosa_pad_lr(x, fsize, fshift):
+ return 0, (x.shape[0] // fshift + 1) * fshift - x.shape[0]
+
+# Conversions
+_mel_basis = None
+
+def _linear_to_mel(spectogram):
+ global _mel_basis
+ if _mel_basis is None:
+ _mel_basis = _build_mel_basis()
+ return np.dot(_mel_basis, spectogram)
+
+def _build_mel_basis():
+ assert hp.fmax <= hp.sample_rate // 2
+ return librosa.filters.mel(sr = hp.sample_rate, n_fft = hp.n_fft, n_mels=hp.num_mels,
+ fmin=hp.fmin, fmax=hp.fmax)
+
+def _amp_to_db(x):
+ min_level = np.exp(hp.min_level_db / 20 * np.log(10))
+ return 20 * np.log10(np.maximum(min_level, x))
+
+def _db_to_amp(x):
+ return np.power(10.0, (x) * 0.05)
+
+def _normalize(S):
+ if hp.allow_clipping_in_normalization:
+ if hp.symmetric_mels:
+ return np.clip((2 * hp.max_abs_value) * ((S - hp.min_level_db) / (-hp.min_level_db)) - hp.max_abs_value,
+ -hp.max_abs_value, hp.max_abs_value)
+ else:
+ return np.clip(hp.max_abs_value * ((S - hp.min_level_db) / (-hp.min_level_db)), 0, hp.max_abs_value)
+
+ assert S.max() <= 0 and S.min() - hp.min_level_db >= 0
+ if hp.symmetric_mels:
+ return (2 * hp.max_abs_value) * ((S - hp.min_level_db) / (-hp.min_level_db)) - hp.max_abs_value
+ else:
+ return hp.max_abs_value * ((S - hp.min_level_db) / (-hp.min_level_db))
+
+def _denormalize(D):
+ if hp.allow_clipping_in_normalization:
+ if hp.symmetric_mels:
+ return (((np.clip(D, -hp.max_abs_value,
+ hp.max_abs_value) + hp.max_abs_value) * -hp.min_level_db / (2 * hp.max_abs_value))
+ + hp.min_level_db)
+ else:
+ return ((np.clip(D, 0, hp.max_abs_value) * -hp.min_level_db / hp.max_abs_value) + hp.min_level_db)
+
+ if hp.symmetric_mels:
+ return (((D + hp.max_abs_value) * -hp.min_level_db / (2 * hp.max_abs_value)) + hp.min_level_db)
+ else:
+ return ((D * -hp.min_level_db / hp.max_abs_value) + hp.min_level_db)
diff --git a/train_audio/face.jpg b/train_audio/face.jpg
new file mode 100644
index 0000000..9168d36
Binary files /dev/null and b/train_audio/face.jpg differ
diff --git a/train_audio/hparams.py b/train_audio/hparams.py
new file mode 100644
index 0000000..1c01904
--- /dev/null
+++ b/train_audio/hparams.py
@@ -0,0 +1,101 @@
+from glob import glob
+import os
+
+def get_image_list(data_root, split):
+ filelist = []
+
+ with open('filelists/{}.txt'.format(split)) as f:
+ for line in f:
+ line = line.strip()
+ if ' ' in line: line = line.split()[0]
+ filelist.append(os.path.join(data_root, line))
+
+ return filelist
+
+class HParams:
+ def __init__(self, **kwargs):
+ self.data = {}
+
+ for key, value in kwargs.items():
+ self.data[key] = value
+
+ def __getattr__(self, key):
+ if key not in self.data:
+ raise AttributeError("'HParams' object has no attribute %s" % key)
+ return self.data[key]
+
+ def set_hparam(self, key, value):
+ self.data[key] = value
+
+
+# Default hyperparameters
+hparams = HParams(
+ num_mels=80, # Number of mel-spectrogram channels and local conditioning dimensionality
+ # network
+ rescale=True, # Whether to rescale audio prior to preprocessing
+ rescaling_max=0.9, # Rescaling value
+
+ # Use LWS (https://github.com/Jonathan-LeRoux/lws) for STFT and phase reconstruction
+ # It"s preferred to set True to use with https://github.com/r9y9/wavenet_vocoder
+ # Does not work if n_ffit is not multiple of hop_size!!
+ use_lws=False,
+
+ n_fft=800, # Extra window size is filled with 0 paddings to match this parameter
+ hop_size=200, # For 16000Hz, 200 = 12.5 ms (0.0125 * sample_rate)
+ win_size=800, # For 16000Hz, 800 = 50 ms (If None, win_size = n_fft) (0.05 * sample_rate)
+ sample_rate=16000, # 16000Hz (corresponding to librispeech) (sox --i )
+
+ frame_shift_ms=None, # Can replace hop_size parameter. (Recommended: 12.5)
+
+ # Mel and Linear spectrograms normalization/scaling and clipping
+ signal_normalization=True,
+ # Whether to normalize mel spectrograms to some predefined range (following below parameters)
+ allow_clipping_in_normalization=True, # Only relevant if mel_normalization = True
+ symmetric_mels=True,
+ # Whether to scale the data to be symmetric around 0. (Also multiplies the output range by 2,
+ # faster and cleaner convergence)
+ max_abs_value=4.,
+ # max absolute value of data. If symmetric, data will be [-max, max] else [0, max] (Must not
+ # be too big to avoid gradient explosion,
+ # not too small for fast convergence)
+ # Contribution by @begeekmyfriend
+ # Spectrogram Pre-Emphasis (Lfilter: Reduce spectrogram noise and helps model certitude
+ # levels. Also allows for better G&L phase reconstruction)
+ preemphasize=True, # whether to apply filter
+ preemphasis=0.97, # filter coefficient.
+
+ # Limits
+ min_level_db=-100,
+ ref_level_db=20,
+ fmin=55,
+ # Set this to 55 if your speaker is male! if female, 95 should help taking off noise. (To
+ # test depending on dataset. Pitch info: male~[65, 260], female~[100, 525])
+ fmax=7600, # To be increased/reduced depending on data.
+
+ ###################### Our training parameters #################################
+ img_size=96,
+ fps=25,
+
+ batch_size=16,
+ initial_learning_rate=1e-4,
+ nepochs=200000000000000000, ### ctrl + c, stop whenever eval loss is consistently greater than train loss for ~10 epochs
+ num_workers=16,
+ checkpoint_interval=3000,
+ eval_interval=3000,
+ save_optimizer_state=True,
+
+ syncnet_wt=0.0, # is initially zero, will be set automatically to 0.03 later. Leads to faster convergence.
+ syncnet_batch_size=64,
+ syncnet_lr=1e-4,
+ syncnet_eval_interval=10000,
+ syncnet_checkpoint_interval=10000,
+
+ disc_wt=0.07,
+ disc_initial_learning_rate=1e-4,
+)
+
+
+def hparams_debug_string():
+ values = hparams.values()
+ hp = [" %s: %s" % (name, values[name]) for name in sorted(values) if name != "sentences"]
+ return "Hyperparameters:\n" + "\n".join(hp)
diff --git a/train_audio/models/__init__.py b/train_audio/models/__init__.py
new file mode 100644
index 0000000..4374370
--- /dev/null
+++ b/train_audio/models/__init__.py
@@ -0,0 +1,2 @@
+from .wav2lip import Wav2Lip, Wav2Lip_disc_qual
+from .syncnet import SyncNet_color
\ No newline at end of file
diff --git a/train_audio/models/conv.py b/train_audio/models/conv.py
new file mode 100644
index 0000000..ed83da0
--- /dev/null
+++ b/train_audio/models/conv.py
@@ -0,0 +1,44 @@
+import torch
+from torch import nn
+from torch.nn import functional as F
+
+class Conv2d(nn.Module):
+ def __init__(self, cin, cout, kernel_size, stride, padding, residual=False, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.conv_block = nn.Sequential(
+ nn.Conv2d(cin, cout, kernel_size, stride, padding),
+ nn.BatchNorm2d(cout)
+ )
+ self.act = nn.ReLU()
+ self.residual = residual
+
+ def forward(self, x):
+ out = self.conv_block(x)
+ if self.residual:
+ out += x
+ return self.act(out)
+
+class nonorm_Conv2d(nn.Module):
+ def __init__(self, cin, cout, kernel_size, stride, padding, residual=False, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.conv_block = nn.Sequential(
+ nn.Conv2d(cin, cout, kernel_size, stride, padding),
+ )
+ self.act = nn.LeakyReLU(0.01, inplace=True)
+
+ def forward(self, x):
+ out = self.conv_block(x)
+ return self.act(out)
+
+class Conv2dTranspose(nn.Module):
+ def __init__(self, cin, cout, kernel_size, stride, padding, output_padding=0, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.conv_block = nn.Sequential(
+ nn.ConvTranspose2d(cin, cout, kernel_size, stride, padding, output_padding),
+ nn.BatchNorm2d(cout)
+ )
+ self.act = nn.ReLU()
+
+ def forward(self, x):
+ out = self.conv_block(x)
+ return self.act(out)
diff --git a/train_audio/models/syncnet.py b/train_audio/models/syncnet.py
new file mode 100644
index 0000000..e773cdc
--- /dev/null
+++ b/train_audio/models/syncnet.py
@@ -0,0 +1,66 @@
+import torch
+from torch import nn
+from torch.nn import functional as F
+
+from .conv import Conv2d
+
+class SyncNet_color(nn.Module):
+ def __init__(self):
+ super(SyncNet_color, self).__init__()
+
+ self.face_encoder = nn.Sequential(
+ Conv2d(15, 32, kernel_size=(7, 7), stride=1, padding=3),
+
+ Conv2d(32, 64, kernel_size=5, stride=(1, 2), padding=1),
+ Conv2d(64, 64, kernel_size=3, stride=1, padding=1, residual=True),
+ Conv2d(64, 64, kernel_size=3, stride=1, padding=1, residual=True),
+
+ Conv2d(64, 128, kernel_size=3, stride=2, padding=1),
+ Conv2d(128, 128, kernel_size=3, stride=1, padding=1, residual=True),
+ Conv2d(128, 128, kernel_size=3, stride=1, padding=1, residual=True),
+ Conv2d(128, 128, kernel_size=3, stride=1, padding=1, residual=True),
+
+ Conv2d(128, 256, kernel_size=3, stride=2, padding=1),
+ Conv2d(256, 256, kernel_size=3, stride=1, padding=1, residual=True),
+ Conv2d(256, 256, kernel_size=3, stride=1, padding=1, residual=True),
+
+ Conv2d(256, 512, kernel_size=3, stride=2, padding=1),
+ Conv2d(512, 512, kernel_size=3, stride=1, padding=1, residual=True),
+ Conv2d(512, 512, kernel_size=3, stride=1, padding=1, residual=True),
+
+ Conv2d(512, 512, kernel_size=3, stride=2, padding=1),
+ Conv2d(512, 512, kernel_size=3, stride=1, padding=0),
+ Conv2d(512, 512, kernel_size=1, stride=1, padding=0),)
+
+ self.audio_encoder = nn.Sequential(
+ Conv2d(1, 32, kernel_size=3, stride=1, padding=1),
+ Conv2d(32, 32, kernel_size=3, stride=1, padding=1, residual=True),
+ Conv2d(32, 32, kernel_size=3, stride=1, padding=1, residual=True),
+
+ Conv2d(32, 64, kernel_size=3, stride=(3, 1), padding=1),
+ Conv2d(64, 64, kernel_size=3, stride=1, padding=1, residual=True),
+ Conv2d(64, 64, kernel_size=3, stride=1, padding=1, residual=True),
+
+ Conv2d(64, 128, kernel_size=3, stride=3, padding=1),
+ Conv2d(128, 128, kernel_size=3, stride=1, padding=1, residual=True),
+ Conv2d(128, 128, kernel_size=3, stride=1, padding=1, residual=True),
+
+ Conv2d(128, 256, kernel_size=3, stride=(3, 2), padding=1),
+ Conv2d(256, 256, kernel_size=3, stride=1, padding=1, residual=True),
+ Conv2d(256, 256, kernel_size=3, stride=1, padding=1, residual=True),
+
+ Conv2d(256, 512, kernel_size=3, stride=1, padding=0),
+ Conv2d(512, 512, kernel_size=1, stride=1, padding=0),)
+
+ def forward(self, audio_sequences, face_sequences): # audio_sequences := (B, dim, T)
+ face_embedding = self.face_encoder(face_sequences)
+ audio_embedding = self.audio_encoder(audio_sequences)
+
+ audio_embedding = audio_embedding.view(audio_embedding.size(0), -1)
+ face_embedding = face_embedding.view(face_embedding.size(0), -1)
+
+ audio_embedding = F.normalize(audio_embedding, p=2, dim=1)
+ face_embedding = F.normalize(face_embedding, p=2, dim=1)
+
+
+ return audio_embedding, face_embedding
diff --git a/train_audio/models/wav2lip.py b/train_audio/models/wav2lip.py
new file mode 100644
index 0000000..ae5d691
--- /dev/null
+++ b/train_audio/models/wav2lip.py
@@ -0,0 +1,184 @@
+import torch
+from torch import nn
+from torch.nn import functional as F
+import math
+
+from .conv import Conv2dTranspose, Conv2d, nonorm_Conv2d
+
+class Wav2Lip(nn.Module):
+ def __init__(self):
+ super(Wav2Lip, self).__init__()
+
+ self.face_encoder_blocks = nn.ModuleList([
+ nn.Sequential(Conv2d(6, 16, kernel_size=7, stride=1, padding=3)), # 96,96
+
+ nn.Sequential(Conv2d(16, 32, kernel_size=3, stride=2, padding=1), # 48,48
+ Conv2d(32, 32, kernel_size=3, stride=1, padding=1, residual=True),
+ Conv2d(32, 32, kernel_size=3, stride=1, padding=1, residual=True)),
+
+ nn.Sequential(Conv2d(32, 64, kernel_size=3, stride=2, padding=1), # 24,24
+ Conv2d(64, 64, kernel_size=3, stride=1, padding=1, residual=True),
+ Conv2d(64, 64, kernel_size=3, stride=1, padding=1, residual=True),
+ Conv2d(64, 64, kernel_size=3, stride=1, padding=1, residual=True)),
+
+ nn.Sequential(Conv2d(64, 128, kernel_size=3, stride=2, padding=1), # 12,12
+ Conv2d(128, 128, kernel_size=3, stride=1, padding=1, residual=True),
+ Conv2d(128, 128, kernel_size=3, stride=1, padding=1, residual=True)),
+
+ nn.Sequential(Conv2d(128, 256, kernel_size=3, stride=2, padding=1), # 6,6
+ Conv2d(256, 256, kernel_size=3, stride=1, padding=1, residual=True),
+ Conv2d(256, 256, kernel_size=3, stride=1, padding=1, residual=True)),
+
+ nn.Sequential(Conv2d(256, 512, kernel_size=3, stride=2, padding=1), # 3,3
+ Conv2d(512, 512, kernel_size=3, stride=1, padding=1, residual=True),),
+
+ nn.Sequential(Conv2d(512, 512, kernel_size=3, stride=1, padding=0), # 1, 1
+ Conv2d(512, 512, kernel_size=1, stride=1, padding=0)),])
+
+ self.audio_encoder = nn.Sequential(
+ Conv2d(1, 32, kernel_size=3, stride=1, padding=1),
+ Conv2d(32, 32, kernel_size=3, stride=1, padding=1, residual=True),
+ Conv2d(32, 32, kernel_size=3, stride=1, padding=1, residual=True),
+
+ Conv2d(32, 64, kernel_size=3, stride=(3, 1), padding=1),
+ Conv2d(64, 64, kernel_size=3, stride=1, padding=1, residual=True),
+ Conv2d(64, 64, kernel_size=3, stride=1, padding=1, residual=True),
+
+ Conv2d(64, 128, kernel_size=3, stride=3, padding=1),
+ Conv2d(128, 128, kernel_size=3, stride=1, padding=1, residual=True),
+ Conv2d(128, 128, kernel_size=3, stride=1, padding=1, residual=True),
+
+ Conv2d(128, 256, kernel_size=3, stride=(3, 2), padding=1),
+ Conv2d(256, 256, kernel_size=3, stride=1, padding=1, residual=True),
+
+ Conv2d(256, 512, kernel_size=3, stride=1, padding=0),
+ Conv2d(512, 512, kernel_size=1, stride=1, padding=0),)
+
+ self.face_decoder_blocks = nn.ModuleList([
+ nn.Sequential(Conv2d(512, 512, kernel_size=1, stride=1, padding=0),),
+
+ nn.Sequential(Conv2dTranspose(1024, 512, kernel_size=3, stride=1, padding=0), # 3,3
+ Conv2d(512, 512, kernel_size=3, stride=1, padding=1, residual=True),),
+
+ nn.Sequential(Conv2dTranspose(1024, 512, kernel_size=3, stride=2, padding=1, output_padding=1),
+ Conv2d(512, 512, kernel_size=3, stride=1, padding=1, residual=True),
+ Conv2d(512, 512, kernel_size=3, stride=1, padding=1, residual=True),), # 6, 6
+
+ nn.Sequential(Conv2dTranspose(768, 384, kernel_size=3, stride=2, padding=1, output_padding=1),
+ Conv2d(384, 384, kernel_size=3, stride=1, padding=1, residual=True),
+ Conv2d(384, 384, kernel_size=3, stride=1, padding=1, residual=True),), # 12, 12
+
+ nn.Sequential(Conv2dTranspose(512, 256, kernel_size=3, stride=2, padding=1, output_padding=1),
+ Conv2d(256, 256, kernel_size=3, stride=1, padding=1, residual=True),
+ Conv2d(256, 256, kernel_size=3, stride=1, padding=1, residual=True),), # 24, 24
+
+ nn.Sequential(Conv2dTranspose(320, 128, kernel_size=3, stride=2, padding=1, output_padding=1),
+ Conv2d(128, 128, kernel_size=3, stride=1, padding=1, residual=True),
+ Conv2d(128, 128, kernel_size=3, stride=1, padding=1, residual=True),), # 48, 48
+
+ nn.Sequential(Conv2dTranspose(160, 64, kernel_size=3, stride=2, padding=1, output_padding=1),
+ Conv2d(64, 64, kernel_size=3, stride=1, padding=1, residual=True),
+ Conv2d(64, 64, kernel_size=3, stride=1, padding=1, residual=True),),]) # 96,96
+
+ self.output_block = nn.Sequential(Conv2d(80, 32, kernel_size=3, stride=1, padding=1),
+ nn.Conv2d(32, 3, kernel_size=1, stride=1, padding=0),
+ nn.Sigmoid())
+
+ def forward(self, audio_sequences, face_sequences):
+ # audio_sequences = (B, T, 1, 80, 16)
+ B = audio_sequences.size(0)
+
+ input_dim_size = len(face_sequences.size())
+ if input_dim_size > 4:
+ audio_sequences = torch.cat([audio_sequences[:, i] for i in range(audio_sequences.size(1))], dim=0)
+ face_sequences = torch.cat([face_sequences[:, :, i] for i in range(face_sequences.size(2))], dim=0)
+
+ audio_embedding = self.audio_encoder(audio_sequences) # B, 512, 1, 1
+
+ feats = []
+ x = face_sequences
+ for f in self.face_encoder_blocks:
+ x = f(x)
+ feats.append(x)
+
+ x = audio_embedding
+ for f in self.face_decoder_blocks:
+ x = f(x)
+ try:
+ x = torch.cat((x, feats[-1]), dim=1)
+ except Exception as e:
+ print(x.size())
+ print(feats[-1].size())
+ raise e
+
+ feats.pop()
+
+ x = self.output_block(x)
+
+ if input_dim_size > 4:
+ x = torch.split(x, B, dim=0) # [(B, C, H, W)]
+ outputs = torch.stack(x, dim=2) # (B, C, T, H, W)
+
+ else:
+ outputs = x
+
+ return outputs
+
+class Wav2Lip_disc_qual(nn.Module):
+ def __init__(self):
+ super(Wav2Lip_disc_qual, self).__init__()
+
+ self.face_encoder_blocks = nn.ModuleList([
+ nn.Sequential(nonorm_Conv2d(3, 32, kernel_size=7, stride=1, padding=3)), # 48,96
+
+ nn.Sequential(nonorm_Conv2d(32, 64, kernel_size=5, stride=(1, 2), padding=2), # 48,48
+ nonorm_Conv2d(64, 64, kernel_size=5, stride=1, padding=2)),
+
+ nn.Sequential(nonorm_Conv2d(64, 128, kernel_size=5, stride=2, padding=2), # 24,24
+ nonorm_Conv2d(128, 128, kernel_size=5, stride=1, padding=2)),
+
+ nn.Sequential(nonorm_Conv2d(128, 256, kernel_size=5, stride=2, padding=2), # 12,12
+ nonorm_Conv2d(256, 256, kernel_size=5, stride=1, padding=2)),
+
+ nn.Sequential(nonorm_Conv2d(256, 512, kernel_size=3, stride=2, padding=1), # 6,6
+ nonorm_Conv2d(512, 512, kernel_size=3, stride=1, padding=1)),
+
+ nn.Sequential(nonorm_Conv2d(512, 512, kernel_size=3, stride=2, padding=1), # 3,3
+ nonorm_Conv2d(512, 512, kernel_size=3, stride=1, padding=1),),
+
+ nn.Sequential(nonorm_Conv2d(512, 512, kernel_size=3, stride=1, padding=0), # 1, 1
+ nonorm_Conv2d(512, 512, kernel_size=1, stride=1, padding=0)),])
+
+ self.binary_pred = nn.Sequential(nn.Conv2d(512, 1, kernel_size=1, stride=1, padding=0), nn.Sigmoid())
+ self.label_noise = .0
+
+ def get_lower_half(self, face_sequences):
+ return face_sequences[:, :, face_sequences.size(2)//2:]
+
+ def to_2d(self, face_sequences):
+ B = face_sequences.size(0)
+ face_sequences = torch.cat([face_sequences[:, :, i] for i in range(face_sequences.size(2))], dim=0)
+ return face_sequences
+
+ def perceptual_forward(self, false_face_sequences):
+ false_face_sequences = self.to_2d(false_face_sequences)
+ false_face_sequences = self.get_lower_half(false_face_sequences)
+
+ false_feats = false_face_sequences
+ for f in self.face_encoder_blocks:
+ false_feats = f(false_feats)
+
+ false_pred_loss = F.binary_cross_entropy(self.binary_pred(false_feats).view(len(false_feats), -1),
+ torch.ones((len(false_feats), 1)).cuda())
+
+ return false_pred_loss
+
+ def forward(self, face_sequences):
+ face_sequences = self.to_2d(face_sequences)
+ face_sequences = self.get_lower_half(face_sequences)
+
+ x = face_sequences
+ for f in self.face_encoder_blocks:
+ x = f(x)
+
+ return self.binary_pred(x).view(len(x), -1)
diff --git a/train_audio/preparation_step0.py b/train_audio/preparation_step0.py
new file mode 100644
index 0000000..a53cf97
--- /dev/null
+++ b/train_audio/preparation_step0.py
@@ -0,0 +1,124 @@
+import os
+current_dir = os.path.dirname(os.path.abspath(__file__))
+import sys
+sys.path.append(os.path.join(current_dir, ".."))
+
+import sys, audio
+from tqdm import tqdm
+import glob
+from models import Wav2Lip
+import cv2
+import numpy as np
+import torch
+device = 'cuda' if torch.cuda.is_available() else 'cpu'
+checkpoint_path = "checkpoints/wav2lip.pth"
+
+mel_step_size = 16
+wav2lip_batch_size = 8
+img_size = 96
+fps = 25
+device = 'cuda' if torch.cuda.is_available() else 'cpu'
+print('Using {} for inference.'.format(device))
+Wav2Lip_model = None
+def load_model(path):
+ model = Wav2Lip()
+ print("Load checkpoint from: {}".format(path))
+ checkpoint = torch.load(path)
+ s = checkpoint["state_dict"]
+ new_s = {}
+ for k, v in s.items():
+ new_s[k.replace('module.', '')] = v
+ model.load_state_dict(new_s)
+
+ model = model.to(device)
+ return model.eval()
+
+def face_detect(image):
+ from talkingface.mediapipe_utils import detect_face_mesh
+ keypoints = detect_face_mesh([image])[0]
+ x_min, y_min, x_max, y_max = np.min(keypoints[:, 0]), np.min(keypoints[:, 1]), np.max(keypoints[:, 0]), np.max(
+ keypoints[:, 1])
+ y_min = y_min - (y_max - y_min) * 0.1
+ (x1, y1, x2, y2) = np.array([x_min, y_min, x_max, y_max], dtype = int)
+ face = image[y1: y2, x1:x2]
+ face = cv2.resize(face, (96, 96))
+ return face
+
+def datagen(image, mels):
+ img_batch = []
+ mel_batch = []
+ for i, m in enumerate(mels):
+ img_batch.append(image)
+ mel_batch.append(m)
+ if len(img_batch) >= wav2lip_batch_size:
+ img_batch, mel_batch = np.asarray(img_batch), np.asarray(mel_batch)
+
+ img_masked = img_batch.copy()
+ img_masked[:, img_size // 2:] = 0
+
+ img_batch = np.concatenate((img_masked, img_batch), axis=3) / 255.
+ mel_batch = np.reshape(mel_batch, [len(mel_batch), mel_batch.shape[1], mel_batch.shape[2], 1])
+
+ yield img_batch, mel_batch
+ img_batch, mel_batch = [], []
+
+
+def main(face_image, wav_path, outfile):
+ global Wav2Lip_model
+ if Wav2Lip_model is None:
+ Wav2Lip_model = load_model(checkpoint_path)
+ print(wav_path)
+ wav = audio.load_wav(wav_path, 16000)
+ mel = audio.melspectrogram(wav)
+ print(mel.shape)
+
+ mel_chunks = []
+ mel_idx_multiplier = 80. / fps
+ i = 0
+ while 1:
+ start_idx = int(i * mel_idx_multiplier)
+ if start_idx + mel_step_size > len(mel[0]):
+ mel_chunks.append(mel[:, len(mel[0]) - mel_step_size:])
+ break
+ mel_chunks.append(mel[:, start_idx: start_idx + mel_step_size])
+ i += 1
+
+ print("Length of mel chunks: {}".format(len(mel_chunks)))
+
+ batch_size = 8
+ gen = datagen(face_image, mel_chunks)
+
+ for i, (img_batch, mel_batch) in enumerate(tqdm(gen, total=int(np.ceil(float(len(mel_chunks)) / batch_size)))):
+ if i == 0:
+ out = cv2.VideoWriter(outfile, cv2.VideoWriter_fourcc(*'DIVX'), fps, (96, 96))
+
+ img_batch = torch.FloatTensor(np.transpose(img_batch, (0, 3, 1, 2))).to(device)
+ mel_batch = torch.FloatTensor(np.transpose(mel_batch, (0, 3, 1, 2))).to(device)
+
+ with torch.no_grad():
+ pred = Wav2Lip_model(mel_batch, img_batch)
+
+ pred = pred.cpu().numpy().transpose(0, 2, 3, 1) * 255.
+
+ for p in pred:
+ f = p.astype(np.uint8)
+ out.write(f)
+ out.release()
+
+if __name__ == '__main__':
+ if len(sys.argv) < 3:
+ print("Usage: python preparation_step0.py ")
+ sys.exit(1) # 参数数量不正确时退出程序
+
+ # 获取video_name参数
+ face_path = sys.argv[1]
+ print(f"Face path is set to: {face_path}")
+ wav_16K_path = sys.argv[2]
+ print(f"Wav 16K path is set to: {wav_16K_path}, please make sure all wav files duration not less than 2s.")
+
+ image = cv2.imread(face_path)
+ face_pix96 = face_detect(image)
+ wav_files = glob.glob(os.path.join(wav_16K_path, "*.wav"))
+ for index_, wav_path in enumerate(wav_files):
+ outfile = wav_path.replace(".wav", ".avi")
+ main(face_pix96, wav_path, outfile)
diff --git a/train_audio/preparation_step1.py b/train_audio/preparation_step1.py
new file mode 100644
index 0000000..295c0ef
--- /dev/null
+++ b/train_audio/preparation_step1.py
@@ -0,0 +1,123 @@
+import os
+current_dir = os.path.dirname(os.path.abspath(__file__))
+import sys
+sys.path.append(os.path.join(current_dir, ".."))
+from sklearn import decomposition
+import imageio
+import numpy as np
+import cv2
+import pickle
+import tqdm
+import glob
+from talkingface.utils import INDEX_LIPS_OUTER,main_keypoints_index
+from talkingface.mediapipe_utils import detect_face_mesh
+
+def main(video_path_list):
+ cap = cv2.VideoCapture(video_path_list[0])
+ vid_frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
+ frames = []
+ for i in range(min(500, vid_frame_count)):
+ frames.append(cap.read()[1])
+ cap.release()
+ keypoints = detect_face_mesh(frames)
+ keypoints = keypoints[:, main_keypoints_index]
+ print(keypoints.shape, len(main_keypoints_index))
+ # 先根据一个视频的前500帧估计嘴巴范围
+ x_min, x_max = np.min(keypoints[:, INDEX_LIPS_OUTER, 0]), np.max(keypoints[:, INDEX_LIPS_OUTER, 0])
+ y_min, y_max = np.min(keypoints[:, INDEX_LIPS_OUTER, 1]), np.max(keypoints[:, INDEX_LIPS_OUTER, 1])
+ x_mid, y_mid = (x_min + x_max) / 2, (y_min + y_max) / 2
+ x_len, y_len = (x_max - x_min) / 2, (y_max - y_min) / 2
+ x_min, x_max = x_mid - x_len * 0.9, x_mid + x_len * 0.9
+ y_min, y_max = y_mid - y_len * 0.9, y_mid + y_len * 0.9
+ print("嘴部区域:", x_min, x_max, y_min, y_max)
+ frames = []
+ num_sum = 0
+ for video_path in video_path_list:
+ cap = cv2.VideoCapture(video_path)
+ vid_frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
+ for i in range(vid_frame_count):
+ frame = cv2.resize(cap.read()[1][int(y_min):int(y_max), int(x_min):int(x_max)], (30, 15)).astype(np.float32)
+ # frame = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY).astype(np.float32)
+ tmp = (frame[:, :15] + frame[:, 15:][:, ::-1]) / 2
+ frame = np.concatenate([tmp, tmp[:, ::-1]], axis=1)
+ # max_, min_ = np.max(frame), np.min(frame)
+ # print(max_, min_)
+ frame = (frame - 60) / (180 - 60.) * 255
+ frame = frame.clip(0, 255).astype(np.uint8)
+ # cv2.imshow("s", cv2.resize(frame, (400,200)))
+ # cv2.waitKey(40)
+ frames.append(frame)
+ cap.release()
+ num_sum += vid_frame_count
+ if num_sum > 100000:
+ break
+ # exit()
+
+ out_size = [30, 15]
+
+ x = np.array([frame.flatten() for frame in frames])
+ del frames
+ n_components = 7
+ pca = decomposition.PCA(n_components=n_components)
+ pca.fit(x[:150000])
+ y = pca.transform(x[:30000])
+ print("PCA建模完成")
+ frames = []
+ for index_ in range(n_components):
+ bs_sort = np.sort(y[:, index_])
+ y_min_bs = bs_sort[int(0. * len(bs_sort))]
+ y_max_bs = bs_sort[int(1 * len(bs_sort)) - 1]
+ frames_ = []
+ # 从-0.5到1.5,均分为30份
+ list_ = [0 + jj * 1. / 30 for jj in range(30)]
+ for index__ in list_:
+ weight = y_min_bs + index__ * (y_max_bs - y_min_bs)
+ frame = pca.mean_ + pca.components_[index_] * weight
+ frame = frame.reshape(out_size[1], out_size[0], 3)
+ frame = frame.clip(0, 255).astype(np.uint8)
+ frame = cv2.resize(frame, (frame.shape[1] * 20, frame.shape[0] * 20))
+ # cv2.imshow("s", frame)
+ # cv2.waitKey(30)
+
+ frames_.append(frame)
+ frames.append(frames_)
+ frames_final = []
+ for i in range(30):
+ img0 = np.concatenate([frames[0][i], frames[1][i], frames[2][i]], axis=1)
+ img1 = np.concatenate([frames[3][i], frames[4][i], frames[5][i]], axis=1)
+ frame = np.concatenate([img0, img1])
+ frames_final.append(frame[:, :, ::-1])
+
+ imageio.mimsave("checkpoints/wav2lip_pca_all.gif", frames_final, 'GIF', duration=0.15)
+
+ Path_output_pkl = r"checkpoints/pca.pkl"
+ with open(Path_output_pkl, "wb") as f:
+ pickle.dump(pca, f)
+
+ for video_path in tqdm.tqdm(video_path_list[:]):
+ frames = []
+
+ cap = cv2.VideoCapture(video_path)
+ vid_frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
+ for i in range(vid_frame_count):
+ frame = cv2.resize(cap.read()[1][int(y_min):int(y_max), int(x_min):int(x_max)], (30, 15))
+ # frame = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
+ frames.append(frame)
+ cap.release()
+
+ x = np.array([frame.flatten() for frame in frames])
+ y = pca.transform(x)
+ pca_coefs_path = video_path.replace(".avi", ".txt")
+ np.savetxt(pca_coefs_path, y, fmt="%.02f")
+ print("Done!")
+
+
+if __name__ == '__main__':
+ if len(sys.argv) < 2:
+ print("Usage: python preparation_step1.py ")
+ sys.exit(1) # 参数数量不正确时退出程序
+
+ # 获取video_name参数
+ data_path = sys.argv[1]
+ video_path_list = glob.glob(os.path.join(data_path, "*.avi"))
+ main(video_path_list)
\ No newline at end of file
diff --git a/train_audio/test.py b/train_audio/test.py
new file mode 100644
index 0000000..d60c7f6
--- /dev/null
+++ b/train_audio/test.py
@@ -0,0 +1,89 @@
+import os
+current_dir = os.path.dirname(os.path.abspath(__file__))
+import sys
+sys.path.append(os.path.join(current_dir, ".."))
+
+import pickle
+import numpy as np
+import kaldi_native_fbank as knf
+from scipy.io import wavfile
+import torch
+import glob
+import cv2
+import os
+from talkingface.models.audio2bs_lstm import Audio2Feature
+
+def main(wavpath, ckpt_path):
+ device = "cuda" if torch.cuda.is_available() else "cpu"
+ # 加载模型
+ Audio2FeatureModel = Audio2Feature().to(device)
+ Audio2FeatureModel.load_state_dict(torch.load(ckpt_path))
+ Audio2FeatureModel.eval()
+ Path_output_pkl = "checkpoints/pca.pkl"
+ with open(Path_output_pkl, "rb") as f:
+ pca = pickle.load(f)
+ rate, wav = wavfile.read(wavpath, mmap=False)
+ augmented_samples = wav
+ augmented_samples2 = augmented_samples.astype(np.float32, order='C') / 32768.0
+ print(augmented_samples2.shape, augmented_samples2.shape[0] / 16000)
+
+ opts = knf.FbankOptions()
+ opts.frame_opts.dither = 0
+ opts.frame_opts.frame_length_ms = 50
+ opts.frame_opts.frame_shift_ms = 20
+ opts.mel_opts.num_bins = 80
+ opts.frame_opts.snip_edges = False
+ opts.mel_opts.debug_mel = False
+ fbank = knf.OnlineFbank(opts)
+ fbank.accept_waveform(16000, augmented_samples2.tolist())
+ seq_len = fbank.num_frames_ready // 2
+ A2Lsamples = np.zeros([2 * seq_len, 80])
+ for i in range(2 * seq_len):
+ print(i)
+ f2 = fbank.get_frame(i)
+ A2Lsamples[i] = f2
+
+ orig_mel = A2Lsamples
+ print(orig_mel.shape)
+ input = torch.from_numpy(orig_mel).unsqueeze(0).float().to(device)
+ print(input.shape)
+ h0 = torch.zeros(2, 1, 192).to(device)
+ c0 = torch.zeros(2, 1, 192).to(device)
+ bs_array, hn, cn = Audio2FeatureModel(input, h0, c0)
+ print(bs_array.shape)
+ bs_array = bs_array[0].detach().cpu().float().numpy()
+ print(bs_array.shape)
+ bs_array = bs_array[4:]
+ frame_num = len(bs_array)
+ import uuid
+
+ task_id = str(uuid.uuid1())
+ for frame_index in range(frame_num):
+ bs_real = bs_array[frame_index]
+ pts = np.dot(bs_real[:2], pca.components_[:2]) + pca.mean_
+ ref_img_ = pts.reshape(15, -1, 3).astype(np.uint8)
+ frame = cv2.resize(ref_img_, (ref_img_.shape[1] * 4, ref_img_.shape[0] * 4))
+
+ # for point in pts:
+ # cv2.circle(frame, (int(point[0]), int(point[1])), point_size, point_color, thickness)
+
+ os.makedirs("output/{}".format(task_id), exist_ok=True)
+ cv2.imwrite("output/{}/{:>06d}.png".format(task_id, frame_index), frame)
+ # cv2.imshow("aa", frame)
+ # cv2.waitKey(16)
+
+ cv2.destroyAllWindows()
+ val_video = "output/{}.mp4".format(task_id)
+ os.system(
+ "ffmpeg -r 25 -i output/{}/%06d.png -i {} -c:v libx264 -pix_fmt yuv420p {}".format(task_id, wavpath, val_video))
+
+if __name__ == '__main__':
+ if len(sys.argv) < 3:
+ print("Usage: python test.py ")
+ sys.exit(1) # 参数数量不正确时退出程序
+
+ # 获取video_name参数
+ wav_path = sys.argv[1]
+ ckpt_path = sys.argv[2]
+ # model_path = 'checkpoints/audio.pkl'
+ main(wav_path, ckpt_path)
\ No newline at end of file
diff --git a/train_audio/train_lstm.py b/train_audio/train_lstm.py
new file mode 100644
index 0000000..dec5aa3
--- /dev/null
+++ b/train_audio/train_lstm.py
@@ -0,0 +1,244 @@
+import os
+current_dir = os.path.dirname(os.path.abspath(__file__))
+import sys
+sys.path.append(os.path.join(current_dir, ".."))
+import glob
+
+model_name = "lstm"
+seq_len = 26
+from talkingface.models.audio2bs_lstm import Audio2Feature
+import torch
+from torch.utils.data import DataLoader
+from talkingface.data.dataset_wav import AudioVisualDataset
+device = "cuda" if torch.cuda.is_available() else "cpu"
+from scipy.io import wavfile
+import pickle
+import cv2
+import tqdm
+import numpy as np
+import os
+
+
+def main(data_path):
+ pcm_16k_list = []
+ pca_info_list = []
+ print("Loading all data into memory. Make sure your memory is enough.")
+ wav2_dir = glob.glob(os.path.join(data_path, "*.wav"))
+ for index_, wav_file in enumerate(wav2_dir):
+ coef_path = wav_file.replace(".wav", ".txt")
+ pca_coef = np.loadtxt(coef_path)
+ rate, wav = wavfile.read(wav_file, mmap=False)
+ pca_info_list.append(pca_coef[:, :6])
+ pcm_16k_list.append(wav)
+ print("All data Loaded. Total wav files number: {}. Total pca files number: {}.".format(len(pcm_16k_list),
+ len(pca_info_list)))
+ Path_output_pkl = "checkpoints/pca.pkl"
+ with open(Path_output_pkl, "rb") as f:
+ pca = pickle.load(f)
+
+ def generate_ref_image(bs_real, bs_pred):
+ # print(bs_real.shape, bs_pred.shape)
+ pts = np.dot(bs_real[:8], pca.components_[:6]) + pca.mean_
+ ref_img_ = pts.reshape(8, 15, 30, 3).transpose(1, 0, 2, 3).reshape(15, -1, 3).astype(np.uint8)
+ ref_img_ = cv2.resize(ref_img_, (ref_img_.shape[1] * 5, ref_img_.shape[0] * 5))
+ pts = np.dot(bs_pred[:8], pca.components_[:6]) + pca.mean_
+ ref_img_2 = pts.reshape(8, 15, 30, 3).transpose(1, 0, 2, 3).reshape(15, -1, 3).astype(np.uint8)
+ ref_img_2 = cv2.resize(ref_img_2, (ref_img_2.shape[1] * 5, ref_img_2.shape[0] * 5))
+ ref_img_ = np.concatenate([ref_img_, ref_img_2], axis=0)
+ return ref_img_
+
+ from sklearn.model_selection import train_test_split
+ import random
+ random_st = random.choice(range(10000))
+ print("random_st:", random_st)
+ random_st = 777
+ train_pcm_16k_list, test_pcm_16k_list, train_pca_info_list, test_pca_info_list = train_test_split(pcm_16k_list,
+ pca_info_list,
+ test_size=0.2,
+ random_state=random_st)
+
+ train_audioVisualDataset = AudioVisualDataset(train_pcm_16k_list, train_pca_info_list, seq_len=seq_len)
+ test_audioVisualDataset = AudioVisualDataset(test_pcm_16k_list, test_pca_info_list, seq_len=seq_len)
+
+ training_data_loader = DataLoader(dataset=train_audioVisualDataset, num_workers=0, batch_size=32, shuffle=True)
+ test_data_loader = DataLoader(dataset=test_audioVisualDataset, num_workers=0, batch_size=8, shuffle=True)
+
+ # 加载模型
+ Audio2FeatureModel = Audio2Feature().to(device)
+ criterionL1 = torch.nn.L1Loss().to(device)
+
+ # setup optimizer
+ optimizer = torch.optim.Adam(Audio2FeatureModel.parameters(), lr=0.0004, betas=(0.9, 0.99))
+
+ # tensorboard设置
+ train_log_path = os.path.join("checkpoints/log", model_name, "train")
+ val_log_path = os.path.join("checkpoints/log", model_name, "val")
+ os.makedirs(train_log_path, exist_ok=True)
+ os.makedirs(val_log_path, exist_ok=True)
+ from torch.utils.tensorboard import SummaryWriter
+ train_logger = SummaryWriter(train_log_path)
+ val_logger = SummaryWriter(val_log_path)
+
+ def log(
+ logger, step=None, losses=None, fig=None, audio=None, sampling_rate=22050, tag="", video=None
+ ):
+ if losses is not None:
+ logger.add_scalar("Loss/loss", losses[0], step)
+
+ if fig is not None:
+ logger.add_image(tag, fig, 2, dataformats='HWC')
+ if video is not None:
+ logger.add_video(tag, video, fps=60)
+
+ if audio is not None:
+ logger.add_audio(
+ tag,
+ audio / max(abs(audio)),
+ sample_rate=sampling_rate,
+ )
+
+ point_size = 3
+ point_color = (0, 0, 255) # BGR
+ thickness = 3 # 0 、4、8
+ loss_iteration_100_train = 0
+ loss_iteration_100_test = 0
+ for epoch in range(0, 1001):
+ Audio2FeatureModel.train()
+ for iteration, batch in enumerate(training_data_loader):
+ A2Lsamples, target_pts2d = batch
+ A2Lsamples, target_pts2d = A2Lsamples.to(device), target_pts2d.to(device)
+ # print(len(batch), batch[0].size())
+ # # A2Lsamples, target_pts2d = batch[0].to(device), batch[1].to(device)
+ # print(iteration, A2Lsamples.shape, target_pts2d.shape)
+ bs = A2Lsamples.size()[0]
+ h0 = torch.zeros(2, bs, 192).to(device)
+ c0 = torch.zeros(2, bs, 192).to(device)
+ pred_pts2d, _, _ = Audio2FeatureModel(A2Lsamples, h0, c0)
+
+ # print(iteration, A2Lsamples.shape, target_pts2d.shape, pred_pts2d.shape)
+
+ # 25帧的序列,生成25帧的关键点,只使用第5-24帧的结果,和目标关键点序列target_pts2d的第0-19帧对应
+ output_dim_size = pred_pts2d.size()
+ if len(output_dim_size) > 2:
+ pred_pts2d = pred_pts2d[:, 4:]
+ target_pts2d = target_pts2d[:, :-4]
+ else:
+ pred_pts2d = pred_pts2d.view(output_dim_size[0], 1, output_dim_size[1])
+ target_pts2d = target_pts2d[:, seq_len // 2:seq_len // 2 + 1]
+
+ # print(pred_pts2d.shape, target_pts2d.shape)
+ # exit()
+
+ # Backward and optimize
+ optimizer.zero_grad()
+ # print(target_pts2d.size(), pred_pts2d.size())
+ # pred_pts2d = torch.ones_like(pred_pts2d).cuda() * 0.5
+ loss = criterionL1(target_pts2d, pred_pts2d)
+ # loss = cosine_loss(target_pts2d, pred_pts2d, bs)
+ loss.requires_grad_(True)
+ loss.backward()
+ optimizer.step()
+
+ print("===> Epoch[{}]({}/{}): Loss: {:.4f}".format(
+ epoch, iteration, len(training_data_loader), loss.item()))
+ loss_iteration_100_train += loss.item()
+
+ real_iteration = epoch * len(training_data_loader) + iteration
+
+ if real_iteration % 100 == 0 and real_iteration > 0:
+ losses = [loss_iteration_100_train / 100]
+ message1 = "Step {}/{}, ".format(real_iteration, epoch * len(training_data_loader))
+ message2 = "Loss: {:.4f},".format(
+ *losses
+ )
+
+ with open(os.path.join(train_log_path, "log.txt"), "a") as f:
+ f.write(message1 + message2 + "\n")
+
+ # outer_bar.write(message1 + message2)
+
+ log(train_logger, real_iteration, losses=losses)
+ loss_iteration_100_train = 0
+
+ if real_iteration % 300 == 0:
+ bs_pred = pred_pts2d[0].detach().cpu().float().numpy()
+ bs_real = target_pts2d[0].detach().cpu().float().numpy()
+ frame = generate_ref_image(bs_real, bs_pred)
+ log(
+ train_logger,
+ fig=frame,
+ tag="Training/epoch_{}_{}_predict".format(epoch, iteration),
+ )
+
+ Audio2FeatureModel.eval()
+
+ for iteration, batch in enumerate(test_data_loader):
+ A2Lsamples, target_pts2d = batch[0].to(device), batch[1].to(device)
+ bs = A2Lsamples.size()[0]
+ h0 = torch.zeros(2, bs, 192).to(device)
+ c0 = torch.zeros(2, bs, 192).to(device)
+ pred_pts2d, _, _ = Audio2FeatureModel(A2Lsamples, h0, c0)
+
+ output_dim_size = pred_pts2d.size()
+ if len(output_dim_size) > 2:
+ pred_pts2d = pred_pts2d[:, 4:]
+ target_pts2d = target_pts2d[:, :-4]
+ else:
+ pred_pts2d = pred_pts2d.view(output_dim_size[0], 1, output_dim_size[1])
+ target_pts2d = target_pts2d[:, seq_len // 2:seq_len // 2 + 1]
+
+ # print(iteration, A2Lsamples.shape, target_pts2d.shape, pred_pts2d.shape)
+ # pred_pts2d = torch.ones_like(pred_pts2d).cuda() * 0.5
+ loss = criterionL1(target_pts2d, pred_pts2d)
+ # loss = cosine_loss(target_pts2d, pred_pts2d, bs)
+ print("===> Epoch[{}]({}/{}): Loss: {:.4f}".format(
+ epoch, iteration, len(test_data_loader), loss.item()))
+
+ real_iteration = epoch * len(test_data_loader) + iteration
+ loss_iteration_100_test += loss.item()
+
+ if real_iteration % 100 == 0 and real_iteration > 0:
+ losses = [loss_iteration_100_test / 100]
+ message1 = "Step {}/{}, ".format(real_iteration, epoch * len(test_data_loader))
+ message2 = "Loss: {:.4f},".format(
+ *losses
+ )
+
+ with open(os.path.join(val_log_path, "log.txt"), "a") as f:
+ f.write(message1 + message2 + "\n")
+
+ # outer_bar.write(message1 + message2)
+
+ log(val_logger, real_iteration, losses=losses)
+ loss_iteration_100_test = 0
+
+ if real_iteration % 300 == 0:
+ bs_pred = pred_pts2d[0].detach().cpu().float().numpy()
+ bs_real = target_pts2d[0].detach().cpu().float().numpy()
+ frame = generate_ref_image(bs_real, bs_pred)
+ log(
+ train_logger,
+ fig=frame,
+ tag="Testing/epoch_{}_{}_predict".format(epoch, iteration),
+ )
+ # checkpoint
+ if epoch % 5 == 0:
+ if not os.path.exists("checkpoints"):
+ os.mkdir("checkpoints")
+ if not os.path.exists(os.path.join("checkpoints", model_name)):
+ os.mkdir(os.path.join("checkpoints", model_name))
+ model_out_path = "checkpoints/{}/epoch_{}.pth".format(model_name, epoch)
+ # states = { 'epoch': epoch + 1, 'state_dict': Audio2FeatureModel.state_dict(), 'optimizer': optimizer.state_dict() }
+ states = Audio2FeatureModel.state_dict()
+ torch.save(states, model_out_path)
+ print("Checkpoint saved to {}".format(epoch))
+ torch.save(Audio2FeatureModel.state_dict(), "checkpoints/audio.pkl")
+
+if __name__ == '__main__':
+ if len(sys.argv) < 2:
+ print("Usage: python train_lstm.py ")
+ sys.exit(1) # 参数数量不正确时退出程序
+
+ # 获取video_name参数
+ data_path = sys.argv[1]
+ main(data_path)
\ No newline at end of file
diff --git a/video_concat.txt b/video_concat.txt
new file mode 100644
index 0000000..dcdaac4
--- /dev/null
+++ b/video_concat.txt
@@ -0,0 +1,2 @@
+file 'front.mp4'
+file 'back.mp4'
\ No newline at end of file
diff --git a/video_data/audio0.wav b/video_data/audio0.wav
new file mode 100644
index 0000000..d879630
Binary files /dev/null and b/video_data/audio0.wav differ
diff --git a/video_data/audio1.wav b/video_data/audio1.wav
new file mode 100644
index 0000000..a6130f5
Binary files /dev/null and b/video_data/audio1.wav differ
diff --git a/video_data/demo.mp4 b/video_data/demo.mp4
new file mode 100644
index 0000000..ba018f5
Binary files /dev/null and b/video_data/demo.mp4 differ
diff --git a/video_data/test/circle.mp4 b/video_data/test/circle.mp4
new file mode 100644
index 0000000..8ee4930
Binary files /dev/null and b/video_data/test/circle.mp4 differ
diff --git a/video_data/test/keypoint_rotate.pkl b/video_data/test/keypoint_rotate.pkl
new file mode 100644
index 0000000..1719918
Binary files /dev/null and b/video_data/test/keypoint_rotate.pkl differ
diff --git a/web_demo/server.py b/web_demo/server.py
new file mode 100644
index 0000000..08f0f78
--- /dev/null
+++ b/web_demo/server.py
@@ -0,0 +1,27 @@
+import json
+import requests
+import time
+from starlette.staticfiles import StaticFiles
+from fastapi import FastAPI, Request
+from fastapi.responses import JSONResponse
+from fastapi.middleware.cors import CORSMiddleware
+from fastapi.responses import StreamingResponse
+import uuid
+import re
+app = FastAPI()
+
+# 允许前端跨域调用
+app.add_middleware(
+ CORSMiddleware,
+ allow_origins=["*"],
+ allow_credentials=True,
+ allow_methods=["*"],
+ allow_headers=["*"],
+)
+app.mount("/static", StaticFiles(directory="static"), name="static")
+
+# 启动Uvicorn服务器
+if __name__ == "__main__":
+ import uvicorn
+
+ uvicorn.run(app, host="0.0.0.0", port=8888)
\ No newline at end of file
diff --git a/web_demo/static/DHLiveMini.wasm b/web_demo/static/DHLiveMini.wasm
new file mode 100644
index 0000000..b8ae5c8
Binary files /dev/null and b/web_demo/static/DHLiveMini.wasm differ
diff --git a/web_demo/static/MiniLive.html b/web_demo/static/MiniLive.html
new file mode 100644
index 0000000..da40bd8
--- /dev/null
+++ b/web_demo/static/MiniLive.html
@@ -0,0 +1,89 @@
+
+
+
+
+
+
+
+ MiniLive
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/web_demo/static/assets/01.mp4 b/web_demo/static/assets/01.mp4
new file mode 100644
index 0000000..04452b4
Binary files /dev/null and b/web_demo/static/assets/01.mp4 differ
diff --git a/web_demo/static/assets/bs_texture_halfFace.png b/web_demo/static/assets/bs_texture_halfFace.png
new file mode 100644
index 0000000..f28a247
Binary files /dev/null and b/web_demo/static/assets/bs_texture_halfFace.png differ
diff --git a/web_demo/static/assets/face3D.obj b/web_demo/static/assets/face3D.obj
new file mode 100644
index 0000000..1831cf9
--- /dev/null
+++ b/web_demo/static/assets/face3D.obj
@@ -0,0 +1,696 @@
+v 498.817 737.983 -238.767 2.00 0
+v 503.928 697.292 -236.049 -1.00 1
+v 499.195 746.284 -236.865 2.00 2
+v 499.807 755.259 -230.745 2.00 3
+v 500.646 761.073 -222.339 2.00 4
+v 501.051 778.732 -217.698 2.01 5
+v 501.303 788.041 -219.775 2.01 6
+v 501.056 799.634 -221.794 2.01 7
+v 501.775 811.280 -216.869 2.01 8
+v 505.085 827.477 -196.870 0.00 9
+v 437.686 848.623 -176.136 0.00 10
+v 411.647 665.445 -195.787 0.00 11
+v 478.348 735.267 -236.262 2.00 12
+v 481.087 755.568 -228.449 2.00 13
+v 457.773 744.532 -226.237 2.00 14
+v 444.621 753.774 -214.008 2.00 15
+v 464.765 758.297 -222.252 2.00 16
+v 453.180 762.213 -210.319 2.00 17
+v 424.472 791.869 -183.022 0.00 18
+v 354.476 664.647 -172.240 0.00 19
+v 412.623 771.959 -181.565 0.00 20
+v 325.447 759.741 -22.661 0.00 21
+v 431.711 770.647 -186.137 2.00 22
+v 435.257 770.498 -190.067 2.00 23
+v 479.031 746.040 -234.543 2.00 24
+v 460.948 751.780 -225.250 2.00 25
+v 448.481 758.085 -213.703 2.00 26
+v 433.618 770.615 -187.957 2.00 27
+v 439.883 778.162 -196.363 2.01 28
+v 437.421 770.572 -190.515 2.00 29
+v 456.386 764.876 -207.355 2.00 30
+v 468.607 762.437 -215.217 2.00 31
+v 483.248 761.045 -221.082 2.00 32
+v 480.248 826.884 -195.222 0.00 33
+v 479.185 809.779 -215.664 2.01 34
+v 479.555 798.320 -219.936 2.01 35
+v 481.629 786.848 -218.086 2.01 36
+v 483.593 778.433 -216.409 2.01 37
+v 456.609 776.128 -203.617 2.01 38
+v 452.802 779.859 -204.946 2.01 39
+v 447.950 785.443 -206.497 2.01 40
+v 445.212 791.962 -203.019 2.01 41
+v 430.694 735.241 -206.194 0.00 42
+v 301.317 661.529 4.777 0.00 43
+v 447.774 773.957 -196.165 2.01 44
+v 443.795 775.700 -196.932 2.01 45
+v 483.283 698.048 -230.849 -1.00 46
+v 457.565 696.433 -211.326 -1.00 47
+v 427.699 627.652 -193.175 -1.00 48
+v 397.453 641.065 -186.246 0.00 49
+v 437.599 805.762 -189.317 0.00 50
+v 308.961 613.113 -117.106 -1.00 51
+v 335.797 614.166 -152.844 -1.00 52
+v 357.544 621.452 -169.755 -1.00 53
+v 393.945 618.050 -178.651 -1.00 54
+v 313.168 656.169 -123.293 0.00 55
+v 445.157 676.595 -201.900 -1.00 56
+v 310.559 709.544 -3.794 0.00 57
+v 365.068 807.692 -116.102 0.00 58
+v 366.256 828.138 -84.270 0.00 59
+v 300.414 659.412 -59.035 0.00 60
+v 341.482 781.389 -94.182 0.00 61
+v 435.309 864.191 -166.269 0.00 62
+v 434.281 650.046 -200.525 -1.00 63
+v 436.842 781.131 -193.738 2.01 64
+v 319.962 695.921 -118.229 0.00 65
+v 468.142 886.942 -160.249 0.00 66
+v 416.762 865.797 -127.957 0.00 67
+v 394.179 851.296 -109.485 0.00 68
+v 503.713 888.472 -165.120 0.00 69
+v 504.010 712.606 -232.384 0.00 70
+v 448.211 723.275 -214.724 0.00 71
+v 480.794 714.716 -230.498 0.00 72
+v 389.450 831.141 -131.756 0.00 73
+v 411.566 847.834 -147.692 0.00 74
+v 465.058 876.199 -182.318 0.00 75
+v 344.574 799.942 -52.354 0.00 76
+v 502.095 877.706 -186.830 0.00 77
+v 440.248 878.238 -147.768 0.00 78
+v 308.206 703.349 -62.027 0.00 79
+v 468.949 777.530 -210.860 2.01 80
+v 465.215 783.865 -212.597 2.01 81
+v 461.531 792.745 -214.330 2.01 82
+v 460.035 802.994 -210.716 2.01 83
+v 455.730 818.121 -194.971 0.00 84
+v 443.319 766.291 -199.735 2.00 85
+v 439.251 764.350 -200.223 2.00 86
+v 435.746 762.080 -200.513 2.00 87
+v 418.626 751.871 -195.253 0.00 88
+v 344.030 706.912 -153.604 0.00 89
+v 446.884 767.621 -198.192 2.00 90
+v 347.776 754.229 -128.154 0.00 91
+v 445.696 833.178 -183.058 0.00 92
+v 502.450 862.664 -196.041 0.00 93
+v 503.871 844.123 -195.894 0.00 94
+v 473.729 843.393 -191.513 0.00 95
+v 407.671 798.398 -170.584 0.00 96
+v 428.810 692.145 -196.253 0.00 97
+v 424.385 818.408 -175.768 0.00 98
+v 383.500 689.462 -187.362 0.00 99
+v 411.323 711.743 -193.500 0.00 100
+v 370.526 721.680 -174.536 0.00 101
+v 467.241 861.413 -191.062 0.00 102
+v 393.568 811.779 -152.816 0.00 103
+v 415.692 831.222 -161.822 0.00 104
+v 393.910 773.790 -171.387 0.00 105
+v 328.375 729.349 -112.131 0.00 106
+v 370.911 776.320 -151.778 0.00 107
+v 320.561 743.911 -70.524 0.00 108
+v 398.747 737.820 -186.165 0.00 109
+v 295.345 616.042 -62.461 -1.00 110
+v 296.648 616.156 4.740 -1.00 111
+v 563.584 842.609 -177.416 0.00 112
+v 590.620 665.297 -198.483 0.00 113
+v 518.169 735.101 -235.423 2.00 114
+v 516.542 755.564 -227.595 2.00 115
+v 537.690 742.747 -224.122 2.00 116
+v 550.755 751.911 -210.304 2.00 117
+v 530.780 757.605 -219.708 2.00 118
+v 542.526 761.219 -207.211 2.00 119
+v 577.115 788.599 -182.135 0.00 120
+v 644.126 664.607 -174.501 0.00 121
+v 589.370 769.280 -178.535 0.00 122
+v 676.860 754.636 -19.059 0.00 123
+v 566.410 770.084 -179.279 2.00 124
+v 560.378 769.522 -185.603 2.00 125
+v 517.606 746.050 -233.620 2.00 126
+v 534.281 750.764 -222.967 2.00 127
+v 546.553 756.699 -210.581 2.00 128
+v 563.229 769.918 -182.869 2.00 129
+v 555.928 776.825 -193.532 2.01 130
+v 558.082 769.492 -185.919 2.00 131
+v 539.110 763.824 -203.944 2.00 132
+v 528.795 761.821 -212.420 2.00 133
+v 515.859 760.894 -219.299 2.00 134
+v 526.767 825.532 -197.215 0.00 135
+v 522.069 808.709 -215.800 2.01 136
+v 520.404 797.286 -219.355 2.01 137
+v 518.976 786.114 -216.800 2.01 138
+v 516.574 777.886 -214.617 2.01 139
+v 539.774 774.387 -200.267 2.01 140
+v 543.204 778.284 -203.137 2.01 141
+v 547.036 783.714 -205.808 2.01 142
+v 551.538 790.129 -202.255 2.01 143
+v 571.296 733.560 -206.155 0.00 144
+v 706.017 662.354 6.609 0.00 145
+v 548.332 772.323 -190.978 2.01 146
+v 551.939 774.283 -193.360 2.01 147
+v 523.632 697.775 -231.453 -1.00 148
+v 548.267 695.430 -213.779 -1.00 149
+v 575.156 628.054 -193.241 -1.00 150
+v 604.884 641.458 -188.213 0.00 151
+v 564.170 802.276 -188.962 0.00 152
+v 690.174 614.823 -118.018 -1.00 153
+v 659.527 614.045 -155.582 -1.00 154
+v 637.392 622.120 -173.390 -1.00 155
+v 604.937 619.102 -180.957 -1.00 156
+v 686.347 656.264 -123.143 0.00 157
+v 561.071 676.142 -203.396 -1.00 158
+v 694.638 707.310 -1.403 0.00 159
+v 633.649 799.861 -114.205 0.00 160
+v 632.821 818.394 -81.727 0.00 161
+v 704.136 659.486 -57.603 0.00 162
+v 657.074 775.317 -91.660 0.00 163
+v 565.210 856.909 -165.961 0.00 164
+v 568.465 650.051 -201.365 -1.00 165
+v 560.203 779.798 -190.418 2.01 166
+v 678.981 694.518 -117.952 0.00 167
+v 536.808 882.237 -159.982 0.00 168
+v 585.203 855.516 -126.073 0.00 169
+v 606.624 840.300 -106.849 0.00 170
+v 556.120 722.099 -214.652 0.00 171
+v 525.866 714.357 -230.626 0.00 172
+v 609.956 822.179 -131.058 0.00 173
+v 587.890 838.656 -147.662 0.00 174
+v 536.626 872.224 -182.534 0.00 175
+v 655.788 792.331 -48.552 0.00 176
+v 562.686 870.030 -145.970 0.00 177
+v 693.671 701.174 -60.624 0.00 178
+v 529.434 776.275 -208.045 2.01 179
+v 532.925 782.470 -210.673 2.01 180
+v 535.946 791.065 -213.079 2.01 181
+v 539.198 801.286 -209.807 2.01 182
+v 547.552 815.223 -194.916 0.00 183
+v 551.998 765.067 -195.298 2.00 184
+v 556.592 763.179 -194.891 2.00 185
+v 560.467 760.694 -194.679 2.00 186
+v 582.981 749.897 -192.647 0.00 187
+v 653.177 705.431 -155.271 0.00 188
+v 548.265 766.439 -193.151 2.00 189
+v 650.818 750.312 -127.341 0.00 190
+v 556.745 828.352 -184.908 0.00 191
+v 531.808 840.811 -193.526 0.00 192
+v 592.694 793.600 -171.450 0.00 193
+v 575.970 691.245 -198.723 0.00 194
+v 576.107 812.900 -177.754 0.00 195
+v 616.374 688.641 -191.523 0.00 196
+v 591.505 710.471 -195.783 0.00 197
+v 627.386 719.777 -176.976 0.00 198
+v 535.675 858.218 -191.651 0.00 199
+v 606.128 804.803 -153.327 0.00 200
+v 584.989 823.914 -163.630 0.00 201
+v 606.666 770.245 -169.799 0.00 202
+v 670.057 726.529 -111.502 0.00 203
+v 626.843 771.308 -151.785 0.00 204
+v 679.590 739.889 -67.795 0.00 205
+v 601.843 736.026 -186.456 0.00 206
+v 707.683 618.404 -60.591 -1.00 207
+v 711.020 619.372 6.618 -1.00 208
+v 286.340 612.648 5.129 -1.00 209
+v 286.205 659.669 5.362 -1.00 210
+v 291.334 711.866 -3.871 -1.00 211
+v 303.277 768.918 -25.116 -1.00 212
+v 320.838 816.983 -59.754 -1.00 213
+v 342.358 852.955 -98.489 -1.00 214
+v 372.452 884.289 -130.778 -1.00 215
+v 397.400 906.177 -156.067 -1.00 216
+v 424.606 926.215 -183.955 -1.00 217
+v 458.607 942.110 -203.487 -1.00 218
+v 503.983 949.114 -213.749 -1.00 219
+v 546.157 936.112 -203.146 -1.00 220
+v 577.655 915.954 -181.707 -1.00 221
+v 603.741 893.583 -153.759 -1.00 222
+v 627.386 871.094 -127.614 -1.00 223
+v 655.572 841.505 -95.500 -1.00 224
+v 678.734 808.231 -55.381 -1.00 225
+v 698.616 763.174 -21.063 -1.00 226
+v 713.820 709.408 -1.241 -1.00 227
+v 721.257 660.556 7.332 -1.00 228
+v 721.430 616.024 7.100 -1.00 229
+v 441.941 769.162 -176.353 3.00 230
+v 539.136 745.589 -196.660 3.00 231
+v 521.092 772.270 -210.566 3.00 232
+v 475.945 745.565 -210.944 3.00 233
+v 521.030 745.447 -210.641 3.00 234
+v 432.377 768.711 -155.439 3.00 235
+v 563.715 768.561 -155.357 3.00 236
+v 555.271 769.097 -176.335 3.00 237
+v 456.545 745.514 -195.760 3.00 238
+v 564.140 745.685 -155.788 3.00 239
+v 476.245 772.455 -210.878 3.00 240
+v 456.528 770.568 -195.789 3.00 241
+v 539.473 770.451 -196.421 3.00 242
+v 441.807 744.878 -176.518 3.00 243
+v 498.400 745.514 -215.260 3.00 244
+v 498.377 773.093 -215.251 3.00 245
+v 433.018 745.712 -155.636 3.00 246
+v 555.351 744.838 -176.471 3.00 247
+v 446.997 794.902 -175.130 4.00 248
+v 535.135 773.068 -192.046 4.00 249
+v 517.908 796.238 -200.416 4.00 250
+v 480.007 774.372 -200.768 4.00 251
+v 517.640 774.347 -200.837 4.00 252
+v 436.078 793.372 -154.143 4.00 253
+v 562.866 793.734 -154.157 4.00 254
+v 551.808 794.833 -175.253 4.00 255
+v 462.915 773.112 -191.749 4.00 256
+v 562.873 769.561 -154.555 4.00 257
+v 480.137 796.380 -200.737 4.00 258
+v 462.918 795.634 -191.987 4.00 259
+v 534.932 795.566 -192.110 4.00 260
+v 447.042 771.230 -175.249 4.00 261
+v 499.009 775.069 -205.285 4.00 262
+v 498.963 796.053 -205.249 4.00 263
+v 435.938 769.624 -154.378 4.00 264
+v 551.914 771.225 -175.145 4.00 265
+f 115 1 127
+f 13 25 1
+f 3 127 1
+f 3 1 25
+f 115 127 117
+f 13 15 25
+f 128 117 127
+f 26 25 15
+f 78 70 176
+f 78 76 70
+f 169 176 70
+f 67 70 76
+f 122 156 152
+f 20 50 54
+f 157 152 156
+f 55 54 50
+f 117 128 118
+f 15 16 26
+f 129 118 128
+f 27 26 16
+f 113 202 192
+f 11 93 105
+f 196 192 202
+f 99 105 93
+f 129 186 118
+f 27 16 87
+f 187 118 186
+f 88 87 16
+f 120 133 185
+f 18 86 31
+f 190 185 133
+f 91 31 86
+f 145 118 188
+f 43 89 16
+f 187 188 118
+f 88 16 89
+f 205 203 201
+f 108 104 106
+f 194 201 203
+f 97 106 104
+f 136 137 10
+f 34 10 35
+f 9 10 137
+f 9 35 10
+f 131 167 130
+f 29 28 65
+f 125 130 167
+f 23 65 28
+f 192 196 184
+f 93 85 99
+f 153 184 196
+f 51 99 85
+f 164 191 161
+f 62 59 92
+f 205 161 191
+f 108 92 59
+f 172 195 150
+f 72 48 98
+f 159 150 195
+f 57 98 48
+f 143 144 131
+f 41 29 42
+f 167 131 144
+f 65 42 29
+f 122 197 189
+f 20 90 100
+f 199 189 197
+f 102 100 90
+f 193 136 95
+f 96 95 34
+f 10 95 136
+f 10 34 95
+f 153 144 184
+f 51 85 42
+f 183 184 144
+f 84 42 85
+f 183 144 182
+f 84 83 42
+f 143 182 144
+f 41 42 83
+f 9 137 8
+f 9 8 35
+f 138 8 137
+f 36 35 8
+f 197 114 198
+f 100 101 12
+f 195 198 114
+f 98 12 101
+f 165 176 178
+f 63 79 76
+f 169 178 176
+f 67 76 79
+f 172 117 145
+f 72 43 15
+f 118 145 117
+f 16 15 43
+f 162 161 171
+f 60 69 59
+f 174 171 161
+f 74 59 69
+f 202 113 175
+f 105 75 11
+f 165 175 113
+f 63 11 75
+f 153 121 144
+f 51 42 19
+f 167 144 121
+f 65 19 42
+f 148 126 147
+f 46 45 24
+f 132 147 126
+f 30 24 45
+f 158 154 155
+f 56 53 52
+f 197 198 199
+f 100 102 101
+f 207 199 198
+f 110 101 102
+f 172 173 117
+f 72 15 73
+f 115 117 173
+f 13 73 15
+f 94 200 95
+f 94 95 103
+f 193 95 200
+f 96 103 95
+f 152 151 114
+f 50 12 49
+f 166 114 151
+f 64 49 12
+f 194 203 121
+f 97 19 106
+f 123 121 203
+f 21 106 19
+f 201 194 202
+f 104 105 97
+f 196 202 194
+f 99 97 105
+f 196 194 153
+f 99 51 97
+f 121 153 194
+f 19 97 51
+f 130 126 131
+f 28 29 24
+f 148 131 126
+f 46 24 29
+f 163 208 158
+f 61 56 111
+f 154 158 208
+f 52 111 56
+f 127 116 128
+f 25 26 14
+f 119 128 116
+f 17 14 26
+f 166 159 114
+f 64 12 57
+f 195 114 159
+f 98 57 12
+f 128 119 129
+f 26 27 17
+f 120 129 119
+f 18 17 27
+f 199 207 205
+f 102 108 110
+f 203 205 207
+f 106 110 108
+f 129 120 186
+f 27 87 18
+f 185 186 120
+f 86 18 87
+f 174 201 175
+f 74 75 104
+f 202 175 201
+f 105 104 75
+f 175 165 170
+f 75 68 63
+f 178 170 165
+f 79 63 68
+f 122 189 158
+f 20 56 90
+f 168 158 189
+f 66 90 56
+f 142 143 148
+f 40 46 41
+f 131 148 143
+f 29 41 46
+f 182 143 181
+f 83 82 41
+f 142 181 143
+f 40 41 82
+f 152 157 151
+f 50 49 55
+f 146 209 163
+f 44 61 112
+f 208 163 209
+f 111 112 61
+f 8 138 7
+f 8 7 36
+f 139 7 138
+f 37 36 7
+f 7 139 6
+f 7 6 37
+f 140 6 139
+f 38 37 6
+f 180 181 141
+f 81 39 82
+f 142 141 181
+f 40 82 39
+f 147 141 148
+f 45 46 39
+f 142 148 141
+f 40 39 46
+f 177 164 162
+f 77 60 62
+f 161 162 164
+f 59 62 60
+f 124 206 177
+f 22 77 109
+f 164 177 206
+f 62 109 77
+f 119 134 120
+f 17 18 32
+f 133 120 134
+f 31 32 18
+f 121 123 167
+f 19 65 21
+f 125 167 123
+f 23 21 65
+f 176 200 78
+f 76 78 103
+f 94 78 200
+f 94 103 78
+f 116 135 119
+f 14 17 33
+f 134 119 135
+f 32 33 17
+f 185 190 126
+f 86 24 91
+f 132 126 190
+f 30 91 24
+f 158 155 122
+f 56 20 53
+f 156 122 155
+f 54 53 20
+f 171 174 170
+f 69 68 74
+f 175 170 174
+f 75 74 68
+f 198 145 207
+f 101 110 43
+f 188 207 145
+f 89 43 110
+f 173 149 71
+f 73 71 47
+f 2 71 149
+f 2 47 71
+f 1 115 71
+f 1 71 13
+f 173 71 115
+f 73 13 71
+f 3 4 127
+f 3 25 4
+f 116 127 4
+f 14 4 25
+f 4 5 116
+f 4 14 5
+f 135 116 5
+f 33 5 14
+f 122 152 197
+f 20 100 50
+f 114 197 152
+f 12 50 100
+f 195 172 198
+f 98 101 72
+f 145 198 172
+f 43 72 101
+f 172 150 173
+f 72 73 48
+f 149 173 150
+f 47 48 73
+f 205 201 161
+f 108 59 104
+f 174 161 201
+f 74 104 59
+f 113 200 165
+f 11 63 103
+f 176 165 200
+f 76 103 63
+f 139 181 140
+f 37 38 82
+f 180 140 181
+f 81 82 38
+f 138 182 139
+f 36 37 83
+f 181 139 182
+f 82 83 37
+f 137 183 138
+f 35 36 84
+f 182 138 183
+f 83 84 36
+f 136 184 137
+f 34 35 85
+f 183 137 184
+f 84 85 35
+f 192 184 193
+f 93 96 85
+f 136 193 184
+f 34 85 96
+f 163 179 146
+f 61 44 80
+f 160 146 179
+f 58 80 44
+f 186 185 130
+f 87 28 86
+f 126 130 185
+f 24 86 28
+f 186 130 187
+f 87 88 28
+f 125 187 130
+f 23 28 88
+f 188 187 123
+f 89 21 88
+f 125 123 187
+f 23 88 21
+f 207 188 203
+f 110 106 89
+f 123 203 188
+f 21 89 106
+f 205 191 199
+f 108 102 92
+f 189 199 191
+f 90 92 102
+f 158 168 163
+f 56 61 66
+f 179 163 168
+f 80 66 61
+f 200 113 193
+f 103 96 11
+f 192 193 113
+f 93 11 96
+f 164 206 191
+f 62 92 109
+f 204 191 206
+f 107 109 92
+f 168 204 179
+f 66 80 107
+f 206 179 204
+f 109 107 80
+f 189 191 168
+f 90 66 92
+f 204 168 191
+f 107 92 66
+f 160 179 124
+f 58 22 80
+f 206 124 179
+f 109 80 22
+f 112 210 44
+f 44 210 211
+f 44 211 58
+f 58 211 212
+f 58 212 22
+f 22 212 213
+f 22 213 77
+f 77 213 214
+f 77 214 60
+f 60 214 215
+f 60 215 69
+f 69 215 216
+f 69 216 68
+f 68 216 217
+f 68 217 79
+f 79 217 218
+f 79 218 67
+f 67 218 219
+f 67 219 70
+f 70 219 220
+f 70 220 169
+f 169 220 221
+f 169 221 178
+f 178 221 222
+f 178 222 170
+f 170 222 223
+f 170 223 171
+f 171 223 224
+f 171 224 162
+f 162 224 225
+f 162 225 177
+f 177 225 226
+f 177 226 124
+f 124 226 227
+f 124 227 160
+f 160 227 228
+f 160 228 146
+f 146 228 229
+f 146 229 209
+f 209 229 230
+f 240 248 237
+f 237 248 238
+f 248 232 238
+f 238 232 243
+f 232 235 243
+f 243 235 233
+f 235 245 233
+f 233 245 246
+f 245 234 246
+f 246 234 241
+f 234 239 241
+f 241 239 242
+f 239 244 242
+f 242 244 231
+f 244 247 231
+f 231 247 236
+f 258 266 255
+f 255 266 256
+f 266 250 256
+f 256 250 261
+f 250 253 261
+f 261 253 251
+f 253 263 251
+f 251 263 264
+f 263 252 264
+f 264 252 259
+f 252 257 259
+f 259 257 260
+f 257 262 260
+f 260 262 249
+f 262 265 249
+f 249 265 254
+f 240 247 254
+f 240 254 255
diff --git a/web_demo/static/assets/json_data.json b/web_demo/static/assets/json_data.json
new file mode 100644
index 0000000..c318ad7
--- /dev/null
+++ b/web_demo/static/assets/json_data.json
@@ -0,0 +1 @@
+[{"rect": [260, 446, 538, 724], "points": [0.36112, 0.05555, 0.09409, 0.0, -0.0629, 0.36057, -0.01918, 0.0, -0.11125, -0.01512, 0.36334, 0.0, -90.59755, -251.32371, -57.41388, 1.0, 70.0, 45.1, 73.7, 31.8, 69.5, 48.3, 68.6, 51.6, 67.7, 53.9, 65.8, 60.8, 65.8, 64.0, 65.4, 67.7, 64.5, 71.8, 62.2, 78.3, 33.6, 82.9, 37.3, 14.7, 62.6, 43.3, 61.2, 50.6, 52.9, 45.1, 46.0, 47.9, 54.3, 50.6, 48.3, 51.1, 32.7, 60.8, 14.3, 11.1, 29.0, 52.9, -18.0, 41.0, 37.3, 52.5, 39.1, 52.9, 61.7, 47.0, 53.4, 47.9, 47.4, 49.3, 38.2, 52.5, 41.0, 56.2, 40.1, 52.9, 49.3, 52.0, 54.8, 52.0, 60.8, 52.5, 52.9, 76.9, 55.7, 70.0, 57.1, 66.3, 58.5, 62.2, 59.4, 59.4, 47.9, 56.6, 46.5, 57.6, 44.7, 59.4, 42.8, 61.2, 41.0, 41.0, -23.0, 3.7, 44.2, 55.3, 42.4, 55.3, 65.4, 30.8, 53.9, 28.5, 45.1, 1.8, 32.7, 5.1, 37.3, 66.8, -4.6, -11.1, 8.7, -8.7, 18.0, -4.6, 32.7, -4.1, -5.1, 4.6, 49.3, 20.3, -22.1, 21.6, 3.2, 62.6, -0.9, 69.5, -16.6, 4.1, -6.0, 51.1, 30.4, 88.4, 47.0, 10.6, 39.6, 56.6, -6.0, 19.3, 41.0, 98.5, 19.8, 87.5, 10.6, 80.1, 54.3, 100.8, 72.3, 37.3, 49.3, 37.8, 63.5, 36.8, 12.4, 72.7, 20.7, 80.6, 42.4, 94.8, -10.1, 57.6, 56.6, 97.2, 29.5, 93.5, -16.1, 20.7, 53.4, 58.0, 52.0, 60.3, 50.2, 63.1, 48.8, 66.3, 44.2, 72.3, 43.3, 52.0, 41.9, 51.1, 41.0, 50.2, 34.1, 46.0, 5.5, 25.3, 44.2, 52.5, 1.4, 42.4, 38.2, 77.4, 58.9, 91.6, 60.3, 84.7, 48.8, 82.9, 24.9, 62.2, 41.9, 25.3, 30.4, 70.9, 24.9, 21.6, 34.1, 31.3, 16.6, 32.7, 45.1, 89.3, 17.0, 66.3, 24.9, 75.1, 21.2, 52.5, -5.5, 31.8, 11.1, 52.0, -13.4, 35.9, 26.7, 40.1, -15.2, -11.5, -22.1, -12.9, 80.6, 87.0, 103.1, 24.4, 76.9, 45.6, 74.1, 52.5, 82.0, 49.3, 84.3, 53.4, 77.8, 54.3, 80.1, 56.2, 89.3, 67.7, 119.3, 26.7, 94.8, 61.2, 107.7, 57.6, 84.7, 59.9, 83.3, 59.9, 76.0, 49.3, 80.1, 52.0, 82.4, 54.8, 83.8, 59.9, 82.4, 62.2, 82.4, 59.4, 78.3, 56.6, 76.0, 55.3, 72.3, 54.3, 70.4, 78.7, 71.4, 71.8, 71.8, 68.1, 71.8, 64.0, 70.9, 61.2, 77.4, 60.8, 78.7, 62.2, 80.1, 64.5, 81.0, 66.8, 93.0, 47.9, 121.1, 25.3, 79.7, 60.3, 81.0, 61.2, 80.6, 33.2, 87.9, 33.2, 99.0, 10.1, 108.2, 16.6, 84.7, 72.3, 132.1, 10.1, 125.7, 9.2, 119.3, 11.1, 109.1, 8.3, 128.9, 24.9, 92.5, 26.7, 115.1, 41.0, 100.4, 73.2, 95.3, 79.7, 127.5, 25.3, 107.7, 64.9, 78.7, 92.1, 96.2, 18.0, 83.3, 63.5, 123.4, 37.8, 66.3, 100.4, 81.5, 92.1, 87.9, 87.0, 89.3, 43.3, 80.1, 39.1, 93.0, 81.0, 86.1, 86.1, 69.1, 96.7, 101.3, 70.4, 75.1, 96.7, 121.1, 39.6, 75.1, 61.2, 76.0, 63.5, 76.9, 66.3, 77.4, 70.0, 78.3, 76.0, 82.0, 57.6, 83.8, 57.6, 85.2, 56.6, 95.3, 54.3, 117.9, 41.4, 80.1, 58.0, 111.4, 56.6, 79.7, 81.5, 70.9, 84.7, 93.5, 70.4, 96.2, 32.7, 86.6, 76.9, 110.0, 34.1, 100.4, 40.5, 110.5, 45.6, 70.9, 91.6, 95.3, 74.6, 87.5, 81.0, 99.9, 62.2, 117.4, 48.8, 104.5, 63.5, 114.6, 52.9, 101.8, 50.2, 131.7, 11.1, 125.7, 10.6]}, {"rect": [261, 446, 539, 724], "points": [0.35921, 0.05552, 0.09347, 0.0, -0.06341, 0.36036, -0.01938, 0.0, -0.11009, -0.01619, 0.36017, 0.0, -89.17497, -251.58791, -56.64056, 1.0, 70.0, 45.1, 73.7, 31.8, 69.5, 47.9, 68.1, 51.1, 67.2, 52.9, 65.4, 60.8, 65.4, 64.0, 64.9, 67.7, 64.0, 71.4, 62.2, 77.8, 33.6, 82.4, 37.8, 14.3, 62.2, 42.8, 61.2, 50.2, 52.9, 45.1, 46.0, 47.4, 53.9, 50.2, 48.3, 50.6, 32.7, 60.3, 14.3, 10.6, 29.5, 52.5, -17.5, 41.0, 37.3, 52.5, 39.1, 52.5, 61.7, 46.5, 53.4, 47.4, 47.0, 49.3, 38.2, 52.5, 41.0, 56.2, 40.1, 52.9, 48.8, 51.6, 54.3, 51.6, 60.8, 52.0, 52.9, 76.4, 55.7, 69.5, 56.6, 65.8, 58.0, 62.2, 58.9, 59.9, 47.9, 56.6, 46.5, 58.0, 44.7, 59.4, 42.8, 61.2, 41.0, 40.5, -23.0, 3.2, 43.7, 55.3, 42.4, 55.7, 65.4, 30.8, 53.9, 28.1, 45.6, 1.8, 33.2, 4.6, 37.8, 66.3, -4.1, -11.5, 9.2, -9.2, 18.4, -5.1, 32.7, -4.1, -5.1, 4.6, 49.7, 20.3, -21.6, 21.6, 3.2, 62.6, -0.9, 69.5, -16.1, 3.7, -6.0, 51.1, 30.8, 87.9, 47.4, 10.1, 39.6, 56.6, -5.5, 19.3, 41.0, 98.1, 19.8, 87.0, 10.6, 80.1, 54.3, 100.4, 72.3, 37.3, 49.3, 37.3, 63.5, 36.4, 12.4, 72.7, 21.2, 80.1, 42.4, 93.9, -10.1, 57.1, 56.6, 96.7, 29.9, 93.0, -16.1, 20.3, 52.9, 58.5, 51.6, 60.3, 50.2, 63.1, 48.3, 66.3, 44.2, 71.8, 43.3, 51.6, 41.9, 50.6, 41.0, 49.7, 34.1, 45.6, 6.0, 25.3, 44.2, 52.0, 1.4, 41.9, 38.2, 76.9, 58.5, 91.2, 60.3, 84.3, 48.8, 82.4, 25.3, 61.7, 42.4, 24.9, 30.4, 70.4, 24.9, 21.2, 34.1, 30.8, 16.6, 32.2, 45.1, 88.9, 17.5, 65.8, 25.3, 74.6, 21.6, 52.0, -5.5, 31.8, 11.1, 51.6, -13.4, 35.9, 27.2, 39.6, -14.7, -12.0, -21.6, -13.4, 80.1, 86.6, 102.7, 23.9, 76.4, 45.6, 73.7, 52.5, 81.5, 49.3, 83.8, 53.4, 77.8, 53.9, 80.1, 55.7, 89.3, 67.2, 119.3, 26.2, 94.4, 60.8, 107.7, 57.1, 84.3, 60.3, 82.9, 59.9, 75.5, 49.3, 79.7, 52.0, 82.0, 54.8, 83.3, 59.9, 82.0, 62.2, 82.0, 59.4, 78.3, 56.2, 76.0, 54.8, 72.3, 53.9, 70.0, 78.3, 70.9, 71.8, 71.4, 68.1, 71.4, 64.0, 70.9, 61.2, 77.4, 61.2, 78.7, 62.6, 79.7, 64.5, 80.6, 66.8, 93.0, 47.4, 121.1, 25.3, 79.2, 60.3, 80.6, 61.2, 80.6, 32.7, 87.5, 32.7, 99.0, 10.1, 108.2, 16.1, 84.3, 71.8, 132.1, 9.7, 125.7, 8.7, 119.3, 10.6, 108.7, 8.3, 128.9, 24.4, 92.1, 26.2, 114.6, 41.0, 100.4, 73.2, 95.3, 79.2, 127.5, 25.3, 107.3, 64.9, 78.3, 91.6, 96.2, 17.5, 82.9, 63.5, 123.4, 37.8, 65.8, 99.5, 81.0, 91.6, 87.5, 86.6, 88.9, 42.8, 80.1, 38.7, 92.5, 80.6, 85.2, 85.6, 68.6, 96.2, 101.3, 70.4, 74.6, 96.2, 121.1, 39.6, 74.6, 61.2, 75.5, 63.5, 76.4, 66.8, 76.9, 70.0, 77.8, 75.5, 81.5, 57.6, 83.3, 57.6, 84.7, 56.6, 94.8, 53.9, 117.9, 41.0, 79.7, 57.6, 111.0, 56.6, 79.2, 81.0, 70.4, 84.3, 93.0, 70.0, 96.2, 32.7, 86.6, 76.0, 110.0, 33.6, 100.4, 40.1, 110.5, 45.1, 70.4, 91.2, 94.8, 74.6, 87.0, 80.6, 99.5, 62.2, 117.4, 48.3, 104.1, 63.1, 114.6, 52.9, 101.8, 49.7, 131.7, 10.6, 125.7, 10.1]}, {"rect": [261, 445, 539, 723], "points": [0.35936, 0.05581, 0.09676, 0.0, -0.06309, 0.35965, -0.01583, 0.0, -0.11388, -0.01762, 0.36114, 0.0, -89.84633, -251.02088, -61.37071, 1.0, 70.4, 45.6, 74.1, 32.2, 70.0, 48.8, 68.6, 52.0, 67.7, 53.9, 65.8, 61.2, 65.8, 64.5, 65.4, 68.1, 64.5, 71.8, 62.2, 78.7, 33.6, 82.9, 37.8, 14.7, 62.6, 43.3, 61.7, 50.6, 53.4, 45.6, 46.5, 47.9, 54.3, 50.6, 48.8, 51.1, 32.7, 60.8, 14.7, 11.1, 29.5, 52.9, -18.0, 41.0, 37.8, 52.5, 39.6, 52.9, 62.2, 47.4, 53.9, 48.3, 47.9, 49.7, 38.7, 52.9, 41.4, 56.2, 40.5, 52.9, 49.3, 52.5, 54.8, 52.5, 61.2, 52.9, 52.9, 77.4, 56.2, 70.0, 57.1, 66.3, 58.5, 62.6, 59.4, 59.9, 48.3, 57.1, 47.0, 58.0, 45.1, 59.4, 43.3, 61.2, 41.0, 41.0, -23.5, 3.7, 44.7, 55.3, 43.3, 55.7, 65.8, 31.3, 53.9, 28.5, 46.0, 2.3, 33.2, 5.1, 37.8, 66.8, -4.1, -11.1, 9.2, -8.7, 18.9, -4.6, 33.2, -3.7, -5.1, 5.1, 49.7, 20.7, -22.1, 21.6, 3.2, 62.6, -0.9, 70.0, -16.6, 4.1, -6.0, 51.6, 30.8, 88.9, 47.4, 10.6, 40.1, 57.1, -6.0, 19.3, 41.0, 98.5, 19.8, 87.5, 10.6, 80.6, 54.3, 101.3, 72.7, 37.8, 49.3, 37.8, 64.0, 37.3, 12.4, 73.2, 21.2, 81.0, 42.8, 94.8, -10.6, 57.6, 56.6, 97.6, 29.9, 93.9, -16.6, 20.7, 53.4, 58.5, 52.0, 60.3, 50.6, 63.1, 48.8, 66.3, 44.2, 72.7, 43.7, 52.0, 42.4, 51.1, 41.4, 50.2, 34.5, 46.0, 6.0, 25.3, 44.7, 52.5, 1.4, 42.4, 38.2, 77.8, 58.9, 92.1, 60.8, 85.2, 49.3, 82.9, 25.3, 62.6, 42.4, 25.3, 30.8, 70.9, 25.3, 22.1, 34.5, 31.3, 17.0, 32.7, 45.6, 89.8, 17.5, 66.3, 25.3, 75.1, 21.6, 52.5, -5.5, 31.8, 11.1, 52.0, -13.8, 35.9, 27.2, 40.1, -15.2, -11.5, -22.1, -12.9, 80.6, 87.5, 103.1, 24.9, 77.4, 45.6, 74.1, 52.9, 82.4, 49.3, 84.7, 53.4, 78.3, 54.3, 80.6, 56.2, 89.8, 67.7, 119.3, 26.7, 94.8, 61.2, 107.3, 57.1, 85.2, 59.9, 83.3, 59.4, 76.0, 49.7, 80.1, 52.0, 82.9, 54.8, 84.3, 59.9, 82.4, 62.2, 82.4, 59.4, 78.7, 56.6, 76.4, 55.7, 72.7, 54.8, 70.4, 79.2, 71.8, 71.8, 72.3, 68.1, 71.8, 64.5, 71.4, 61.7, 77.8, 60.8, 79.2, 62.6, 80.6, 64.5, 81.5, 66.3, 93.5, 47.9, 120.6, 25.3, 79.7, 60.3, 81.0, 61.2, 81.0, 33.6, 87.9, 33.2, 99.5, 10.6, 108.7, 16.6, 84.7, 72.3, 132.1, 10.1, 125.7, 9.2, 119.3, 11.1, 109.1, 8.3, 128.9, 24.9, 92.5, 26.7, 114.6, 41.0, 100.4, 73.7, 95.3, 79.7, 127.1, 25.3, 107.7, 65.4, 78.7, 92.5, 96.7, 18.0, 83.3, 63.1, 123.4, 37.8, 66.3, 100.4, 81.5, 92.1, 87.9, 87.0, 89.3, 43.3, 80.6, 39.6, 93.0, 81.0, 85.6, 86.6, 69.5, 97.2, 101.3, 70.4, 75.1, 96.7, 121.1, 40.1, 75.1, 61.7, 76.4, 63.5, 76.9, 66.8, 77.4, 70.0, 78.3, 76.4, 82.0, 57.6, 83.8, 57.1, 85.6, 56.6, 95.3, 54.3, 117.9, 41.4, 80.6, 57.6, 111.4, 56.6, 79.7, 81.5, 70.9, 85.2, 93.5, 70.4, 96.7, 33.2, 87.0, 76.9, 110.0, 34.1, 100.8, 40.5, 110.5, 45.6, 70.9, 92.1, 95.3, 75.1, 87.5, 81.0, 99.9, 62.6, 117.4, 48.8, 104.5, 63.5, 114.6, 52.9, 102.2, 50.2, 131.2, 11.1, 125.2, 10.1]}, {"rect": [262, 445, 540, 723], "points": [0.35836, 0.05624, 0.09511, 0.0, -0.06326, 0.3599, -0.01931, 0.0, -0.11237, -0.01593, 0.36007, 0.0, -89.16118, -251.23805, -58.13091, 1.0, 70.5, 45.5, 73.8, 32.0, 70.0, 48.4, 68.6, 51.6, 67.7, 53.8, 65.9, 60.9, 65.9, 64.1, 65.4, 67.8, 64.5, 71.5, 62.1, 78.3, 33.6, 82.8, 37.7, 14.6, 62.7, 43.2, 61.4, 50.6, 53.1, 45.2, 46.5, 47.8, 54.4, 50.6, 48.5, 51.1, 32.9, 60.7, 14.6, 10.9, 29.6, 52.8, -17.7, 41.2, 37.7, 52.5, 39.3, 52.9, 62.2, 47.0, 53.9, 47.9, 47.5, 49.4, 38.6, 52.9, 41.4, 56.1, 40.2, 53.0, 49.3, 52.1, 54.8, 52.1, 61.2, 52.5, 52.9, 76.9, 56.1, 69.9, 57.5, 66.3, 58.5, 62.6, 59.4, 59.9, 48.3, 57.0, 47.0, 58.0, 45.1, 59.4, 43.3, 61.3, 41.3, 40.9, -23.1, 3.6, 44.3, 55.3, 42.9, 55.7, 65.5, 30.8, 53.9, 28.5, 45.7, 2.1, 33.2, 5.0, 37.6, 66.7, -3.9, -10.9, 9.6, -8.8, 18.8, -4.7, 33.2, -3.8, -4.8, 4.9, 49.7, 20.5, -21.8, 21.6, 3.4, 62.5, -0.7, 69.8, -16.2, 4.1, -5.7, 51.4, 30.7, 88.3, 47.4, 10.5, 39.7, 57.0, -5.4, 19.6, 40.9, 98.4, 19.7, 87.3, 10.5, 80.4, 54.3, 100.8, 72.4, 37.6, 49.3, 37.7, 63.6, 36.8, 12.4, 73.0, 21.1, 80.6, 42.7, 94.7, -10.3, 57.4, 56.6, 97.1, 29.8, 93.4, -15.9, 20.6, 53.4, 58.5, 52.0, 60.3, 50.6, 63.1, 48.8, 66.3, 44.1, 72.3, 43.4, 52.0, 42.3, 51.0, 41.1, 50.1, 34.4, 46.0, 6.2, 25.3, 44.6, 52.4, 1.6, 42.2, 38.5, 77.3, 58.5, 91.6, 60.4, 84.7, 48.8, 82.8, 25.2, 62.1, 42.3, 25.2, 30.7, 70.8, 25.3, 21.9, 34.4, 31.2, 17.0, 32.5, 45.2, 89.3, 17.4, 66.2, 25.2, 74.9, 21.8, 52.4, -5.3, 32.0, 11.3, 52.0, -13.5, 36.1, 27.4, 39.9, -14.8, -11.7, -21.8, -13.0, 80.2, 87.3, 102.8, 24.7, 77.0, 45.6, 74.2, 52.8, 82.3, 49.3, 84.6, 53.1, 78.2, 54.3, 80.5, 55.8, 89.1, 67.7, 119.0, 26.9, 94.5, 61.2, 107.3, 57.5, 84.7, 59.9, 83.3, 59.5, 76.0, 49.4, 80.2, 52.0, 82.8, 54.5, 84.2, 59.9, 82.4, 62.2, 82.4, 59.4, 78.7, 56.6, 76.4, 55.3, 72.8, 54.4, 70.0, 78.8, 71.5, 71.8, 72.0, 68.1, 71.9, 64.4, 71.3, 61.4, 77.8, 60.8, 79.1, 62.3, 80.2, 64.5, 81.1, 66.7, 93.0, 48.1, 120.6, 25.7, 79.6, 60.3, 81.0, 61.3, 80.4, 33.1, 87.6, 33.1, 99.1, 10.5, 108.3, 16.8, 84.3, 72.3, 131.8, 10.4, 125.6, 9.1, 119.5, 11.3, 108.9, 8.6, 128.6, 25.1, 92.2, 26.6, 114.3, 41.3, 100.1, 73.6, 94.9, 79.9, 127.1, 25.7, 107.3, 65.3, 78.4, 92.4, 96.3, 17.9, 83.3, 63.2, 123.0, 38.1, 65.9, 100.2, 81.1, 92.0, 87.5, 86.9, 89.0, 43.2, 80.2, 39.4, 92.6, 80.9, 85.3, 86.4, 69.1, 97.0, 100.9, 70.7, 74.6, 96.6, 120.8, 40.0, 75.0, 61.3, 76.1, 63.6, 76.9, 66.4, 77.3, 70.0, 78.0, 76.3, 81.9, 57.6, 83.8, 57.2, 85.3, 56.6, 94.9, 54.2, 117.5, 41.4, 80.2, 57.6, 110.7, 56.9, 79.3, 81.5, 70.5, 85.0, 93.1, 70.4, 96.0, 33.0, 86.6, 76.8, 109.8, 34.3, 100.1, 40.8, 110.1, 45.8, 70.5, 91.6, 94.9, 74.9, 87.1, 81.0, 99.2, 62.5, 117.1, 49.0, 104.1, 63.8, 114.3, 53.3, 101.5, 50.1, 131.3, 11.4, 125.2, 10.5]}, {"rect": [263, 444, 541, 722], "points": [0.35809, 0.0566, 0.09548, 0.0, -0.06317, 0.35995, -0.02051, 0.0, -0.11347, -0.0159, 0.36021, 0.0, -89.3916, -251.35741, -57.68475, 1.0, 70.5, 45.7, 74.0, 32.1, 70.0, 48.8, 68.7, 52.0, 67.7, 53.9, 65.9, 61.3, 65.9, 64.5, 65.4, 68.4, 64.2, 72.1, 62.0, 78.7, 33.4, 82.9, 37.5, 14.9, 62.7, 43.5, 61.6, 51.1, 53.3, 45.6, 46.4, 48.0, 54.4, 50.8, 48.7, 51.5, 32.6, 61.1, 14.2, 11.2, 29.1, 53.0, -18.2, 41.3, 37.6, 53.0, 39.4, 53.1, 62.2, 47.5, 53.9, 48.4, 47.4, 49.8, 38.6, 53.0, 41.3, 56.3, 40.3, 53.4, 49.2, 52.5, 54.8, 52.5, 61.2, 52.9, 52.7, 77.3, 55.9, 70.0, 57.3, 66.6, 58.5, 63.0, 59.4, 60.3, 48.3, 57.2, 46.9, 58.2, 45.1, 59.8, 43.3, 61.7, 40.9, 41.3, -23.6, 3.9, 44.2, 55.7, 42.8, 55.9, 65.6, 31.1, 53.8, 28.8, 45.6, 2.2, 32.9, 5.3, 37.2, 67.1, -4.3, -10.8, 9.2, -8.5, 18.4, -4.4, 33.0, -3.5, -5.2, 4.9, 49.6, 20.6, -22.3, 21.9, 2.9, 62.9, -1.2, 69.9, -16.7, 4.4, -6.2, 51.5, 30.4, 88.4, 47.1, 10.8, 39.6, 57.2, -6.1, 19.7, 40.5, 98.5, 19.4, 87.4, 10.2, 80.5, 54.2, 100.9, 72.6, 37.7, 49.1, 38.0, 63.5, 37.1, 12.1, 73.1, 20.7, 80.9, 42.3, 94.8, -10.8, 57.6, 56.5, 97.5, 29.5, 93.5, -16.4, 20.6, 53.4, 58.9, 52.0, 60.8, 50.3, 63.5, 48.9, 66.7, 44.0, 72.7, 43.6, 52.1, 42.3, 51.2, 41.3, 50.3, 34.1, 46.3, 5.8, 25.6, 44.6, 52.6, 1.2, 42.3, 38.1, 77.7, 58.4, 92.0, 60.2, 85.1, 48.7, 83.2, 24.8, 62.5, 42.0, 25.5, 30.3, 70.9, 25.0, 22.0, 34.2, 31.5, 16.7, 32.6, 45.0, 89.7, 17.0, 66.6, 24.9, 75.0, 21.3, 52.8, -5.8, 32.1, 10.7, 52.3, -14.0, 36.3, 26.8, 40.0, -15.3, -11.6, -22.3, -12.9, 80.1, 87.4, 102.7, 24.8, 77.0, 45.8, 74.2, 53.0, 82.1, 49.7, 84.4, 53.5, 78.0, 54.5, 80.3, 56.2, 89.2, 68.1, 119.1, 27.1, 94.3, 61.6, 106.7, 57.9, 84.5, 60.3, 83.0, 59.9, 76.0, 49.8, 80.2, 52.5, 82.6, 54.8, 83.9, 60.2, 82.1, 62.6, 82.1, 59.8, 78.4, 57.0, 76.1, 55.7, 72.8, 54.8, 69.9, 79.2, 71.5, 72.2, 72.0, 68.5, 71.9, 64.8, 71.1, 61.8, 77.5, 61.3, 78.9, 62.7, 80.2, 64.9, 81.1, 66.9, 92.9, 48.3, 120.1, 26.1, 79.4, 60.7, 80.7, 61.7, 80.5, 33.4, 87.5, 33.5, 99.0, 10.8, 108.2, 16.9, 84.2, 72.7, 131.4, 10.8, 125.4, 9.5, 119.1, 11.6, 108.5, 8.9, 128.5, 25.2, 92.2, 27.0, 114.0, 41.7, 100.0, 73.9, 94.6, 80.0, 126.8, 26.1, 107.0, 65.7, 78.2, 92.5, 96.2, 18.2, 83.0, 63.6, 122.7, 38.5, 65.8, 100.4, 80.8, 92.1, 87.2, 87.0, 88.9, 43.6, 80.1, 39.5, 92.2, 81.0, 85.2, 86.5, 69.0, 97.1, 100.3, 70.9, 74.3, 96.7, 120.5, 40.4, 74.8, 61.7, 76.1, 64.0, 76.9, 66.8, 77.1, 70.4, 78.1, 76.5, 81.7, 58.0, 83.5, 57.6, 85.3, 57.0, 94.8, 54.4, 117.4, 41.7, 80.1, 58.0, 110.6, 57.0, 79.2, 81.8, 70.4, 85.2, 93.0, 70.5, 96.2, 33.4, 86.5, 76.9, 109.9, 34.4, 100.2, 40.9, 110.0, 46.0, 70.4, 92.0, 94.8, 75.0, 87.0, 81.4, 99.3, 62.7, 117.0, 49.2, 103.7, 63.9, 114.0, 53.7, 101.6, 50.5, 131.0, 11.8, 124.7, 10.9]}, {"rect": [264, 444, 542, 722], "points": [0.35719, 0.057, 0.09441, 0.0, -0.06284, 0.36006, -0.02114, 0.0, -0.11302, -0.01575, 0.35962, 0.0, -89.1837, -251.7836, -56.47072, 1.0, 70.7, 45.6, 73.7, 31.3, 70.2, 48.5, 68.9, 51.8, 67.9, 53.7, 66.2, 61.5, 66.1, 64.4, 65.6, 67.9, 64.7, 71.6, 61.4, 78.5, 32.9, 82.6, 37.6, 14.1, 62.9, 43.7, 61.6, 50.8, 53.3, 45.6, 46.1, 47.9, 54.6, 50.8, 48.4, 51.3, 32.0, 60.9, 14.6, 10.4, 28.7, 52.7, -18.0, 40.7, 37.4, 52.9, 39.1, 53.3, 62.4, 47.5, 53.8, 48.4, 47.4, 49.7, 38.3, 53.0, 41.1, 56.5, 40.0, 53.4, 49.2, 52.2, 54.8, 52.2, 61.1, 52.7, 52.1, 77.0, 56.4, 69.7, 57.7, 66.3, 58.7, 62.7, 59.6, 60.3, 48.0, 57.4, 46.9, 58.4, 45.0, 59.8, 43.2, 61.7, 40.6, 40.8, -23.4, 3.3, 44.1, 55.6, 42.7, 56.0, 65.1, 30.3, 53.5, 28.0, 45.5, 1.6, 33.3, 4.5, 36.6, 66.9, -4.2, -11.4, 10.0, -9.1, 19.3, -4.9, 33.6, -4.3, -4.8, 4.3, 49.3, 20.0, -22.1, 21.4, 2.8, 62.1, -1.4, 69.3, -16.3, 3.8, -6.1, 50.9, 30.0, 88.1, 47.3, 10.0, 39.6, 57.1, -5.7, 19.0, 40.2, 98.2, 19.4, 86.8, 10.1, 79.9, 53.9, 100.6, 72.2, 36.9, 48.8, 37.3, 63.1, 36.3, 12.0, 72.5, 20.4, 80.3, 42.0, 94.2, -10.7, 57.2, 56.2, 97.0, 29.1, 93.2, -16.2, 20.0, 53.4, 58.9, 52.0, 60.7, 50.5, 63.2, 49.1, 66.4, 43.4, 72.4, 43.3, 52.1, 42.0, 51.2, 41.0, 50.2, 33.7, 45.8, 5.9, 25.0, 44.3, 52.6, 1.3, 41.7, 37.5, 77.2, 58.0, 91.5, 59.9, 84.6, 48.4, 82.7, 24.4, 61.9, 41.9, 24.7, 30.0, 70.6, 25.2, 21.4, 34.1, 30.8, 16.9, 32.0, 44.7, 89.2, 16.7, 66.0, 24.5, 74.5, 21.2, 52.3, -5.6, 31.5, 10.6, 51.8, -13.8, 35.7, 26.7, 39.4, -14.9, -12.0, -22.1, -13.3, 79.9, 86.9, 102.6, 24.3, 77.2, 46.0, 74.4, 52.8, 82.3, 49.7, 84.6, 53.4, 78.2, 54.5, 80.5, 55.9, 88.8, 67.9, 118.7, 26.5, 94.2, 61.4, 107.3, 57.4, 84.6, 60.3, 82.9, 59.8, 76.2, 49.8, 80.4, 52.2, 82.8, 54.8, 83.8, 59.9, 82.3, 62.6, 82.3, 59.5, 78.6, 56.5, 76.3, 55.4, 73.0, 54.6, 69.5, 79.0, 72.0, 71.6, 72.4, 68.2, 72.1, 64.6, 71.2, 62.0, 77.7, 61.2, 79.1, 62.6, 80.4, 64.9, 81.3, 66.8, 92.5, 47.7, 120.6, 25.6, 79.5, 60.7, 80.9, 61.6, 80.4, 32.6, 87.7, 33.0, 98.9, 10.0, 107.8, 16.4, 83.8, 72.5, 131.5, 10.1, 124.3, 8.7, 118.3, 10.6, 107.7, 7.9, 128.3, 24.7, 92.3, 26.5, 114.6, 41.3, 100.1, 73.2, 94.9, 79.5, 127.1, 25.6, 107.3, 65.2, 78.1, 92.0, 96.1, 17.5, 83.2, 63.5, 122.8, 37.8, 65.7, 100.1, 81.1, 91.5, 87.2, 86.5, 88.8, 43.1, 80.0, 39.0, 92.3, 80.6, 85.4, 86.0, 68.6, 96.6, 100.8, 70.4, 74.4, 96.4, 121.0, 39.9, 74.9, 61.7, 76.3, 64.0, 77.1, 66.8, 77.5, 70.1, 77.8, 76.2, 81.8, 57.7, 83.7, 57.5, 85.5, 56.8, 94.4, 54.1, 117.3, 41.0, 80.1, 57.7, 110.7, 56.6, 79.1, 81.4, 70.0, 84.9, 92.8, 70.3, 96.0, 32.6, 86.1, 76.7, 109.5, 33.9, 99.9, 40.4, 109.9, 45.5, 70.3, 91.5, 94.7, 74.5, 86.9, 80.9, 99.0, 62.4, 117.1, 48.7, 103.8, 63.4, 114.6, 53.2, 101.2, 50.1, 131.3, 11.3, 125.2, 10.7]}, {"rect": [265, 444, 543, 722], "points": [0.35647, 0.05781, 0.09408, 0.0, -0.06289, 0.36117, -0.02152, 0.0, -0.11287, -0.01619, 0.35912, 0.0, -88.88326, -253.07786, -55.92169, 1.0, 70.4, 45.6, 73.3, 31.4, 69.9, 48.7, 68.6, 52.0, 67.6, 54.2, 66.1, 61.3, 66.1, 64.2, 65.3, 67.8, 64.4, 71.5, 61.3, 78.7, 32.8, 82.5, 37.6, 14.1, 62.7, 43.6, 61.3, 51.0, 53.0, 45.6, 46.0, 47.9, 54.3, 51.0, 48.3, 51.5, 31.8, 60.9, 14.5, 10.3, 28.5, 52.6, -18.1, 40.6, 37.3, 52.9, 38.8, 53.0, 62.1, 47.4, 53.8, 48.4, 47.1, 49.7, 38.2, 53.0, 41.0, 56.3, 39.7, 53.4, 48.9, 52.4, 54.7, 52.4, 60.8, 52.9, 51.7, 77.0, 56.1, 69.6, 57.5, 66.1, 58.4, 62.7, 59.4, 60.0, 47.9, 57.2, 46.5, 58.1, 44.7, 59.6, 43.1, 61.7, 40.5, 40.7, -23.0, 3.0, 43.8, 55.4, 42.4, 55.8, 64.9, 30.5, 53.4, 28.2, 45.4, 1.5, 33.0, 4.4, 36.5, 66.9, -4.0, -11.8, 9.5, -9.5, 18.7, -5.3, 33.0, -4.5, -4.8, 4.0, 49.3, 20.0, -22.0, 21.3, 2.7, 62.2, -1.4, 69.2, -16.4, 3.4, -6.4, 50.8, 29.9, 88.0, 47.0, 9.8, 39.5, 57.1, -5.7, 18.7, 40.0, 98.1, 19.3, 86.8, 10.1, 79.8, 53.5, 100.8, 71.9, 37.3, 48.5, 37.5, 62.8, 36.5, 11.9, 72.4, 20.3, 80.3, 41.6, 94.4, -10.7, 57.2, 55.8, 97.1, 29.0, 93.1, -16.3, 19.9, 53.3, 58.6, 51.9, 60.5, 50.2, 63.2, 48.8, 66.4, 43.0, 72.4, 43.2, 52.3, 41.9, 51.4, 40.6, 50.2, 33.6, 45.8, 5.8, 24.7, 44.1, 52.8, 1.2, 41.6, 37.4, 77.4, 57.7, 91.6, 59.5, 84.8, 48.0, 82.9, 24.1, 61.9, 41.8, 24.7, 29.6, 70.5, 24.9, 21.0, 34.0, 30.9, 16.6, 31.9, 44.3, 89.3, 16.6, 66.0, 24.4, 74.6, 20.8, 52.2, -5.7, 31.4, 10.5, 51.7, -13.7, 35.6, 26.6, 39.4, -14.7, -12.6, -21.7, -13.7, 79.3, 87.3, 102.2, 24.4, 77.2, 45.9, 74.1, 53.2, 82.2, 49.7, 84.5, 53.4, 78.1, 54.7, 80.4, 56.1, 88.5, 68.1, 118.4, 26.7, 93.6, 61.6, 106.5, 57.8, 84.5, 60.2, 83.0, 59.8, 75.9, 49.7, 80.3, 52.4, 82.7, 54.8, 83.9, 59.9, 82.2, 62.5, 82.2, 59.7, 78.5, 56.9, 76.2, 55.7, 72.7, 54.8, 69.2, 79.2, 71.6, 71.8, 72.1, 68.2, 72.1, 64.6, 71.2, 61.8, 77.6, 61.2, 79.0, 62.6, 80.3, 64.8, 80.9, 67.0, 92.2, 47.9, 119.8, 26.0, 79.4, 60.4, 80.8, 61.3, 79.8, 32.8, 87.1, 33.2, 98.5, 10.1, 107.7, 16.5, 83.4, 72.7, 131.1, 10.4, 124.4, 9.1, 118.3, 10.9, 107.7, 8.2, 127.9, 25.1, 91.8, 26.7, 113.8, 41.6, 99.5, 73.9, 94.1, 79.9, 126.3, 26.0, 106.5, 65.6, 77.5, 92.4, 95.8, 17.8, 83.1, 63.5, 122.4, 38.4, 65.1, 100.3, 80.3, 91.9, 86.6, 86.9, 88.4, 43.3, 79.7, 39.2, 91.7, 81.2, 84.8, 86.4, 68.2, 97.0, 100.0, 71.1, 73.8, 96.6, 120.3, 40.3, 74.8, 61.7, 76.2, 64.0, 76.8, 66.7, 77.2, 70.3, 77.4, 76.4, 81.7, 57.9, 83.6, 57.5, 85.4, 57.0, 94.0, 54.3, 116.9, 41.6, 80.0, 57.9, 110.1, 57.0, 78.5, 81.8, 69.6, 85.1, 92.2, 70.7, 95.5, 32.8, 85.7, 76.9, 109.1, 34.1, 99.5, 40.8, 109.3, 45.9, 69.7, 91.9, 94.1, 74.9, 86.6, 81.3, 98.6, 62.6, 116.5, 49.1, 103.2, 63.9, 113.8, 53.7, 100.8, 50.5, 130.7, 11.7, 124.3, 10.8]}, {"rect": [265, 444, 543, 722], "points": [0.35639, 0.05752, 0.09546, 0.0, -0.06237, 0.36192, -0.02014, 0.0, -0.11343, -0.01749, 0.35944, 0.0, -89.22888, -253.75725, -57.82338, 1.0, 70.7, 45.8, 73.9, 31.5, 70.2, 48.7, 69.2, 52.2, 67.9, 54.2, 66.4, 61.3, 66.1, 64.4, 65.6, 68.1, 64.7, 71.7, 61.6, 79.0, 33.2, 82.5, 37.7, 14.3, 63.2, 43.6, 61.9, 51.0, 53.3, 45.5, 46.4, 47.9, 54.7, 51.0, 48.7, 51.5, 32.0, 60.9, 14.7, 10.3, 28.7, 52.9, -18.0, 40.6, 37.4, 53.0, 39.2, 53.0, 62.4, 47.6, 54.1, 48.6, 47.7, 49.7, 38.3, 53.0, 41.3, 56.5, 40.1, 53.4, 49.2, 52.5, 55.1, 52.5, 61.1, 53.2, 52.1, 77.2, 56.4, 69.9, 57.7, 66.3, 58.8, 62.9, 59.7, 60.2, 48.2, 57.2, 46.9, 58.4, 45.0, 59.8, 43.2, 61.7, 40.6, 41.0, -23.3, 2.9, 44.2, 55.6, 42.8, 55.8, 65.3, 30.6, 53.8, 28.2, 45.5, 1.5, 33.2, 4.6, 36.9, 67.1, -4.1, -11.9, 9.6, -9.7, 18.8, -5.2, 33.0, -4.6, -4.7, 4.1, 49.6, 20.0, -22.1, 21.2, 2.9, 62.3, -1.3, 69.2, -16.5, 3.3, -6.1, 50.8, 30.1, 88.0, 47.3, 9.8, 39.6, 57.1, -5.6, 18.9, 40.2, 98.1, 19.5, 87.0, 10.2, 79.8, 53.9, 100.8, 72.2, 37.3, 48.8, 37.8, 63.4, 36.6, 12.1, 72.4, 20.7, 80.3, 42.0, 94.4, -10.6, 57.1, 56.2, 97.2, 29.2, 93.1, -16.2, 19.9, 53.7, 58.8, 52.3, 60.7, 50.5, 63.4, 49.1, 66.4, 43.4, 72.7, 43.3, 52.1, 42.2, 51.2, 41.0, 50.2, 34.0, 46.1, 6.0, 24.9, 44.3, 52.9, 1.4, 41.9, 37.8, 77.4, 58.1, 91.7, 59.9, 85.0, 48.4, 82.9, 24.5, 62.1, 41.9, 24.9, 30.0, 70.6, 25.2, 21.2, 34.1, 31.0, 16.9, 31.9, 44.7, 89.4, 16.7, 66.0, 24.6, 74.7, 21.2, 52.5, -5.5, 31.4, 10.7, 51.7, -13.8, 35.5, 26.8, 39.6, -15.0, -12.5, -22.0, -13.8, 79.6, 87.2, 102.5, 24.4, 77.5, 45.9, 74.4, 53.3, 82.3, 49.6, 84.6, 53.3, 78.1, 54.7, 80.4, 56.1, 88.7, 68.1, 118.6, 26.4, 93.9, 61.4, 106.8, 57.4, 84.6, 60.0, 82.9, 59.5, 76.2, 49.9, 80.4, 52.4, 82.7, 54.8, 83.8, 59.9, 82.0, 62.3, 82.3, 59.5, 78.6, 56.7, 76.3, 55.7, 73.0, 55.0, 69.5, 79.4, 71.7, 71.8, 72.2, 68.2, 72.1, 64.8, 71.2, 62.0, 77.7, 61.2, 79.0, 62.6, 80.1, 64.6, 81.0, 66.8, 92.4, 48.0, 120.0, 25.5, 79.5, 60.4, 80.9, 61.3, 80.3, 32.8, 87.7, 33.2, 98.8, 9.8, 107.9, 16.3, 83.7, 72.7, 131.4, 10.2, 124.9, 8.8, 118.8, 10.6, 108.3, 7.9, 128.0, 24.7, 92.3, 26.5, 114.1, 41.1, 99.8, 73.5, 94.4, 79.5, 126.5, 25.5, 106.8, 65.2, 78.0, 92.2, 96.0, 17.6, 83.2, 63.5, 122.4, 37.9, 65.7, 100.0, 80.8, 91.8, 86.9, 86.7, 88.7, 43.4, 80.0, 39.2, 92.0, 80.8, 85.1, 86.2, 68.5, 96.8, 100.3, 70.7, 74.1, 96.4, 120.6, 39.9, 74.9, 61.6, 76.3, 63.9, 77.1, 66.7, 77.2, 70.1, 77.7, 76.7, 81.8, 57.6, 83.6, 57.2, 85.2, 56.7, 94.3, 54.4, 116.9, 41.2, 80.1, 57.9, 110.4, 56.8, 79.0, 81.6, 70.0, 85.2, 92.5, 70.5, 96.0, 32.8, 86.0, 76.9, 109.4, 34.1, 99.8, 40.6, 109.5, 45.7, 70.3, 91.8, 94.3, 74.8, 86.9, 81.2, 98.9, 62.6, 116.8, 48.9, 103.5, 63.7, 114.1, 53.2, 100.8, 50.3, 130.7, 11.2, 124.3, 10.3]}, {"rect": [265, 444, 543, 722], "points": [0.35557, 0.05741, 0.09563, 0.0, -0.06166, 0.36283, -0.01897, 0.0, -0.11272, -0.01883, 0.35878, 0.0, -89.17078, -254.5917, -58.65273, 1.0, 70.5, 45.3, 73.7, 32.0, 70.0, 48.5, 68.8, 51.8, 67.7, 54.0, 66.0, 61.3, 65.9, 64.2, 65.4, 68.2, 64.5, 71.6, 61.8, 78.8, 33.6, 82.8, 37.9, 14.6, 63.0, 43.2, 61.7, 50.8, 53.4, 45.3, 46.5, 47.9, 54.7, 50.8, 48.8, 51.3, 32.6, 61.2, 14.9, 10.5, 29.1, 52.9, -17.8, 40.6, 38.0, 53.0, 39.5, 53.1, 62.2, 47.2, 53.9, 48.4, 47.8, 49.8, 38.9, 53.0, 41.4, 56.3, 40.4, 53.2, 49.5, 52.5, 54.9, 52.5, 61.2, 53.0, 52.5, 77.0, 56.2, 69.7, 57.3, 66.3, 58.6, 62.7, 59.5, 60.0, 48.3, 57.2, 47.0, 58.2, 45.1, 59.9, 43.3, 61.8, 41.0, 41.3, -23.0, 2.8, 44.5, 55.4, 43.1, 55.8, 65.4, 31.1, 53.9, 28.5, 45.6, 1.8, 33.3, 4.6, 37.3, 66.9, -4.0, -11.9, 9.4, -9.9, 18.5, -5.4, 32.8, -4.6, -4.6, 4.2, 49.7, 20.3, -22.0, 21.2, 3.3, 62.5, -0.9, 69.5, -16.1, 3.3, -5.9, 51.1, 30.8, 88.3, 47.4, 10.1, 40.0, 57.2, -5.5, 18.9, 40.9, 98.2, 20.1, 87.1, 10.6, 80.1, 54.2, 100.6, 72.3, 37.6, 49.2, 38.1, 63.5, 37.1, 12.5, 72.7, 21.2, 80.5, 42.6, 94.5, -10.5, 57.2, 56.5, 97.2, 29.9, 93.1, -16.0, 19.9, 53.5, 58.6, 52.1, 60.5, 50.3, 63.2, 48.9, 66.4, 44.0, 72.7, 43.7, 52.2, 42.3, 51.2, 41.3, 50.2, 34.2, 46.4, 6.1, 24.9, 44.6, 52.7, 1.5, 42.0, 38.2, 77.4, 58.5, 91.7, 60.2, 84.9, 48.8, 83.0, 24.9, 62.2, 42.3, 25.2, 30.4, 70.8, 25.3, 21.5, 34.2, 31.3, 17.1, 32.2, 45.1, 89.4, 17.4, 66.2, 25.3, 75.0, 21.6, 52.5, -5.4, 31.4, 11.1, 52.0, -13.6, 35.6, 27.2, 39.9, -14.7, -12.7, -21.7, -14.1, 79.7, 87.4, 102.2, 24.7, 77.3, 45.4, 74.2, 53.1, 82.4, 49.4, 84.3, 53.1, 77.9, 54.5, 80.2, 56.2, 88.8, 68.1, 118.4, 26.6, 93.9, 61.6, 106.9, 57.8, 84.6, 60.0, 82.9, 59.5, 76.0, 49.5, 80.2, 52.2, 82.5, 54.8, 83.8, 59.9, 82.0, 62.3, 82.3, 59.5, 78.4, 56.7, 76.1, 55.7, 72.8, 54.8, 69.9, 79.2, 71.5, 71.6, 72.0, 68.2, 71.9, 64.6, 71.0, 61.8, 77.4, 61.0, 78.8, 62.6, 80.1, 64.6, 81.0, 66.6, 92.5, 48.3, 119.9, 25.6, 79.3, 60.4, 80.7, 61.3, 80.1, 33.1, 87.5, 33.4, 98.5, 10.0, 107.7, 16.5, 83.8, 72.7, 131.0, 10.1, 124.8, 8.7, 118.5, 10.6, 107.9, 7.8, 128.0, 25.1, 92.1, 26.9, 113.9, 41.3, 99.6, 74.0, 94.5, 80.0, 126.3, 25.6, 106.8, 65.7, 77.9, 92.5, 95.8, 17.9, 83.0, 63.3, 122.5, 38.1, 65.8, 100.0, 80.7, 92.0, 86.7, 87.0, 88.8, 43.6, 80.0, 39.5, 92.0, 81.3, 85.1, 86.5, 68.6, 96.8, 100.4, 71.1, 74.1, 96.6, 120.6, 40.3, 74.8, 61.4, 76.0, 63.7, 76.9, 66.5, 77.0, 70.1, 77.8, 76.5, 81.6, 57.6, 83.4, 57.2, 85.2, 56.7, 94.3, 54.6, 117.0, 41.6, 80.1, 57.7, 110.5, 57.3, 79.1, 81.9, 70.4, 85.2, 92.5, 70.8, 95.7, 33.0, 86.0, 77.2, 109.1, 34.3, 99.8, 40.9, 109.6, 45.9, 70.4, 92.0, 94.4, 75.3, 86.9, 81.4, 98.9, 62.9, 116.6, 49.2, 103.5, 63.9, 114.2, 53.6, 100.9, 50.5, 130.5, 11.3, 124.2, 10.4]}, {"rect": [265, 444, 543, 722], "points": [0.35525, 0.05682, 0.09635, 0.0, -0.06109, 0.36352, -0.01613, 0.0, -0.11194, -0.01999, 0.35856, 0.0, -89.24106, -254.97871, -60.90272, 1.0, 70.7, 45.3, 73.7, 32.2, 69.9, 48.5, 68.9, 52.1, 67.7, 54.0, 66.2, 61.3, 65.9, 64.5, 65.4, 68.3, 64.5, 71.9, 62.1, 78.8, 34.0, 82.9, 38.2, 14.7, 63.0, 43.4, 61.7, 51.1, 53.4, 45.6, 46.6, 48.0, 54.8, 51.1, 48.8, 51.6, 33.1, 61.2, 15.2, 10.6, 29.8, 53.0, -17.5, 40.9, 37.9, 53.1, 39.6, 53.4, 62.2, 47.2, 53.9, 48.5, 47.9, 49.8, 38.8, 53.3, 41.5, 56.6, 40.6, 53.5, 49.4, 52.6, 55.2, 52.5, 61.2, 53.1, 52.9, 77.3, 56.2, 70.1, 57.5, 66.4, 58.8, 62.8, 59.7, 60.3, 48.4, 57.5, 47.0, 58.5, 45.2, 59.9, 43.4, 61.8, 41.4, 41.4, -22.9, 3.1, 44.3, 55.7, 42.9, 56.1, 65.5, 31.3, 53.9, 28.9, 45.7, 1.8, 33.6, 4.9, 37.7, 67.2, -3.7, -11.6, 9.6, -9.7, 18.5, -5.2, 32.7, -4.5, -4.5, 4.4, 49.8, 20.6, -21.6, 21.5, 3.7, 62.6, -0.5, 69.8, -16.0, 3.6, -5.5, 51.4, 31.2, 88.4, 47.5, 10.5, 40.1, 57.5, -5.3, 19.2, 41.1, 98.5, 20.4, 87.4, 11.0, 80.4, 54.4, 100.8, 72.3, 37.8, 49.3, 38.2, 63.6, 37.3, 12.9, 73.1, 21.6, 80.9, 42.8, 94.8, -10.1, 57.4, 56.7, 97.2, 30.3, 93.4, -15.9, 20.2, 53.8, 58.9, 52.1, 60.8, 50.6, 63.5, 49.2, 66.8, 44.2, 72.8, 43.8, 52.5, 42.4, 51.5, 41.5, 50.3, 34.5, 46.5, 6.4, 25.3, 44.7, 53.0, 1.9, 42.3, 38.6, 77.8, 58.9, 92.0, 60.4, 85.1, 49.2, 83.2, 25.3, 62.6, 42.4, 25.3, 30.8, 70.9, 25.4, 21.6, 34.5, 31.6, 17.2, 32.6, 45.5, 89.7, 17.6, 66.3, 25.7, 75.1, 22.0, 52.8, -5.1, 31.7, 11.5, 52.0, -13.2, 35.9, 27.6, 40.0, -14.7, -12.5, -21.9, -13.9, 79.7, 87.5, 102.0, 24.5, 77.3, 45.7, 74.4, 53.1, 82.3, 49.5, 84.3, 53.1, 78.1, 54.5, 80.2, 56.2, 88.6, 68.1, 118.5, 26.6, 93.9, 61.6, 107.0, 57.8, 84.4, 60.0, 82.9, 59.6, 76.0, 49.5, 80.2, 52.2, 82.5, 54.8, 83.8, 60.0, 82.0, 62.3, 82.1, 59.6, 78.3, 56.8, 76.3, 55.8, 72.8, 54.9, 70.0, 79.3, 71.4, 71.9, 72.1, 68.3, 71.9, 64.6, 71.3, 61.8, 77.4, 61.2, 78.8, 62.7, 80.1, 64.6, 81.0, 66.9, 92.3, 48.3, 120.0, 25.3, 79.3, 60.5, 80.7, 61.3, 80.1, 33.2, 87.2, 33.3, 98.3, 10.1, 107.5, 16.5, 83.9, 72.7, 131.0, 10.0, 124.6, 8.7, 118.5, 10.6, 108.0, 7.9, 127.8, 24.8, 91.8, 26.8, 114.0, 41.0, 99.7, 74.0, 94.6, 80.0, 126.4, 25.4, 106.9, 65.7, 77.9, 92.6, 95.5, 17.9, 83.0, 63.5, 122.3, 38.1, 65.9, 100.3, 80.7, 92.1, 86.8, 87.3, 88.6, 43.7, 79.8, 39.6, 91.9, 81.4, 85.0, 86.6, 68.7, 97.1, 100.5, 70.9, 74.2, 96.7, 120.5, 40.0, 75.0, 61.7, 76.0, 63.7, 76.9, 66.8, 77.0, 70.1, 77.8, 76.5, 81.6, 57.7, 83.4, 57.3, 85.2, 56.8, 94.1, 54.4, 117.1, 41.4, 80.1, 58.0, 110.3, 57.1, 78.9, 81.9, 70.5, 85.2, 92.3, 70.8, 95.5, 33.1, 85.8, 77.0, 108.9, 34.2, 99.6, 40.9, 109.6, 46.0, 70.5, 92.1, 94.5, 75.1, 86.7, 81.4, 98.7, 62.7, 116.7, 49.2, 103.3, 63.9, 114.0, 53.4, 100.9, 50.6, 130.6, 11.0, 124.5, 10.1]}, {"rect": [265, 445, 543, 723], "points": [0.35553, 0.05615, 0.0964, 0.0, -0.06096, 0.36409, -0.01418, 0.0, -0.11082, -0.0216, 0.35825, 0.0, -89.17672, -255.51744, -62.19681, 1.0, 70.5, 45.2, 73.7, 31.8, 69.6, 48.4, 68.7, 51.7, 67.7, 53.9, 66.0, 61.2, 65.9, 64.1, 65.4, 68.2, 64.4, 71.8, 62.5, 78.4, 34.4, 82.5, 38.5, 14.4, 62.7, 43.3, 61.7, 50.8, 53.4, 45.2, 46.9, 47.8, 54.8, 50.8, 48.9, 51.2, 33.4, 60.9, 15.5, 10.2, 30.2, 52.6, -17.1, 40.6, 38.2, 52.9, 40.0, 53.0, 62.2, 47.0, 53.9, 48.3, 47.9, 49.7, 39.1, 53.0, 41.8, 56.3, 40.9, 53.3, 49.7, 52.4, 55.2, 52.2, 61.2, 52.9, 53.2, 77.0, 56.2, 70.0, 57.5, 66.3, 58.6, 62.6, 59.5, 59.9, 48.7, 57.2, 47.3, 58.1, 45.5, 59.8, 43.6, 61.7, 41.7, 41.1, -22.6, 2.4, 44.6, 55.3, 43.2, 55.8, 65.7, 30.9, 54.2, 28.5, 46.0, 1.5, 33.9, 4.3, 38.1, 66.8, -3.4, -12.0, 9.6, -10.1, 18.5, -5.8, 32.7, -4.9, -4.1, 3.8, 50.1, 20.3, -21.3, 20.9, 4.1, 62.2, -0.1, 69.2, -15.7, 3.3, -5.1, 50.8, 31.6, 88.0, 47.8, 10.1, 40.4, 57.2, -4.8, 18.9, 41.7, 98.1, 21.0, 87.0, 11.4, 79.8, 54.7, 100.5, 72.4, 37.4, 49.6, 37.8, 63.6, 36.9, 13.3, 72.7, 22.0, 80.3, 43.2, 94.5, -9.7, 56.8, 57.0, 97.1, 30.7, 93.1, -15.4, 19.8, 53.8, 58.6, 52.4, 60.4, 50.6, 63.2, 49.2, 66.7, 44.6, 72.4, 44.1, 52.1, 42.7, 51.2, 41.8, 50.2, 34.9, 46.1, 6.8, 24.9, 45.0, 52.6, 2.2, 41.9, 39.0, 77.4, 59.2, 91.7, 60.7, 84.8, 49.6, 82.9, 25.7, 62.2, 42.7, 24.9, 31.2, 70.5, 25.7, 21.3, 34.9, 31.0, 17.8, 32.2, 45.9, 89.4, 18.2, 65.9, 26.1, 74.7, 22.4, 52.2, -4.7, 31.4, 11.8, 51.6, -12.7, 35.5, 27.9, 39.7, -14.4, -12.8, -21.6, -14.6, 80.0, 87.1, 102.3, 24.1, 77.0, 45.6, 74.2, 52.9, 82.0, 49.3, 84.3, 53.0, 77.9, 54.4, 80.2, 55.8, 88.8, 67.4, 118.8, 26.0, 94.0, 61.0, 107.6, 56.9, 84.4, 59.9, 83.0, 59.4, 76.0, 49.3, 80.1, 52.1, 82.4, 54.5, 83.8, 59.8, 82.0, 62.2, 82.1, 59.4, 78.4, 56.6, 76.1, 55.4, 72.7, 54.5, 70.3, 78.9, 71.4, 71.8, 71.9, 68.2, 71.8, 64.5, 71.0, 61.7, 77.4, 60.9, 78.7, 62.3, 80.1, 64.5, 81.0, 66.7, 92.5, 48.0, 120.6, 24.3, 79.3, 60.3, 80.7, 61.2, 80.2, 33.1, 87.5, 32.9, 98.6, 9.4, 107.8, 15.8, 84.2, 72.0, 131.3, 9.0, 125.2, 8.0, 118.9, 9.9, 108.3, 7.4, 128.3, 24.1, 92.1, 26.4, 114.6, 40.2, 100.2, 73.3, 95.1, 79.4, 127.0, 24.6, 107.2, 65.0, 78.2, 92.2, 95.8, 17.2, 83.0, 63.2, 122.8, 37.4, 66.2, 99.9, 81.0, 91.7, 87.3, 86.7, 88.8, 43.3, 80.1, 39.2, 92.4, 80.7, 85.5, 86.2, 69.0, 96.7, 101.1, 70.2, 74.5, 96.3, 121.1, 39.3, 75.0, 61.3, 76.0, 63.6, 76.9, 66.4, 77.0, 70.0, 77.9, 76.1, 81.6, 57.6, 83.4, 57.1, 85.2, 56.6, 94.4, 54.0, 117.4, 40.7, 80.1, 57.7, 110.8, 56.4, 79.2, 81.2, 70.8, 84.8, 92.5, 70.2, 95.8, 32.7, 86.1, 76.6, 109.2, 33.7, 99.9, 40.2, 109.7, 45.3, 70.8, 91.7, 94.8, 74.7, 87.0, 80.8, 99.0, 62.3, 117.0, 48.5, 103.6, 63.2, 114.6, 52.7, 101.2, 49.9, 131.2, 10.0, 125.1, 9.1]}, {"rect": [266, 445, 544, 723], "points": [0.35609, 0.05582, 0.09637, 0.0, -0.06127, 0.36466, -0.01366, 0.0, -0.11011, -0.02239, 0.35873, 0.0, -89.19629, -255.875, -62.55575, 1.0, 70.0, 45.6, 73.3, 32.2, 69.2, 48.8, 68.2, 52.0, 67.3, 54.3, 65.7, 61.3, 65.4, 64.4, 64.9, 68.5, 64.0, 72.2, 62.1, 78.7, 34.0, 82.8, 38.2, 14.6, 62.3, 43.7, 61.2, 51.1, 53.0, 45.6, 46.5, 48.0, 54.3, 51.1, 48.7, 51.6, 33.1, 61.2, 15.1, 10.5, 29.8, 52.9, -17.3, 40.9, 38.1, 53.0, 39.5, 53.4, 61.7, 47.4, 53.7, 48.5, 47.4, 49.8, 38.6, 53.1, 41.4, 56.6, 40.5, 53.5, 49.2, 52.6, 54.8, 52.5, 60.8, 53.0, 52.9, 77.2, 55.7, 70.4, 57.0, 66.7, 58.1, 63.0, 59.3, 60.3, 48.3, 57.5, 46.9, 58.4, 45.0, 59.9, 43.2, 62.1, 41.3, 41.4, -22.8, 2.7, 44.2, 55.6, 42.8, 56.1, 65.4, 31.3, 53.8, 28.6, 45.6, 1.7, 33.6, 4.6, 37.7, 67.1, -3.7, -11.9, 9.2, -9.7, 18.0, -5.5, 32.3, -4.6, -4.3, 4.1, 49.7, 20.6, -21.7, 21.1, 3.9, 62.5, -0.2, 69.5, -15.8, 3.6, -5.3, 51.0, 31.2, 88.4, 47.4, 10.2, 40.0, 57.5, -5.1, 18.9, 41.3, 98.5, 20.6, 87.0, 11.3, 80.1, 54.3, 100.8, 72.2, 37.8, 49.2, 38.1, 63.5, 37.3, 13.1, 72.8, 21.6, 80.6, 43.0, 94.8, -9.8, 57.1, 56.6, 97.2, 30.3, 93.4, -15.7, 20.1, 53.4, 58.9, 51.9, 60.8, 50.2, 63.5, 48.8, 66.8, 44.4, 72.7, 43.7, 52.4, 42.3, 51.5, 41.4, 50.3, 34.5, 46.4, 6.4, 25.2, 44.6, 52.9, 2.1, 42.2, 38.6, 77.7, 58.8, 92.0, 60.3, 85.0, 49.2, 82.9, 25.5, 62.5, 42.3, 25.2, 31.1, 70.8, 25.3, 21.5, 34.5, 31.3, 17.4, 32.3, 45.5, 89.7, 17.8, 66.3, 25.7, 75.0, 22.0, 52.5, -5.1, 31.7, 11.4, 51.9, -13.0, 35.8, 27.5, 40.0, -14.8, -12.6, -21.8, -14.3, 79.6, 87.4, 102.2, 24.3, 76.5, 45.7, 73.7, 53.1, 81.6, 49.7, 83.8, 53.4, 77.4, 54.7, 80.0, 56.2, 88.4, 67.7, 118.4, 26.2, 93.6, 61.2, 107.2, 57.4, 84.2, 60.3, 82.8, 59.8, 75.5, 49.7, 79.7, 52.5, 82.0, 54.8, 83.6, 60.0, 81.9, 62.6, 81.9, 59.8, 78.1, 57.0, 75.9, 55.7, 72.3, 54.8, 69.9, 79.1, 70.9, 72.2, 71.4, 68.5, 71.4, 64.8, 70.8, 61.8, 77.2, 61.2, 78.3, 62.7, 79.7, 64.8, 80.6, 67.1, 92.1, 48.3, 120.5, 24.7, 79.1, 60.7, 80.5, 61.3, 79.8, 33.2, 87.1, 33.2, 98.2, 9.7, 107.4, 16.1, 83.8, 72.3, 131.2, 9.2, 125.1, 8.3, 119.0, 10.1, 108.4, 7.5, 128.0, 24.3, 91.7, 26.7, 114.5, 40.4, 99.9, 73.6, 94.8, 79.6, 126.9, 24.8, 106.9, 65.3, 77.8, 92.5, 95.4, 17.5, 82.8, 63.6, 122.5, 37.7, 65.8, 100.2, 80.6, 92.0, 87.0, 87.0, 88.4, 43.4, 79.7, 39.6, 92.1, 81.0, 85.1, 86.4, 68.6, 97.0, 100.8, 70.7, 74.1, 96.7, 121.0, 39.5, 74.6, 61.7, 75.5, 64.0, 76.5, 66.8, 76.8, 70.4, 77.4, 76.4, 81.4, 58.0, 83.3, 57.5, 84.7, 57.0, 94.0, 54.3, 117.1, 41.0, 79.7, 58.0, 110.5, 56.6, 78.7, 81.5, 70.4, 85.1, 92.1, 70.4, 95.4, 32.8, 85.7, 76.8, 109.1, 34.0, 99.5, 40.5, 109.5, 45.5, 70.4, 92.0, 94.4, 74.9, 86.6, 81.0, 98.6, 62.6, 116.9, 48.7, 103.3, 63.5, 114.3, 52.9, 100.8, 50.2, 131.1, 10.1, 125.1, 9.2]}, {"rect": [266, 446, 544, 724], "points": [0.35663, 0.05557, 0.09654, 0.0, -0.0618, 0.36511, -0.01287, 0.0, -0.11007, -0.02372, 0.35894, 0.0, -89.01595, -256.52542, -63.18897, 1.0, 69.7, 45.7, 73.6, 31.9, 69.2, 48.9, 68.2, 52.1, 67.2, 54.1, 65.6, 61.1, 65.4, 64.3, 64.7, 68.1, 63.7, 71.8, 62.1, 78.3, 34.0, 82.5, 38.2, 14.2, 62.3, 43.7, 61.0, 51.1, 53.0, 45.6, 46.5, 48.0, 54.3, 51.1, 48.5, 51.6, 33.1, 60.8, 15.2, 10.2, 29.8, 52.5, -17.4, 40.4, 38.1, 52.9, 39.6, 53.1, 61.7, 47.5, 53.5, 48.5, 47.4, 49.8, 38.7, 53.0, 41.5, 56.5, 40.5, 53.4, 49.3, 52.5, 54.8, 52.5, 60.8, 53.0, 52.9, 76.9, 55.7, 70.3, 56.8, 66.3, 58.1, 62.6, 59.1, 59.9, 48.1, 57.1, 46.7, 58.0, 44.8, 59.7, 43.3, 61.7, 41.4, 41.0, -22.9, 2.2, 44.2, 55.3, 42.8, 55.7, 65.4, 30.9, 53.9, 28.5, 46.0, 1.4, 33.7, 4.5, 37.7, 66.7, -3.7, -12.1, 9.2, -10.1, 18.3, -5.6, 32.6, -4.7, -4.2, 3.7, 49.7, 20.3, -21.6, 20.6, 4.0, 62.1, -0.2, 69.1, -15.7, 3.1, -5.5, 50.6, 31.2, 88.0, 47.5, 10.1, 40.0, 57.1, -5.1, 18.7, 41.3, 98.1, 20.6, 86.7, 11.0, 79.7, 54.3, 100.5, 72.3, 37.7, 49.3, 37.8, 63.5, 36.9, 12.9, 72.4, 21.6, 80.2, 42.8, 94.5, -9.8, 56.6, 56.6, 96.8, 30.3, 93.1, -15.7, 19.7, 53.5, 58.5, 51.8, 60.6, 50.2, 63.4, 48.8, 66.7, 44.3, 72.3, 43.7, 52.2, 42.4, 51.2, 41.4, 50.2, 34.5, 46.1, 6.5, 24.8, 44.7, 52.9, 2.2, 41.8, 38.6, 77.3, 58.8, 91.6, 60.3, 84.4, 49.2, 82.5, 25.3, 62.1, 42.4, 24.9, 30.9, 70.5, 25.6, 21.2, 34.5, 30.9, 17.4, 32.2, 45.5, 89.3, 17.8, 65.9, 25.7, 74.6, 22.0, 52.1, -5.1, 31.2, 11.5, 51.5, -12.9, 35.4, 27.5, 39.6, -14.7, -13.0, -21.7, -14.7, 79.7, 86.8, 102.3, 24.0, 76.5, 46.0, 73.7, 53.1, 81.6, 49.7, 83.9, 53.5, 77.5, 54.5, 79.8, 56.2, 88.5, 67.3, 118.8, 25.8, 93.9, 60.9, 107.4, 56.7, 84.3, 60.3, 82.9, 59.8, 75.2, 49.8, 79.7, 52.5, 82.0, 54.9, 83.5, 59.9, 82.0, 62.5, 82.0, 59.8, 78.0, 56.8, 75.7, 55.8, 72.0, 54.9, 70.0, 78.8, 71.0, 72.2, 71.5, 68.2, 71.4, 64.4, 70.6, 61.6, 77.1, 61.1, 78.4, 62.6, 79.7, 64.5, 80.6, 66.8, 92.2, 47.9, 120.7, 24.0, 79.2, 60.4, 80.6, 61.3, 80.1, 33.1, 87.2, 33.1, 98.6, 9.3, 107.8, 15.7, 83.8, 71.9, 131.4, 8.8, 125.3, 7.9, 118.9, 9.8, 108.3, 7.3, 128.2, 23.7, 91.8, 26.3, 114.7, 39.8, 100.0, 72.9, 94.9, 79.2, 127.1, 24.4, 107.3, 64.6, 77.9, 92.1, 95.8, 17.1, 82.9, 63.5, 122.9, 37.0, 65.8, 99.7, 80.9, 91.7, 87.1, 86.6, 88.5, 43.3, 79.8, 39.2, 92.2, 80.6, 85.2, 85.9, 68.6, 96.4, 100.9, 70.0, 74.2, 96.3, 121.1, 38.8, 74.6, 61.5, 75.6, 63.8, 76.5, 66.7, 76.6, 70.3, 77.7, 76.0, 81.5, 58.0, 83.3, 57.5, 84.8, 56.8, 94.3, 54.0, 117.4, 40.6, 79.7, 58.0, 110.6, 56.2, 78.8, 81.1, 70.4, 84.8, 92.2, 70.0, 95.8, 32.7, 85.7, 76.4, 109.2, 33.6, 99.6, 40.2, 109.7, 45.1, 70.4, 91.6, 94.5, 74.3, 86.7, 80.7, 98.7, 62.2, 117.0, 48.1, 103.6, 63.1, 114.6, 52.5, 100.9, 49.8, 131.3, 9.7, 125.3, 8.8]}, {"rect": [266, 447, 544, 725], "points": [0.3579, 0.05573, 0.09661, 0.0, -0.0625, 0.36572, -0.01362, 0.0, -0.1102, -0.02487, 0.36044, 0.0, -89.0646, -257.48817, -62.83664, 1.0, 69.9, 45.8, 73.7, 31.8, 69.4, 48.8, 68.4, 52.0, 67.2, 54.3, 65.8, 60.9, 65.5, 63.9, 64.9, 67.9, 64.0, 71.7, 61.9, 78.1, 34.0, 82.4, 38.3, 13.8, 62.5, 43.6, 61.2, 51.1, 53.0, 45.7, 46.5, 48.0, 54.4, 51.0, 48.7, 51.4, 32.9, 60.4, 15.2, 10.0, 29.6, 52.2, -17.5, 39.9, 37.9, 52.6, 39.6, 53.0, 61.7, 47.7, 53.8, 48.6, 47.4, 49.9, 38.8, 52.9, 41.5, 56.1, 40.5, 53.1, 49.3, 52.4, 54.8, 52.5, 60.8, 53.0, 52.7, 76.4, 55.8, 69.9, 57.1, 66.1, 58.4, 62.4, 59.4, 59.6, 48.3, 56.9, 47.0, 57.8, 45.1, 59.3, 43.4, 61.5, 41.2, 40.7, -22.7, 1.7, 44.3, 55.1, 42.9, 55.6, 65.5, 30.8, 54.0, 28.2, 46.1, 0.9, 33.7, 4.1, 37.8, 66.3, -3.6, -12.6, 9.2, -10.2, 18.1, -6.0, 32.7, -5.1, -4.2, 3.5, 49.8, 19.9, -21.6, 20.1, 3.7, 61.7, -0.5, 68.9, -15.7, 2.6, -5.5, 50.2, 30.9, 87.9, 47.6, 9.7, 40.1, 57.0, -5.0, 18.3, 41.0, 98.0, 20.2, 86.5, 11.0, 79.5, 54.3, 100.4, 72.4, 37.4, 49.3, 37.4, 63.6, 36.9, 12.8, 72.2, 21.5, 80.1, 42.8, 94.3, -9.8, 56.4, 56.6, 96.7, 30.0, 92.9, -15.6, 19.2, 53.5, 58.2, 52.0, 60.2, 50.3, 63.0, 48.9, 66.3, 44.3, 72.1, 43.8, 52.2, 42.4, 51.2, 41.4, 50.3, 34.6, 45.7, 6.5, 24.4, 44.7, 52.7, 2.0, 41.4, 38.4, 76.9, 58.6, 91.3, 60.3, 84.3, 48.9, 82.3, 25.3, 61.8, 42.4, 24.5, 30.9, 70.1, 25.4, 20.7, 34.6, 30.8, 17.2, 31.8, 45.2, 88.9, 17.6, 65.8, 25.4, 74.2, 21.8, 52.0, -5.0, 30.8, 11.5, 51.1, -12.9, 34.9, 27.3, 39.3, -14.7, -13.5, -21.6, -15.0, 79.7, 86.6, 102.7, 23.6, 76.5, 45.9, 73.7, 53.3, 81.6, 49.6, 83.9, 53.6, 77.7, 54.7, 80.1, 56.1, 88.8, 67.3, 119.2, 25.5, 94.0, 60.9, 107.7, 56.2, 84.5, 60.1, 83.0, 59.6, 75.5, 50.0, 79.7, 52.4, 82.1, 55.0, 83.6, 60.0, 82.1, 62.3, 82.1, 59.6, 78.3, 57.0, 75.9, 55.8, 72.2, 54.8, 70.0, 78.6, 71.0, 71.8, 71.7, 68.0, 71.5, 64.2, 70.9, 61.4, 77.4, 60.7, 78.5, 62.5, 79.8, 64.4, 80.7, 66.7, 92.6, 47.7, 121.1, 23.6, 79.4, 60.3, 80.7, 61.2, 80.2, 32.8, 87.5, 32.8, 99.0, 9.2, 108.1, 15.3, 83.8, 71.8, 132.1, 8.4, 125.7, 7.6, 119.0, 9.7, 108.7, 7.0, 128.8, 23.5, 92.2, 26.3, 115.1, 39.5, 100.3, 72.8, 95.3, 78.8, 127.5, 24.0, 107.6, 64.5, 78.2, 91.8, 96.2, 17.0, 83.0, 63.5, 123.3, 36.9, 65.8, 99.5, 81.0, 91.3, 87.4, 86.2, 88.8, 43.0, 80.1, 39.2, 92.5, 80.3, 85.3, 85.8, 68.7, 96.3, 101.3, 69.6, 74.2, 96.3, 121.5, 38.7, 74.7, 61.1, 75.7, 63.5, 76.6, 66.6, 76.9, 70.0, 77.8, 75.9, 81.6, 57.8, 83.4, 57.4, 84.9, 56.8, 94.4, 54.0, 117.8, 40.5, 79.8, 57.9, 111.0, 55.8, 79.1, 81.0, 70.4, 84.6, 92.5, 69.7, 96.2, 32.3, 86.1, 76.1, 109.6, 33.3, 100.0, 40.1, 110.0, 44.8, 70.4, 91.3, 94.8, 74.2, 87.0, 80.6, 99.0, 61.9, 117.4, 47.9, 104.0, 62.8, 115.0, 52.1, 101.3, 49.8, 131.7, 9.3, 125.7, 8.3]}, {"rect": [266, 448, 544, 726], "points": [0.35906, 0.05631, 0.09749, 0.0, -0.06345, 0.36639, -0.01405, 0.0, -0.11114, -0.02654, 0.3623, 0.0, -88.97346, -258.78738, -63.30193, 1.0, 70.3, 46.2, 74.1, 31.7, 69.5, 49.4, 68.5, 52.5, 67.5, 54.8, 66.1, 60.1, 66.0, 63.4, 65.2, 67.3, 64.2, 71.1, 62.1, 77.7, 33.8, 82.0, 38.3, 13.5, 62.7, 43.8, 61.3, 51.5, 53.3, 45.9, 46.5, 48.2, 54.6, 51.3, 48.8, 51.6, 32.9, 60.3, 15.3, 9.4, 29.4, 52.1, -17.5, 39.1, 38.0, 52.6, 39.5, 53.0, 62.1, 48.0, 53.8, 48.8, 47.5, 50.0, 38.9, 52.7, 41.7, 55.8, 40.4, 53.0, 49.3, 52.6, 55.0, 52.8, 60.9, 53.5, 53.0, 76.0, 56.0, 69.2, 57.4, 65.4, 58.8, 61.6, 59.7, 59.0, 48.5, 56.4, 47.1, 57.4, 45.2, 58.9, 43.5, 60.9, 41.3, 40.6, -22.9, 0.9, 44.4, 54.7, 43.0, 55.2, 65.8, 30.8, 54.3, 28.0, 46.5, 0.6, 34.0, 3.7, 37.6, 65.9, -3.6, -13.3, 9.2, -10.6, 18.4, -6.4, 32.7, -5.4, -4.4, 2.8, 49.9, 19.8, -21.6, 19.3, 3.4, 61.3, -0.8, 68.2, -15.9, 1.8, -5.8, 49.7, 30.6, 87.5, 47.9, 9.3, 40.0, 56.6, -5.0, 17.6, 40.7, 97.7, 19.9, 86.2, 10.6, 79.2, 54.3, 100.3, 72.7, 37.3, 49.5, 37.4, 63.9, 36.8, 12.6, 71.9, 21.0, 79.7, 42.5, 94.0, -10.1, 55.7, 56.6, 96.7, 29.7, 92.6, -15.6, 18.5, 53.8, 57.7, 52.1, 59.7, 50.6, 62.5, 48.9, 65.8, 44.4, 71.5, 43.9, 52.3, 42.5, 51.3, 41.3, 50.3, 34.4, 45.6, 6.6, 24.0, 44.8, 52.8, 2.0, 40.7, 38.4, 76.5, 58.6, 91.2, 60.4, 84.2, 48.9, 82.0, 25.1, 61.4, 42.5, 24.4, 30.7, 70.0, 25.5, 20.4, 34.7, 30.5, 17.2, 31.4, 45.2, 88.8, 17.3, 65.4, 25.1, 74.1, 21.8, 51.7, -5.0, 30.1, 11.3, 50.8, -13.2, 34.1, 27.4, 39.2, -14.7, -14.3, -21.6, -15.8, 80.0, 86.5, 103.3, 23.5, 76.8, 46.4, 74.0, 53.7, 82.0, 50.1, 84.4, 53.8, 77.9, 55.0, 80.4, 56.6, 89.1, 67.3, 119.5, 25.4, 94.5, 60.9, 107.9, 55.8, 85.1, 60.1, 83.4, 59.7, 75.8, 50.4, 80.1, 52.7, 82.5, 55.3, 84.3, 60.0, 82.4, 62.3, 82.6, 59.7, 78.5, 57.3, 76.1, 56.4, 72.3, 55.3, 70.0, 78.2, 71.5, 71.5, 72.0, 67.6, 71.9, 63.6, 71.2, 60.7, 77.8, 60.4, 79.1, 62.2, 80.4, 64.1, 81.2, 66.5, 93.1, 47.9, 121.3, 23.4, 79.8, 60.0, 81.1, 61.0, 80.8, 32.7, 88.1, 32.7, 99.4, 8.8, 108.5, 15.2, 84.1, 71.7, 132.5, 8.3, 126.0, 7.7, 119.5, 9.6, 109.0, 6.8, 129.2, 23.4, 92.7, 26.2, 115.2, 39.2, 100.4, 72.5, 95.4, 78.5, 127.6, 23.9, 107.8, 64.1, 78.3, 91.7, 96.5, 17.0, 83.6, 63.3, 123.4, 36.8, 65.8, 99.5, 81.1, 91.3, 87.5, 86.2, 89.1, 43.2, 80.4, 39.2, 92.6, 80.2, 85.6, 85.7, 69.0, 96.2, 101.4, 69.2, 74.5, 96.2, 121.6, 38.3, 75.0, 60.6, 76.2, 63.0, 77.1, 66.3, 77.1, 69.6, 77.8, 75.5, 82.0, 58.0, 83.7, 57.8, 85.4, 57.0, 94.9, 54.0, 118.1, 40.2, 80.4, 58.3, 111.3, 55.8, 79.2, 81.0, 70.4, 84.3, 92.9, 69.7, 96.5, 32.3, 86.4, 76.0, 110.2, 33.2, 100.6, 40.1, 110.4, 44.8, 70.4, 91.2, 95.1, 74.2, 87.3, 80.3, 99.3, 61.9, 117.8, 47.5, 104.3, 62.8, 115.1, 51.7, 101.6, 49.8, 132.1, 9.2, 125.9, 8.1]}, {"rect": [266, 450, 544, 728], "points": [0.35927, 0.0569, 0.09761, 0.0, -0.06426, 0.36757, -0.01263, 0.0, -0.11031, -0.02875, 0.36338, 0.0, -88.21331, -260.69328, -64.35446, 1.0, 69.0, 47.4, 74.2, 31.0, 68.5, 51.0, 67.3, 54.5, 66.3, 56.8, 65.9, 58.5, 65.5, 62.0, 65.0, 66.4, 63.7, 70.4, 62.1, 76.6, 34.0, 81.4, 38.6, 12.9, 62.0, 44.6, 60.6, 53.2, 53.1, 46.4, 46.6, 48.3, 54.1, 52.5, 48.8, 52.5, 33.7, 59.8, 15.8, 8.7, 30.4, 51.9, -17.3, 37.9, 38.6, 52.1, 40.3, 52.5, 61.1, 49.3, 53.6, 49.8, 47.5, 50.5, 39.5, 52.4, 42.3, 54.9, 40.9, 52.6, 49.3, 53.8, 54.5, 54.5, 60.1, 55.7, 53.2, 75.1, 55.9, 68.6, 57.2, 64.3, 58.6, 60.2, 59.8, 57.1, 48.8, 54.8, 47.4, 56.0, 45.6, 57.8, 44.1, 60.0, 42.0, 40.1, -22.4, -0.4, 45.0, 53.7, 43.6, 54.2, 65.9, 30.0, 54.7, 27.3, 46.8, -0.1, 34.3, 2.9, 38.4, 65.3, -3.2, -14.3, 9.4, -11.5, 18.6, -7.0, 33.0, -6.0, -4.0, 1.9, 50.5, 19.0, -21.1, 18.1, 3.5, 60.4, -0.6, 67.3, -15.5, 0.6, -5.4, 48.8, 30.8, 87.0, 48.3, 8.7, 40.8, 55.8, -4.5, 16.7, 40.8, 97.1, 19.8, 85.6, 10.5, 78.3, 54.2, 99.8, 72.8, 36.8, 50.0, 36.8, 64.1, 36.3, 12.7, 71.2, 21.1, 79.1, 42.7, 93.4, -9.9, 54.5, 56.6, 96.1, 29.8, 92.0, -15.1, 17.5, 53.9, 55.8, 52.4, 58.3, 50.7, 61.1, 49.3, 65.0, 44.9, 70.9, 44.2, 52.4, 42.8, 51.4, 41.9, 50.2, 35.2, 45.1, 7.1, 23.1, 45.1, 53.2, 2.4, 40.1, 38.9, 75.9, 58.8, 90.6, 60.6, 83.3, 49.2, 81.1, 25.6, 61.1, 43.1, 23.9, 31.1, 69.4, 26.0, 19.8, 35.2, 29.9, 17.7, 30.8, 45.4, 88.0, 17.7, 64.9, 25.5, 73.6, 22.3, 51.1, -4.5, 29.4, 11.7, 50.2, -12.8, 33.2, 27.9, 38.6, -14.2, -15.5, -21.1, -17.3, 80.1, 86.0, 102.9, 23.0, 75.8, 47.2, 73.0, 55.5, 81.2, 50.8, 83.9, 54.5, 77.2, 56.5, 80.2, 57.8, 88.9, 66.8, 119.4, 24.9, 94.0, 60.7, 108.4, 55.2, 85.5, 60.4, 84.1, 60.0, 74.5, 51.7, 79.4, 53.9, 82.1, 56.2, 84.9, 60.1, 82.8, 62.0, 83.2, 60.0, 78.4, 58.8, 75.4, 58.2, 71.3, 57.6, 70.0, 77.4, 71.0, 70.9, 71.5, 66.5, 71.5, 62.4, 71.0, 59.3, 78.1, 59.5, 79.2, 61.4, 80.5, 63.5, 81.0, 66.2, 92.7, 47.4, 121.9, 22.3, 80.4, 59.7, 81.7, 60.7, 80.7, 32.2, 88.0, 32.2, 99.5, 8.3, 108.5, 14.7, 83.8, 71.0, 132.7, 7.5, 126.2, 6.9, 119.6, 8.8, 109.1, 6.1, 129.1, 22.7, 92.6, 25.5, 115.8, 38.3, 100.7, 72.2, 95.7, 78.2, 128.0, 23.1, 108.1, 63.6, 78.3, 91.4, 96.4, 16.2, 83.7, 63.0, 123.5, 36.0, 65.8, 99.0, 81.4, 91.0, 87.8, 85.6, 88.9, 42.5, 80.2, 38.7, 92.9, 79.9, 85.6, 85.4, 69.0, 95.7, 101.9, 68.6, 74.5, 95.7, 121.9, 37.7, 75.1, 59.3, 76.1, 61.9, 76.9, 65.4, 76.9, 69.0, 77.8, 74.7, 82.3, 58.6, 83.8, 58.2, 85.2, 57.6, 94.5, 53.8, 118.0, 39.7, 80.5, 59.0, 111.4, 55.3, 79.2, 80.2, 70.4, 83.4, 93.0, 69.4, 96.4, 31.8, 86.2, 75.5, 110.1, 32.7, 100.5, 39.6, 110.5, 44.3, 70.4, 90.6, 95.0, 73.7, 87.4, 80.0, 99.4, 61.7, 117.9, 47.0, 104.2, 62.5, 115.5, 51.1, 101.4, 49.3, 132.6, 8.3, 126.5, 7.0]}, {"rect": [266, 451, 544, 729], "points": [0.36053, 0.05754, 0.09886, 0.0, -0.06511, 0.36894, -0.01352, 0.0, -0.11108, -0.03054, 0.36556, 0.0, -88.25696, -262.53811, -64.81835, 1.0, 69.0, 48.0, 74.5, 31.2, 68.5, 51.6, 67.3, 55.3, 66.3, 57.5, 66.1, 58.2, 65.7, 61.8, 64.9, 66.0, 63.9, 70.1, 62.2, 76.4, 33.8, 81.1, 38.7, 12.5, 62.1, 45.6, 60.7, 53.9, 53.3, 47.1, 46.9, 49.0, 54.3, 53.1, 48.8, 52.8, 33.4, 59.5, 15.4, 8.4, 30.1, 51.6, -18.0, 37.1, 39.0, 52.3, 40.4, 52.5, 61.2, 49.9, 53.8, 50.3, 47.8, 50.9, 39.9, 52.5, 42.6, 54.9, 41.3, 52.8, 49.3, 54.1, 54.4, 55.0, 60.2, 56.3, 53.1, 74.7, 56.1, 68.3, 57.5, 64.1, 58.8, 60.0, 59.8, 56.9, 49.1, 54.8, 47.7, 55.9, 45.9, 57.7, 44.5, 59.9, 42.0, 40.1, -22.8, -1.1, 45.4, 53.8, 44.0, 54.3, 66.3, 29.9, 54.8, 27.2, 46.6, -0.4, 34.2, 2.7, 38.3, 65.0, -3.8, -15.0, 9.0, -11.9, 18.2, -7.3, 32.8, -6.4, -4.3, 1.5, 50.7, 18.9, -21.7, 17.3, 3.1, 60.0, -1.1, 66.9, -15.9, 0.1, -6.1, 48.1, 30.6, 86.6, 48.4, 8.4, 41.2, 55.8, -5.2, 16.3, 40.6, 96.8, 19.5, 85.3, 10.0, 77.9, 54.0, 99.5, 73.1, 36.8, 50.2, 36.8, 64.4, 36.3, 12.3, 70.7, 20.9, 78.8, 42.4, 93.1, -10.7, 54.0, 56.6, 95.8, 29.6, 91.7, -15.7, 16.8, 54.2, 55.8, 52.7, 58.1, 51.0, 60.9, 49.6, 64.6, 44.8, 70.5, 44.5, 52.7, 43.2, 51.5, 42.2, 50.5, 35.1, 45.1, 6.7, 22.7, 45.4, 53.6, 2.0, 39.7, 38.8, 75.6, 58.5, 90.3, 60.4, 83.0, 49.2, 81.0, 25.5, 60.8, 43.0, 23.6, 31.0, 69.1, 25.9, 19.4, 35.1, 29.6, 17.3, 30.5, 45.2, 87.6, 17.3, 64.5, 25.1, 73.3, 21.9, 51.1, -5.2, 28.8, 11.3, 49.8, -13.4, 32.5, 27.8, 38.6, -14.8, -16.0, -21.7, -18.1, 80.1, 85.7, 103.5, 23.0, 75.9, 48.0, 72.9, 56.2, 81.1, 51.3, 83.9, 54.7, 77.3, 56.8, 80.1, 57.9, 88.8, 67.1, 119.7, 25.1, 94.0, 61.0, 108.3, 54.9, 85.7, 60.3, 84.3, 59.8, 74.6, 52.5, 79.3, 54.5, 82.0, 56.4, 85.1, 60.2, 82.9, 61.7, 83.7, 59.8, 78.4, 59.1, 75.5, 58.6, 71.4, 58.1, 70.0, 77.0, 70.9, 70.6, 71.4, 66.3, 71.7, 62.3, 71.3, 59.0, 78.3, 59.5, 79.5, 61.3, 80.5, 63.5, 81.1, 65.9, 92.9, 47.7, 122.1, 22.1, 80.6, 59.5, 81.9, 60.7, 81.0, 32.2, 88.0, 32.2, 99.9, 8.2, 109.0, 14.7, 83.8, 70.9, 133.1, 7.6, 126.3, 6.8, 119.4, 8.7, 109.2, 5.9, 129.5, 22.6, 92.9, 25.6, 115.7, 38.2, 100.8, 72.2, 95.7, 77.9, 128.5, 22.9, 108.2, 63.6, 78.5, 91.2, 96.7, 16.2, 83.8, 63.0, 123.9, 36.0, 65.8, 99.0, 81.4, 90.7, 87.9, 85.6, 88.9, 42.7, 80.5, 38.6, 93.0, 79.7, 85.9, 85.2, 69.0, 95.7, 101.8, 68.6, 74.5, 95.4, 122.1, 37.4, 75.4, 59.1, 76.3, 61.8, 76.9, 65.1, 76.8, 68.7, 77.8, 74.6, 82.4, 58.8, 83.9, 58.3, 85.3, 57.5, 94.4, 53.8, 118.3, 40.0, 80.7, 59.2, 111.5, 55.3, 79.2, 80.1, 70.4, 83.3, 93.0, 69.5, 96.6, 31.8, 86.4, 75.5, 110.4, 32.7, 100.8, 39.6, 110.6, 44.5, 70.4, 90.3, 95.2, 73.7, 87.4, 79.7, 99.4, 61.9, 117.9, 47.0, 104.5, 62.6, 115.6, 51.1, 101.7, 49.6, 132.8, 8.2, 126.7, 6.8]}, {"rect": [266, 452, 544, 730], "points": [0.3608, 0.05765, 0.09857, 0.0, -0.06624, 0.37046, -0.01321, 0.0, -0.11018, -0.03179, 0.36587, 0.0, -87.28992, -264.11154, -64.80944, 1.0, 68.7, 48.3, 74.5, 30.9, 68.2, 51.9, 67.2, 55.6, 66.2, 57.9, 65.9, 58.2, 65.4, 61.8, 64.9, 65.9, 63.6, 70.1, 62.2, 76.1, 34.0, 81.0, 38.8, 12.5, 61.7, 45.9, 60.4, 54.2, 53.3, 47.3, 46.9, 49.2, 54.3, 53.4, 48.8, 52.9, 33.7, 59.4, 15.8, 8.3, 30.4, 51.6, -17.7, 37.0, 39.1, 52.1, 40.5, 52.5, 60.8, 50.2, 53.8, 50.5, 47.8, 51.0, 39.9, 52.5, 42.7, 54.8, 41.3, 52.6, 49.2, 54.3, 54.3, 55.2, 59.9, 56.6, 53.4, 74.6, 56.1, 68.3, 57.5, 64.1, 58.8, 60.0, 59.8, 56.8, 49.2, 54.5, 47.8, 55.8, 46.0, 57.6, 44.5, 59.6, 42.3, 40.1, -22.7, -1.4, 45.4, 53.6, 44.1, 54.0, 66.6, 29.9, 55.2, 27.2, 46.9, -0.8, 34.2, 2.4, 38.6, 65.0, -3.5, -15.2, 9.3, -12.0, 18.5, -7.4, 33.2, -6.5, -4.0, 1.1, 51.0, 18.8, -21.4, 17.1, 3.3, 59.9, -0.8, 66.8, -15.8, -0.3, -5.8, 48.0, 30.8, 86.6, 48.7, 8.3, 41.3, 55.7, -4.9, 16.2, 40.6, 96.7, 19.5, 85.2, 10.3, 77.8, 53.9, 99.4, 73.2, 36.8, 50.5, 36.8, 64.4, 36.0, 12.5, 70.6, 21.2, 78.7, 42.4, 93.0, -10.4, 53.9, 56.6, 95.7, 29.6, 91.6, -15.5, 16.6, 54.2, 55.5, 52.5, 57.8, 51.0, 60.9, 49.6, 64.6, 45.1, 70.2, 44.5, 52.6, 43.2, 51.6, 42.3, 50.6, 35.5, 45.1, 7.0, 22.6, 45.5, 53.5, 2.1, 39.7, 39.1, 75.6, 58.5, 90.2, 60.6, 82.9, 49.3, 80.7, 25.7, 60.8, 43.3, 23.5, 31.3, 69.1, 26.2, 19.4, 35.4, 29.5, 17.6, 30.4, 45.5, 87.6, 17.6, 64.5, 25.4, 73.2, 22.2, 51.1, -4.9, 28.6, 11.6, 49.8, -13.1, 32.3, 28.1, 38.3, -14.5, -16.5, -21.4, -18.4, 80.0, 85.7, 103.5, 23.0, 75.6, 48.2, 72.8, 56.5, 81.0, 51.5, 83.8, 55.0, 77.0, 57.1, 80.1, 58.0, 88.8, 66.9, 120.1, 24.9, 94.0, 60.8, 108.6, 55.1, 86.1, 60.3, 84.7, 59.9, 74.2, 52.8, 79.2, 54.7, 82.0, 56.6, 85.3, 60.2, 83.3, 61.7, 83.9, 59.9, 78.7, 59.3, 75.5, 58.9, 71.3, 58.4, 69.9, 76.6, 70.8, 70.6, 71.4, 66.1, 71.4, 62.2, 71.3, 58.7, 78.4, 59.4, 79.6, 61.3, 80.6, 63.2, 81.1, 65.9, 92.9, 47.5, 122.5, 22.0, 81.0, 59.5, 82.0, 60.7, 81.0, 32.2, 88.2, 32.2, 100.2, 7.9, 109.4, 14.6, 83.8, 70.9, 133.5, 7.3, 126.7, 6.5, 119.8, 8.7, 109.5, 5.6, 129.8, 22.6, 93.0, 25.4, 116.1, 38.1, 100.8, 72.2, 95.8, 78.2, 128.9, 22.6, 108.2, 63.6, 78.3, 91.1, 97.0, 16.1, 83.9, 63.0, 124.2, 35.9, 65.8, 98.9, 81.1, 90.7, 87.9, 85.6, 89.2, 42.7, 80.5, 38.6, 93.0, 79.7, 85.7, 85.2, 69.0, 95.4, 101.9, 68.6, 74.5, 95.3, 122.4, 37.3, 75.4, 59.0, 76.4, 61.8, 76.9, 65.0, 76.6, 68.7, 77.7, 74.3, 82.5, 58.9, 84.2, 58.4, 85.6, 57.8, 94.4, 53.9, 118.3, 40.0, 81.0, 59.4, 111.8, 55.3, 79.1, 80.1, 70.4, 83.0, 93.0, 69.5, 96.7, 31.8, 86.2, 75.5, 110.5, 32.7, 100.8, 39.6, 110.9, 44.6, 70.4, 90.3, 95.3, 73.7, 87.4, 79.7, 99.5, 61.8, 118.3, 47.0, 104.5, 62.6, 115.7, 51.1, 101.7, 49.6, 133.4, 7.8, 127.1, 6.4]}, {"rect": [266, 454, 544, 732], "points": [0.36077, 0.05759, 0.09688, 0.0, -0.06732, 0.37182, -0.01204, 0.0, -0.10834, -0.03286, 0.36498, 0.0, -86.06498, -265.55683, -64.17382, 1.0, 68.6, 48.2, 74.5, 30.4, 68.1, 51.6, 67.1, 55.3, 65.9, 57.6, 65.8, 57.9, 65.3, 61.3, 64.8, 65.5, 63.5, 69.7, 62.2, 75.6, 34.1, 80.4, 39.1, 12.0, 61.6, 45.6, 60.3, 53.9, 53.2, 46.9, 46.9, 48.8, 54.2, 53.3, 48.7, 52.6, 34.0, 59.0, 16.1, 7.8, 30.8, 51.1, -17.2, 36.4, 39.2, 51.7, 40.7, 52.1, 60.7, 50.1, 53.7, 50.2, 47.8, 50.7, 39.9, 52.0, 42.7, 54.4, 41.3, 52.4, 49.2, 54.0, 54.2, 55.2, 59.8, 56.5, 53.4, 73.9, 56.0, 67.9, 57.4, 63.6, 58.8, 59.5, 59.8, 56.5, 49.1, 54.3, 47.7, 55.3, 45.9, 57.2, 44.5, 59.4, 42.4, 39.6, -22.2, -2.2, 45.4, 53.3, 44.0, 53.8, 66.4, 29.2, 55.3, 26.7, 47.0, -1.3, 34.5, 1.9, 38.7, 64.5, -2.9, -16.0, 9.7, -12.8, 18.6, -8.2, 33.3, -7.3, -3.7, 0.5, 51.1, 18.1, -20.9, 16.6, 3.7, 59.5, -0.4, 66.1, -15.3, -0.9, -5.2, 47.6, 30.9, 85.9, 48.8, 7.5, 41.3, 55.3, -4.3, 15.7, 40.6, 95.9, 19.9, 84.5, 10.6, 77.1, 53.9, 98.7, 73.2, 36.1, 50.6, 36.4, 64.4, 35.6, 12.9, 70.1, 21.3, 78.0, 42.5, 92.3, -10.1, 53.2, 56.3, 95.0, 29.7, 90.9, -14.9, 15.8, 54.2, 55.2, 52.7, 57.5, 51.0, 60.5, 49.6, 64.2, 45.1, 69.7, 44.5, 52.4, 43.4, 51.1, 42.5, 50.2, 35.8, 44.7, 7.3, 22.2, 45.4, 53.3, 2.6, 39.2, 39.1, 75.1, 58.5, 89.5, 60.4, 82.2, 49.3, 80.3, 25.8, 60.3, 43.6, 23.0, 31.4, 68.4, 26.3, 18.9, 35.5, 29.0, 17.9, 29.9, 45.3, 87.1, 17.9, 63.8, 25.8, 72.5, 22.5, 50.6, -4.3, 28.2, 11.9, 49.3, -12.6, 31.8, 28.4, 37.9, -13.9, -17.3, -20.8, -19.3, 79.7, 85.2, 103.6, 22.3, 75.5, 47.9, 72.7, 56.1, 81.0, 51.1, 83.9, 54.4, 77.0, 57.0, 80.2, 57.6, 88.5, 66.4, 120.2, 24.4, 93.9, 60.4, 108.7, 54.1, 86.2, 59.9, 84.8, 59.4, 74.1, 52.5, 79.2, 54.4, 82.0, 56.2, 85.6, 59.6, 83.4, 61.3, 84.2, 59.4, 78.7, 58.9, 75.5, 58.5, 71.3, 58.4, 69.7, 76.2, 70.6, 70.2, 71.3, 65.9, 71.4, 61.7, 71.3, 58.4, 78.7, 58.9, 79.7, 60.8, 80.6, 62.8, 81.1, 65.4, 92.7, 47.0, 122.9, 21.3, 81.1, 59.0, 82.1, 60.0, 81.0, 31.5, 88.0, 31.8, 100.3, 7.4, 109.5, 13.9, 83.8, 70.5, 133.9, 6.6, 127.1, 5.9, 120.2, 7.9, 109.7, 5.1, 130.2, 22.1, 93.0, 24.9, 116.4, 37.4, 100.9, 71.6, 95.8, 77.5, 129.3, 21.9, 108.3, 63.2, 78.3, 90.5, 97.1, 15.6, 83.9, 62.4, 124.3, 35.5, 65.6, 98.2, 81.1, 90.0, 87.9, 84.9, 88.9, 42.1, 80.5, 38.0, 93.0, 79.3, 85.7, 84.5, 68.7, 94.9, 102.2, 67.9, 74.2, 94.6, 122.6, 36.8, 75.5, 58.6, 76.4, 61.3, 76.9, 64.6, 76.5, 68.3, 77.5, 73.9, 82.8, 58.5, 84.3, 58.0, 85.6, 57.1, 94.4, 53.4, 118.4, 39.3, 81.1, 58.9, 111.9, 54.9, 78.9, 79.4, 70.1, 82.6, 93.0, 69.1, 96.7, 31.3, 86.1, 75.1, 110.5, 32.2, 100.8, 39.2, 111.0, 43.9, 70.2, 89.9, 95.2, 73.3, 87.1, 79.3, 99.5, 61.3, 118.3, 46.6, 104.5, 62.2, 116.0, 50.4, 101.8, 49.0, 133.8, 7.0, 127.8, 5.6]}, {"rect": [266, 455, 544, 733], "points": [0.36069, 0.0575, 0.09643, 0.0, -0.06794, 0.37329, -0.01075, 0.0, -0.1072, -0.03379, 0.36427, 0.0, -85.29769, -266.79891, -64.51761, 1.0, 68.4, 48.2, 74.5, 30.4, 67.6, 51.8, 66.7, 55.5, 65.7, 57.5, 65.6, 58.0, 65.1, 61.4, 64.4, 65.6, 63.3, 70.2, 62.4, 75.8, 34.4, 80.6, 39.4, 12.0, 61.1, 45.8, 60.1, 54.1, 52.7, 47.0, 46.8, 48.8, 53.9, 53.3, 48.4, 52.8, 34.3, 59.0, 16.4, 7.8, 31.0, 51.1, -17.1, 36.5, 38.8, 51.9, 40.3, 52.1, 60.5, 50.1, 53.5, 50.2, 47.7, 50.7, 39.7, 52.0, 42.5, 54.7, 41.1, 52.5, 49.1, 54.2, 53.9, 55.2, 59.6, 56.5, 53.6, 74.3, 55.8, 68.3, 57.1, 63.8, 58.2, 59.9, 59.5, 56.6, 48.8, 54.3, 47.4, 55.6, 45.8, 57.5, 44.1, 59.5, 42.6, 39.6, -21.8, -2.3, 45.0, 53.4, 43.9, 53.9, 66.6, 29.4, 55.5, 26.7, 47.3, -1.4, 34.8, 1.8, 38.9, 64.6, -2.6, -16.1, 10.1, -12.9, 18.9, -8.6, 33.6, -7.3, -3.4, 0.5, 51.4, 18.4, -20.8, 16.3, 4.1, 59.5, -0.1, 66.3, -14.9, -0.9, -5.1, 47.9, 31.2, 86.1, 49.1, 7.7, 41.1, 55.4, -4.2, 15.7, 40.9, 95.9, 20.2, 84.7, 11.0, 77.4, 54.2, 98.6, 73.2, 36.3, 50.6, 36.4, 64.5, 35.8, 13.2, 70.4, 21.6, 78.3, 42.7, 92.5, -9.7, 53.5, 56.5, 95.0, 30.2, 91.1, -14.8, 15.8, 53.9, 55.3, 52.1, 57.6, 50.6, 60.8, 49.2, 64.5, 45.4, 70.0, 44.1, 52.4, 43.1, 51.2, 42.1, 50.2, 36.1, 44.7, 7.6, 22.2, 45.3, 53.4, 2.7, 39.2, 39.4, 75.2, 58.8, 89.5, 60.6, 82.5, 49.5, 80.4, 26.1, 60.4, 43.7, 23.0, 31.6, 68.6, 26.5, 19.0, 35.8, 29.0, 18.2, 29.9, 45.5, 87.2, 18.2, 64.0, 26.1, 72.7, 22.8, 50.6, -4.2, 28.2, 12.2, 49.4, -12.5, 31.9, 28.5, 38.1, -13.5, -17.4, -20.4, -19.6, 79.7, 85.3, 103.7, 22.4, 75.3, 48.1, 72.5, 56.1, 80.9, 51.3, 83.9, 54.6, 77.1, 57.0, 80.3, 57.9, 88.5, 66.7, 120.3, 24.4, 94.0, 60.3, 109.1, 54.3, 86.5, 59.8, 85.2, 59.4, 74.0, 52.7, 79.0, 54.5, 82.1, 56.1, 86.0, 59.8, 83.7, 61.3, 84.6, 59.4, 78.8, 58.9, 75.6, 58.7, 71.1, 58.3, 69.9, 76.5, 70.6, 70.6, 71.2, 66.1, 71.2, 61.8, 71.1, 58.5, 78.7, 59.0, 79.8, 60.8, 80.7, 63.1, 81.5, 65.5, 92.9, 47.0, 123.0, 21.2, 81.4, 59.2, 82.4, 60.2, 81.0, 31.7, 88.0, 31.8, 100.1, 7.3, 109.3, 13.9, 83.8, 70.6, 134.1, 6.5, 127.3, 5.6, 120.4, 7.9, 109.8, 5.1, 130.4, 22.1, 93.0, 24.9, 116.6, 37.4, 100.9, 71.8, 95.8, 77.8, 129.5, 22.0, 108.6, 63.4, 78.3, 90.7, 97.2, 15.6, 84.3, 62.6, 124.5, 35.5, 65.8, 98.2, 81.1, 90.2, 87.9, 85.1, 88.9, 42.3, 80.5, 38.2, 93.0, 79.3, 85.6, 84.7, 68.7, 95.0, 102.2, 68.1, 74.2, 94.8, 123.0, 36.8, 75.3, 58.8, 76.2, 61.6, 76.7, 64.9, 76.6, 68.7, 77.7, 74.2, 82.9, 58.5, 84.4, 58.0, 85.7, 57.1, 94.4, 53.4, 118.5, 39.5, 81.4, 58.9, 111.9, 55.1, 79.2, 79.7, 70.3, 82.7, 93.0, 69.1, 96.7, 31.3, 86.1, 75.2, 110.6, 32.2, 100.9, 39.2, 111.0, 44.1, 70.4, 89.9, 95.0, 73.6, 87.1, 79.6, 99.5, 61.6, 118.5, 46.8, 104.6, 62.2, 116.1, 50.6, 101.8, 49.2, 133.8, 6.9, 127.8, 5.2]}, {"rect": [266, 456, 544, 734], "points": [0.36109, 0.05721, 0.09502, 0.0, -0.06875, 0.37465, -0.00949, 0.0, -0.10561, -0.03388, 0.36374, 0.0, -84.57267, -267.69717, -64.11356, 1.0, 68.5, 48.2, 74.3, 30.4, 68.0, 51.4, 67.0, 55.3, 66.0, 57.5, 65.6, 58.1, 65.2, 61.8, 64.6, 66.3, 63.3, 70.9, 62.2, 76.4, 34.4, 80.9, 39.4, 12.0, 61.4, 45.5, 60.1, 54.0, 52.7, 46.9, 46.3, 48.7, 53.7, 53.2, 48.1, 52.8, 34.1, 59.0, 16.4, 7.8, 30.8, 51.1, -16.7, 36.8, 37.9, 51.9, 39.7, 52.3, 60.6, 50.0, 53.2, 50.1, 47.2, 50.9, 38.8, 52.0, 41.6, 54.8, 40.3, 52.5, 48.6, 54.1, 53.7, 55.0, 59.7, 56.3, 53.4, 74.9, 55.5, 69.0, 56.9, 64.5, 58.2, 60.3, 59.5, 56.7, 48.5, 54.4, 47.0, 55.8, 45.2, 57.7, 43.4, 59.9, 42.4, 39.6, -21.5, -2.3, 44.4, 53.5, 43.0, 54.0, 66.4, 29.4, 55.3, 26.7, 47.4, -1.4, 34.8, 1.8, 38.7, 64.9, -2.5, -16.2, 10.6, -13.0, 19.4, -8.4, 34.1, -7.4, -3.1, 0.7, 51.2, 18.3, -20.5, 16.5, 4.4, 59.8, 0.3, 66.6, -14.6, -0.9, -4.8, 48.2, 31.3, 86.4, 48.9, 7.5, 40.2, 55.7, -4.0, 15.7, 41.0, 96.2, 20.6, 84.7, 11.4, 77.7, 54.0, 98.9, 72.9, 36.3, 50.6, 36.4, 64.5, 35.8, 13.3, 70.5, 21.9, 78.3, 42.8, 92.6, -9.4, 53.8, 56.3, 95.2, 30.3, 91.1, -14.5, 16.0, 53.6, 55.7, 51.8, 58.0, 50.3, 61.3, 48.6, 65.0, 45.1, 70.4, 43.5, 52.4, 42.5, 51.4, 41.2, 50.2, 35.8, 44.7, 7.6, 22.5, 44.5, 53.3, 3.0, 39.5, 39.2, 75.5, 58.6, 89.8, 60.4, 82.9, 49.3, 80.9, 26.2, 60.4, 43.7, 23.0, 31.7, 68.9, 26.5, 19.2, 35.8, 29.1, 18.3, 29.9, 45.6, 87.5, 18.3, 64.1, 26.1, 72.8, 22.9, 50.6, -3.9, 28.5, 12.3, 49.6, -12.2, 32.1, 28.5, 38.2, -13.3, -17.3, -20.1, -19.5, 79.7, 85.6, 103.8, 22.2, 75.7, 47.8, 72.6, 55.9, 81.2, 51.0, 84.3, 54.3, 77.4, 56.8, 80.6, 57.8, 88.6, 66.8, 120.7, 24.1, 94.1, 60.3, 109.2, 54.4, 86.9, 59.8, 85.5, 59.6, 74.3, 52.3, 79.4, 54.2, 82.5, 56.0, 86.1, 59.7, 83.8, 61.5, 84.7, 59.6, 78.9, 58.7, 75.7, 58.5, 71.2, 58.1, 70.0, 76.9, 70.7, 71.3, 71.5, 66.7, 71.5, 62.2, 71.1, 58.6, 78.8, 59.2, 80.1, 61.1, 81.1, 63.4, 81.6, 65.8, 92.8, 47.0, 123.4, 20.9, 81.5, 59.2, 82.8, 60.2, 80.8, 31.8, 88.1, 31.8, 100.4, 7.0, 109.6, 13.8, 83.9, 70.9, 134.5, 6.2, 128.2, 5.6, 121.3, 7.8, 110.7, 5.1, 130.8, 21.8, 93.1, 24.9, 117.0, 37.4, 101.2, 71.8, 96.1, 77.8, 129.8, 21.8, 108.6, 63.2, 78.3, 90.7, 97.3, 15.3, 84.7, 62.9, 124.8, 35.5, 65.8, 98.4, 81.4, 90.2, 87.9, 85.1, 89.0, 42.3, 80.3, 38.2, 93.0, 79.6, 85.6, 84.7, 68.7, 95.2, 102.5, 68.2, 74.2, 94.8, 123.4, 36.6, 75.6, 58.9, 76.5, 61.7, 77.0, 65.3, 76.9, 69.4, 77.6, 74.5, 83.3, 58.6, 84.7, 57.9, 86.1, 57.0, 94.5, 53.4, 118.8, 39.3, 81.5, 59.1, 112.0, 54.9, 79.2, 80.0, 70.2, 83.2, 93.1, 69.2, 96.8, 31.3, 86.2, 75.5, 110.7, 32.2, 100.9, 39.1, 111.1, 43.9, 70.4, 90.2, 95.2, 73.6, 87.1, 79.7, 99.5, 61.4, 118.8, 46.6, 104.6, 62.2, 116.5, 50.7, 101.9, 49.0, 134.4, 6.6, 128.4, 4.9]}, {"rect": [266, 457, 544, 735], "points": [0.36215, 0.05731, 0.09449, 0.0, -0.06893, 0.37577, -0.00981, 0.0, -0.10621, -0.03383, 0.36423, 0.0, -85.06472, -268.56359, -63.46453, 1.0, 69.3, 47.7, 74.6, 30.6, 68.8, 50.9, 67.6, 54.5, 66.7, 56.7, 66.1, 58.3, 65.7, 62.2, 65.1, 66.8, 63.9, 71.5, 62.2, 76.8, 34.2, 81.0, 39.2, 12.0, 61.9, 45.1, 60.7, 53.4, 52.9, 46.8, 46.2, 48.6, 53.9, 52.7, 48.1, 52.6, 33.8, 59.3, 15.9, 7.8, 30.6, 51.2, -16.8, 36.8, 37.3, 51.7, 39.0, 52.2, 61.1, 49.5, 53.4, 49.9, 47.1, 50.5, 38.2, 52.0, 41.2, 54.9, 39.9, 52.5, 48.6, 53.9, 54.0, 54.7, 60.3, 55.7, 53.2, 75.1, 55.7, 69.4, 57.0, 65.0, 58.4, 60.5, 59.7, 56.9, 48.4, 54.6, 46.7, 55.9, 44.8, 58.1, 43.0, 60.4, 42.1, 39.6, -21.9, -2.3, 44.0, 53.5, 42.7, 54.1, 66.6, 29.6, 55.3, 27.0, 47.3, -1.4, 34.6, 1.7, 38.4, 65.2, -3.0, -16.4, 10.2, -13.3, 19.0, -8.7, 33.7, -7.5, -3.8, 0.5, 51.1, 18.3, -20.9, 16.6, 4.3, 60.1, 0.2, 66.7, -15.3, -0.9, -5.2, 48.3, 31.4, 86.4, 48.8, 7.7, 39.8, 55.8, -4.7, 15.7, 41.0, 96.2, 20.7, 84.7, 11.5, 77.7, 54.0, 98.6, 73.2, 36.3, 50.4, 36.4, 64.5, 35.8, 13.1, 70.7, 21.8, 78.5, 42.9, 92.9, -9.5, 53.8, 56.6, 95.3, 30.4, 91.2, -14.9, 16.1, 53.8, 55.6, 52.0, 58.2, 50.2, 61.7, 48.8, 65.4, 44.9, 70.8, 43.1, 52.3, 42.1, 51.1, 40.8, 50.1, 35.4, 44.6, 7.1, 22.5, 44.4, 53.2, 2.6, 39.5, 38.9, 75.8, 58.6, 90.1, 60.5, 83.2, 49.3, 81.3, 25.9, 60.7, 43.5, 23.0, 31.5, 69.0, 26.1, 19.2, 35.6, 29.3, 17.8, 29.9, 45.6, 87.8, 18.1, 64.3, 25.9, 73.0, 22.4, 50.6, -4.3, 28.5, 11.8, 49.7, -12.6, 32.2, 28.3, 38.2, -13.9, -17.7, -20.5, -19.7, 79.8, 85.8, 104.3, 22.4, 76.3, 47.4, 73.5, 55.3, 81.8, 50.6, 84.7, 53.9, 77.8, 56.3, 81.0, 57.3, 88.9, 67.0, 121.2, 24.5, 94.4, 60.5, 109.5, 54.8, 86.7, 59.5, 85.3, 59.1, 75.0, 51.8, 80.0, 53.7, 82.9, 55.6, 86.1, 59.4, 83.9, 61.3, 84.8, 59.1, 79.2, 58.2, 76.1, 57.7, 71.8, 57.5, 70.1, 77.3, 71.3, 71.7, 72.1, 67.1, 72.1, 62.3, 71.6, 58.7, 79.1, 58.8, 80.1, 60.9, 81.4, 63.3, 82.0, 65.9, 93.3, 47.1, 123.8, 21.2, 81.5, 58.8, 82.9, 60.0, 81.3, 31.9, 88.3, 32.0, 100.7, 7.2, 109.9, 14.0, 83.9, 71.1, 135.1, 6.5, 128.3, 5.7, 121.4, 8.0, 110.8, 5.2, 131.4, 22.1, 93.4, 25.0, 117.3, 37.7, 101.0, 72.3, 95.9, 78.0, 130.2, 22.1, 108.7, 63.6, 78.3, 90.9, 97.5, 15.5, 84.8, 62.7, 125.4, 35.9, 65.6, 98.1, 81.2, 90.4, 87.7, 85.3, 89.3, 42.2, 80.6, 38.4, 92.7, 79.8, 85.4, 85.0, 68.7, 95.2, 102.3, 68.6, 74.2, 94.8, 123.7, 37.2, 75.8, 58.8, 76.8, 61.9, 77.3, 65.5, 77.3, 69.6, 77.9, 74.9, 83.4, 58.0, 84.8, 57.5, 86.2, 56.6, 94.9, 53.6, 119.4, 39.7, 81.6, 58.4, 112.3, 55.3, 79.3, 80.3, 70.4, 83.6, 93.1, 69.6, 97.1, 31.5, 86.2, 75.7, 111.2, 32.4, 101.2, 39.3, 111.6, 44.3, 70.5, 90.5, 95.0, 73.8, 87.1, 79.9, 99.6, 61.8, 119.1, 47.0, 104.9, 62.7, 116.8, 51.1, 102.2, 49.4, 134.7, 7.0, 128.8, 5.2]}, {"rect": [267, 458, 545, 736], "points": [0.36254, 0.05654, 0.09284, 0.0, -0.06849, 0.37636, -0.00892, 0.0, -0.10552, -0.03342, 0.36423, 0.0, -85.59972, -268.61872, -62.76742, 1.0, 69.3, 47.2, 74.2, 30.4, 68.5, 50.1, 67.6, 53.4, 66.7, 55.3, 65.7, 58.9, 65.6, 62.6, 64.8, 67.4, 63.8, 71.7, 61.8, 77.2, 34.0, 81.0, 38.7, 11.9, 61.6, 44.6, 60.6, 52.1, 52.5, 46.4, 46.0, 48.3, 53.8, 51.7, 47.9, 51.7, 33.5, 59.3, 15.6, 7.7, 30.3, 51.4, -16.8, 36.9, 36.9, 51.9, 38.7, 52.4, 61.0, 48.7, 53.0, 49.2, 46.9, 50.1, 37.8, 52.0, 40.6, 55.2, 39.3, 52.4, 48.4, 53.0, 53.9, 53.5, 60.2, 54.0, 52.9, 75.4, 55.2, 69.8, 56.6, 65.6, 58.0, 61.2, 59.3, 57.6, 47.9, 55.2, 46.1, 56.6, 44.3, 58.7, 42.4, 61.0, 41.9, 39.5, -21.9, -2.3, 43.8, 53.8, 42.4, 54.6, 66.0, 29.1, 54.8, 26.7, 46.6, -1.5, 34.1, 1.4, 38.2, 65.3, -3.3, -16.2, 9.7, -13.4, 18.8, -8.8, 33.2, -7.8, -3.9, 0.4, 50.7, 18.0, -20.9, 16.6, 4.3, 59.9, 0.2, 66.7, -15.3, -1.0, -5.0, 48.3, 31.2, 86.2, 48.4, 7.4, 39.2, 56.1, -4.7, 15.6, 40.9, 96.2, 20.6, 84.7, 11.3, 77.5, 53.8, 98.8, 72.8, 36.0, 50.1, 36.3, 64.1, 35.5, 13.1, 70.5, 21.5, 78.3, 42.7, 92.9, -9.4, 53.9, 56.2, 95.3, 30.3, 91.2, -15.0, 16.1, 53.3, 56.5, 51.5, 58.9, 49.7, 62.1, 48.3, 66.0, 44.6, 70.9, 42.8, 52.0, 41.6, 51.0, 40.5, 50.1, 35.3, 44.6, 6.8, 22.4, 43.9, 52.8, 2.6, 39.5, 38.7, 75.9, 58.4, 90.2, 60.3, 83.3, 48.9, 81.4, 25.7, 60.7, 43.2, 22.9, 31.2, 69.0, 25.8, 18.9, 35.1, 29.0, 17.8, 29.9, 45.2, 87.9, 17.9, 64.3, 25.7, 72.8, 22.4, 50.6, -4.4, 28.5, 11.8, 49.7, -12.6, 32.2, 28.0, 38.1, -14.0, -17.6, -20.5, -19.7, 79.6, 85.6, 103.7, 22.1, 76.2, 46.9, 73.5, 54.2, 81.8, 50.1, 84.6, 53.6, 77.7, 55.2, 80.9, 56.5, 88.8, 66.7, 120.6, 24.0, 94.3, 60.0, 109.1, 54.0, 86.8, 59.6, 85.4, 59.1, 74.9, 51.0, 79.9, 52.9, 82.8, 55.1, 85.9, 59.3, 83.7, 61.5, 84.5, 59.1, 79.1, 57.1, 76.2, 56.6, 72.0, 55.8, 69.9, 77.6, 71.2, 72.0, 71.7, 67.5, 71.7, 62.9, 71.2, 59.4, 78.6, 59.3, 79.9, 61.2, 81.3, 63.8, 82.2, 66.4, 93.0, 46.6, 123.7, 20.5, 81.3, 59.2, 82.7, 60.2, 80.7, 31.4, 88.0, 31.4, 100.0, 6.9, 109.5, 13.4, 83.8, 70.9, 134.5, 5.7, 128.0, 5.1, 121.1, 7.4, 110.4, 4.7, 130.8, 21.3, 92.7, 24.5, 117.2, 37.0, 100.7, 71.5, 95.7, 77.5, 129.8, 21.4, 108.3, 63.1, 77.8, 90.7, 97.2, 15.2, 84.9, 62.9, 124.8, 35.1, 65.4, 98.1, 81.0, 89.9, 87.5, 84.8, 88.9, 41.9, 80.2, 37.9, 92.5, 79.2, 85.2, 84.7, 68.5, 95.2, 102.1, 67.8, 74.1, 94.8, 123.4, 36.5, 75.4, 59.4, 76.7, 62.4, 77.2, 66.0, 77.3, 70.1, 77.7, 75.0, 83.2, 57.8, 84.9, 57.3, 86.4, 56.4, 94.8, 53.0, 118.8, 39.1, 81.4, 57.9, 111.9, 54.8, 79.1, 80.1, 70.0, 83.7, 92.9, 69.1, 96.7, 30.9, 86.1, 75.5, 110.6, 31.8, 100.9, 38.8, 111.0, 43.8, 70.1, 90.3, 94.8, 73.3, 87.0, 79.6, 99.4, 61.3, 118.7, 46.2, 104.4, 62.1, 116.4, 50.3, 101.8, 48.8, 134.4, 6.2, 128.7, 4.7]}, {"rect": [267, 459, 545, 737], "points": [0.36327, 0.05614, 0.09244, 0.0, -0.06831, 0.37664, -0.00848, 0.0, -0.10618, -0.03281, 0.3652, 0.0, -86.23432, -268.60155, -62.70771, 1.0, 69.4, 46.3, 74.4, 30.0, 68.9, 49.1, 68.0, 52.0, 67.1, 53.9, 65.5, 59.5, 65.4, 63.2, 64.6, 67.5, 63.9, 71.7, 62.0, 77.2, 34.0, 81.0, 38.6, 11.8, 61.7, 43.9, 60.7, 51.0, 52.5, 45.7, 46.0, 47.6, 53.9, 50.9, 48.2, 50.9, 33.5, 59.3, 15.5, 7.4, 30.3, 51.4, -16.9, 37.1, 36.9, 51.9, 38.7, 52.4, 61.2, 47.7, 53.3, 48.5, 47.0, 49.4, 37.8, 52.0, 40.5, 55.5, 39.5, 52.4, 48.7, 52.2, 54.2, 52.4, 60.6, 52.8, 53.1, 75.7, 55.3, 69.8, 56.6, 66.0, 58.0, 61.7, 59.1, 58.5, 47.9, 55.8, 46.1, 57.1, 44.2, 59.1, 42.4, 61.0, 42.1, 39.4, -22.2, -2.1, 43.8, 54.1, 42.3, 54.9, 66.2, 29.0, 54.8, 26.4, 46.8, -1.8, 34.0, 1.3, 38.1, 65.3, -3.4, -16.3, 9.6, -13.4, 18.7, -8.9, 33.4, -7.9, -4.2, 0.4, 50.6, 17.9, -21.0, 16.8, 4.1, 59.8, -0.1, 66.7, -15.4, -1.0, -5.2, 48.3, 31.2, 86.1, 48.3, 7.3, 39.2, 56.4, -4.8, 15.6, 40.9, 96.1, 20.6, 84.7, 11.4, 77.7, 54.1, 98.6, 73.0, 35.9, 50.1, 36.2, 64.3, 35.4, 13.1, 70.4, 21.6, 78.3, 42.7, 92.6, -9.4, 54.1, 56.4, 95.3, 30.3, 91.1, -15.3, 16.1, 53.1, 57.2, 51.2, 59.5, 49.7, 62.7, 48.0, 66.1, 44.5, 71.1, 42.9, 51.6, 41.8, 50.7, 40.5, 49.7, 35.3, 44.5, 6.7, 22.2, 44.1, 52.2, 2.6, 39.5, 38.9, 75.9, 58.7, 90.1, 60.5, 83.3, 49.1, 81.4, 25.7, 60.6, 43.2, 22.6, 31.1, 69.0, 26.0, 18.8, 35.3, 29.0, 17.7, 29.8, 45.4, 87.8, 17.9, 64.0, 25.7, 72.7, 22.4, 50.6, -4.7, 28.5, 11.8, 49.7, -12.7, 32.2, 28.0, 37.8, -14.3, -17.6, -20.8, -19.6, 79.8, 85.3, 104.0, 21.8, 76.4, 46.2, 73.6, 52.9, 81.9, 49.4, 84.7, 52.7, 78.1, 54.2, 81.0, 55.5, 89.1, 66.4, 120.7, 23.6, 94.6, 59.8, 109.1, 53.7, 86.6, 59.0, 85.2, 58.6, 75.3, 50.0, 80.1, 51.9, 83.1, 54.2, 85.7, 58.9, 83.8, 61.2, 84.3, 58.5, 79.2, 56.1, 76.4, 55.2, 72.2, 54.4, 70.2, 77.7, 71.4, 71.8, 71.8, 67.6, 71.8, 63.3, 71.0, 60.0, 78.4, 59.6, 79.7, 61.4, 81.1, 63.7, 82.3, 66.2, 93.3, 46.5, 123.8, 20.4, 81.0, 58.9, 82.5, 60.1, 81.2, 31.3, 88.2, 31.3, 100.3, 6.6, 109.6, 13.1, 84.1, 70.9, 134.6, 5.6, 128.0, 4.7, 121.1, 7.1, 110.4, 4.3, 130.9, 20.9, 93.2, 24.4, 117.0, 36.7, 100.8, 71.2, 95.7, 77.1, 129.9, 21.3, 108.5, 62.8, 78.0, 90.4, 97.4, 14.8, 84.8, 62.5, 124.8, 34.7, 65.6, 98.0, 81.2, 89.8, 87.7, 84.5, 89.4, 41.6, 80.7, 37.7, 92.7, 78.9, 85.4, 84.4, 68.8, 95.0, 102.1, 67.5, 74.3, 94.5, 123.4, 36.2, 75.4, 59.9, 76.5, 62.4, 77.3, 66.1, 77.6, 69.9, 78.0, 75.0, 83.2, 56.9, 84.8, 56.4, 86.5, 55.8, 95.1, 52.6, 118.8, 38.5, 81.4, 57.2, 111.9, 54.2, 79.1, 80.1, 70.3, 83.4, 93.2, 68.7, 97.0, 30.5, 86.4, 75.2, 110.9, 31.5, 101.1, 38.7, 111.3, 43.4, 70.3, 90.2, 95.0, 72.9, 87.2, 79.3, 99.6, 60.9, 118.8, 45.9, 104.5, 61.6, 116.4, 50.0, 102.1, 48.5, 134.5, 6.1, 128.5, 4.6]}, {"rect": [267, 459, 545, 737], "points": [0.36395, 0.05622, 0.09183, 0.0, -0.06829, 0.37708, -0.00824, 0.0, -0.10662, -0.03256, 0.36577, 0.0, -86.78181, -268.79377, -62.38367, 1.0, 69.3, 46.2, 74.2, 30.6, 68.9, 49.0, 67.9, 51.8, 67.0, 53.7, 65.6, 59.8, 65.2, 63.5, 64.7, 67.7, 63.8, 71.9, 61.8, 77.6, 33.7, 81.4, 38.4, 11.9, 61.5, 43.9, 60.9, 50.9, 52.6, 45.7, 46.0, 47.9, 53.9, 50.8, 48.0, 51.2, 33.2, 59.7, 15.0, 7.7, 30.0, 51.4, -17.6, 37.3, 37.2, 52.1, 38.7, 52.6, 61.1, 47.6, 53.1, 48.5, 47.0, 49.4, 38.1, 52.4, 40.6, 55.7, 39.6, 52.6, 48.8, 52.2, 54.4, 52.2, 60.5, 52.6, 52.7, 75.9, 55.4, 70.0, 56.5, 66.3, 57.8, 61.8, 59.1, 58.9, 47.9, 56.1, 46.1, 57.2, 44.2, 59.1, 42.4, 61.2, 41.6, 39.6, -22.7, -2.1, 44.1, 54.4, 42.4, 54.9, 66.2, 29.3, 54.8, 26.9, 46.6, -1.5, 33.8, 1.7, 37.9, 65.7, -3.9, -16.2, 9.0, -13.3, 18.2, -8.8, 32.8, -7.8, -4.4, 0.5, 50.6, 18.2, -21.7, 17.0, 3.6, 60.2, -0.6, 67.1, -15.9, -0.9, -5.7, 48.7, 30.9, 86.5, 48.3, 7.6, 39.2, 56.6, -5.3, 16.0, 40.7, 96.5, 20.1, 85.1, 10.9, 78.1, 53.6, 98.9, 72.8, 36.2, 49.9, 36.3, 64.1, 35.7, 12.7, 70.8, 21.4, 78.7, 42.5, 93.2, -9.9, 54.3, 55.9, 95.7, 30.1, 91.5, -15.8, 16.5, 53.1, 57.5, 51.3, 59.8, 49.5, 62.7, 48.0, 66.3, 44.3, 71.3, 43.2, 51.7, 41.9, 50.8, 40.6, 49.8, 34.8, 44.6, 6.2, 22.5, 44.2, 52.5, 2.1, 39.6, 38.4, 76.2, 58.2, 90.5, 60.1, 83.7, 48.8, 81.8, 25.5, 60.8, 42.9, 22.9, 30.7, 69.3, 25.5, 19.2, 35.0, 29.3, 17.2, 30.2, 45.2, 88.2, 17.7, 64.4, 25.5, 73.1, 21.9, 50.9, -5.2, 28.9, 11.3, 50.1, -13.4, 32.6, 27.7, 38.1, -14.6, -17.5, -21.4, -19.6, 79.4, 85.9, 104.0, 22.3, 76.2, 46.2, 73.8, 52.7, 82.0, 49.4, 84.8, 52.7, 78.0, 54.0, 81.1, 55.5, 88.7, 66.9, 120.7, 24.2, 94.2, 60.1, 108.9, 54.5, 86.6, 59.1, 84.9, 58.6, 75.3, 49.9, 80.2, 52.0, 83.0, 54.4, 85.7, 59.0, 83.8, 61.3, 84.3, 58.6, 79.2, 56.2, 76.5, 55.0, 72.4, 54.4, 69.7, 78.1, 71.5, 72.2, 71.9, 68.0, 71.6, 63.5, 71.1, 60.3, 78.4, 59.6, 79.8, 61.4, 81.2, 63.7, 82.1, 66.3, 93.1, 46.8, 123.6, 20.9, 80.8, 59.0, 82.4, 60.0, 81.0, 31.6, 88.0, 31.6, 100.3, 7.1, 109.6, 13.6, 83.9, 71.2, 134.8, 6.2, 128.1, 5.0, 121.1, 7.6, 110.2, 4.9, 131.2, 21.5, 93.0, 24.7, 116.8, 37.5, 100.5, 72.0, 95.5, 78.0, 129.9, 21.9, 108.3, 63.3, 77.6, 91.0, 97.2, 15.1, 84.8, 62.6, 124.9, 35.3, 65.1, 98.4, 80.8, 90.2, 87.2, 85.4, 89.0, 42.1, 80.6, 38.0, 92.3, 79.5, 84.9, 85.0, 68.3, 95.5, 101.9, 68.3, 73.8, 95.1, 123.5, 37.0, 75.2, 60.0, 76.6, 62.7, 77.4, 66.3, 77.5, 70.1, 77.6, 75.3, 83.0, 57.1, 84.8, 56.7, 86.5, 55.8, 94.9, 53.1, 118.9, 39.3, 81.2, 57.2, 112.0, 55.0, 78.9, 80.4, 70.1, 84.0, 92.8, 69.3, 96.8, 31.1, 86.2, 75.8, 110.9, 32.0, 100.9, 39.0, 111.1, 44.0, 70.1, 90.6, 94.6, 73.5, 86.8, 79.9, 99.2, 61.4, 118.9, 46.7, 104.2, 62.3, 116.2, 50.8, 101.9, 49.0, 134.6, 6.7, 128.6, 5.0]}, {"rect": [267, 459, 545, 737], "points": [0.3644, 0.05591, 0.09133, 0.0, -0.06784, 0.37704, -0.00649, 0.0, -0.10626, -0.03206, 0.36673, 0.0, -87.26302, -268.46925, -62.97097, 1.0, 69.9, 46.5, 74.4, 30.4, 69.4, 49.2, 68.5, 52.0, 67.6, 53.8, 65.9, 60.3, 65.8, 63.9, 65.2, 68.1, 64.3, 72.2, 62.0, 77.5, 33.9, 81.5, 38.6, 12.0, 62.1, 44.2, 61.2, 51.1, 52.9, 46.0, 46.1, 48.2, 54.3, 51.0, 48.3, 51.5, 33.2, 59.5, 15.1, 7.8, 30.0, 51.3, -17.1, 37.6, 37.3, 52.5, 38.7, 52.9, 61.6, 47.9, 53.4, 48.7, 47.3, 49.7, 37.9, 52.8, 40.6, 56.1, 39.6, 52.9, 49.2, 52.5, 54.7, 52.4, 60.8, 52.6, 52.8, 76.1, 55.7, 70.4, 57.0, 66.7, 58.3, 62.4, 59.4, 59.4, 47.9, 56.6, 46.5, 57.8, 44.3, 59.7, 42.5, 61.6, 41.8, 39.6, -22.3, -1.6, 44.2, 55.1, 42.4, 55.6, 66.2, 29.2, 54.8, 26.8, 46.5, -1.4, 34.0, 1.5, 38.1, 65.6, -3.7, -16.1, 9.2, -13.0, 18.4, -8.7, 32.8, -7.5, -4.3, 0.8, 50.7, 18.1, -21.3, 17.4, 4.0, 60.4, -0.1, 67.3, -15.7, -0.5, -5.2, 48.8, 30.9, 86.6, 48.3, 7.5, 39.2, 57.0, -5.1, 16.1, 40.9, 96.4, 20.6, 85.3, 11.4, 78.3, 53.8, 99.1, 72.8, 36.1, 50.1, 36.4, 64.0, 35.5, 12.9, 71.0, 21.6, 78.8, 42.7, 93.1, -9.7, 54.7, 56.1, 95.8, 30.3, 91.7, -15.7, 16.6, 53.3, 58.0, 51.6, 60.2, 49.8, 63.4, 48.3, 66.7, 44.3, 71.5, 43.2, 52.0, 41.9, 51.1, 40.9, 50.2, 35.0, 44.7, 6.4, 22.6, 44.2, 52.6, 2.2, 39.7, 38.6, 76.1, 58.4, 90.4, 60.3, 83.8, 48.8, 81.7, 25.7, 60.9, 43.2, 23.0, 30.9, 69.2, 25.7, 19.0, 35.0, 29.2, 17.4, 30.1, 45.2, 88.1, 17.9, 64.5, 25.7, 73.3, 22.1, 50.8, -4.8, 29.0, 11.8, 50.2, -13.0, 32.7, 27.7, 37.9, -14.4, -17.2, -21.2, -19.1, 79.6, 85.8, 104.0, 22.1, 76.8, 46.4, 74.1, 52.9, 82.4, 49.7, 85.1, 53.0, 78.6, 54.0, 81.4, 55.7, 89.1, 66.6, 121.0, 24.0, 94.6, 59.9, 109.1, 54.4, 86.6, 59.4, 85.1, 58.9, 75.9, 49.9, 80.5, 52.1, 83.3, 54.4, 86.0, 59.1, 83.8, 61.6, 84.3, 58.9, 79.5, 56.2, 76.8, 55.2, 72.7, 54.4, 69.9, 78.0, 71.8, 72.3, 72.2, 68.2, 72.2, 64.0, 71.4, 60.8, 78.7, 60.2, 80.1, 61.8, 81.4, 64.0, 82.4, 66.4, 93.3, 46.7, 123.9, 20.8, 81.0, 59.4, 82.4, 60.4, 81.0, 31.5, 88.3, 31.5, 100.4, 7.0, 109.9, 13.5, 84.1, 71.1, 134.9, 6.0, 128.3, 5.1, 121.4, 7.5, 110.4, 5.0, 131.2, 21.3, 93.0, 24.6, 117.3, 37.4, 100.8, 71.9, 95.7, 77.9, 130.3, 21.7, 108.6, 63.2, 77.8, 90.9, 97.2, 15.2, 85.1, 62.8, 125.2, 35.1, 65.3, 98.5, 80.9, 90.3, 87.4, 85.3, 89.3, 42.0, 80.6, 37.9, 92.5, 79.4, 85.2, 84.9, 68.5, 95.5, 102.2, 68.3, 74.0, 95.0, 123.8, 36.9, 75.5, 60.6, 76.8, 63.1, 77.7, 66.4, 77.8, 70.4, 77.8, 75.2, 83.3, 57.2, 85.1, 56.7, 86.6, 56.1, 95.2, 52.7, 119.2, 39.2, 81.5, 57.5, 112.3, 54.9, 79.1, 80.3, 70.3, 84.0, 93.0, 69.1, 97.1, 30.9, 86.4, 75.6, 111.0, 31.9, 101.2, 38.9, 111.4, 43.8, 70.3, 90.7, 94.8, 73.4, 87.0, 79.7, 99.4, 61.0, 119.2, 46.6, 104.5, 62.2, 116.5, 50.7, 102.1, 48.6, 134.9, 6.5, 128.9, 5.1]}, {"rect": [268, 460, 546, 738], "points": [0.36486, 0.05597, 0.09117, 0.0, -0.06766, 0.37731, -0.00579, 0.0, -0.10635, -0.03216, 0.36724, 0.0, -87.85066, -268.78911, -63.22776, 1.0, 69.5, 46.1, 73.8, 30.0, 69.1, 48.9, 68.2, 51.6, 67.2, 53.2, 65.7, 60.3, 65.4, 63.6, 64.9, 67.8, 64.0, 71.8, 61.3, 77.4, 33.2, 81.1, 37.9, 11.6, 61.7, 43.8, 60.8, 50.7, 52.5, 45.6, 45.7, 47.9, 53.9, 50.7, 47.9, 51.1, 32.7, 59.3, 14.4, 7.4, 29.5, 51.1, -17.8, 37.2, 36.8, 52.4, 38.3, 52.8, 61.2, 47.5, 53.3, 48.3, 46.9, 49.6, 37.7, 52.5, 40.4, 56.0, 39.2, 52.8, 48.8, 52.1, 54.4, 52.0, 60.7, 52.1, 52.1, 76.0, 55.3, 70.0, 56.6, 66.3, 58.0, 62.1, 59.0, 59.3, 47.5, 56.3, 46.1, 57.5, 44.1, 59.4, 42.3, 61.2, 41.1, 39.2, -23.0, -2.0, 43.7, 54.7, 42.0, 55.2, 65.5, 29.0, 54.4, 26.4, 46.1, -1.8, 33.3, 1.3, 37.4, 65.4, -4.2, -16.3, 8.8, -13.4, 17.7, -8.8, 32.3, -7.9, -5.0, 0.4, 50.2, 18.0, -22.0, 17.0, 3.4, 60.2, -0.8, 67.1, -16.4, -0.7, -5.9, 48.7, 30.4, 86.5, 47.6, 7.3, 38.8, 56.6, -5.8, 15.7, 40.4, 96.3, 19.9, 85.2, 10.7, 78.2, 53.3, 99.0, 72.3, 35.9, 49.4, 36.0, 63.6, 35.1, 12.4, 70.9, 21.2, 78.7, 42.0, 93.0, -10.1, 54.3, 55.6, 95.8, 29.6, 91.5, -16.1, 16.4, 52.9, 57.9, 51.4, 59.9, 49.6, 63.1, 47.9, 66.3, 43.8, 71.4, 42.8, 51.9, 41.5, 51.0, 40.5, 50.1, 34.5, 44.3, 6.0, 22.4, 43.8, 52.4, 1.6, 39.5, 37.9, 76.0, 57.9, 90.3, 59.8, 83.5, 48.3, 81.5, 25.0, 60.7, 42.5, 22.6, 30.4, 69.1, 25.0, 18.8, 34.6, 29.0, 16.7, 29.9, 44.7, 88.0, 17.5, 64.4, 25.0, 73.2, 21.7, 50.6, -5.5, 28.9, 11.1, 49.8, -13.7, 32.6, 27.2, 37.8, -15.1, -17.6, -21.7, -19.5, 79.1, 85.7, 103.6, 21.7, 76.5, 46.1, 74.0, 52.6, 82.0, 49.3, 84.8, 52.8, 78.2, 53.8, 81.0, 55.3, 88.5, 66.4, 120.6, 23.6, 94.0, 59.6, 108.7, 54.3, 86.2, 59.0, 84.7, 58.8, 75.5, 49.7, 80.2, 51.7, 82.9, 54.2, 85.3, 58.9, 83.4, 61.3, 83.8, 58.5, 78.9, 55.8, 76.4, 54.9, 72.3, 54.0, 69.5, 77.9, 71.7, 71.9, 71.9, 68.1, 71.8, 63.9, 71.2, 60.7, 78.3, 59.9, 79.7, 61.7, 81.0, 63.9, 82.0, 66.3, 92.6, 46.5, 123.5, 20.7, 80.6, 59.3, 82.0, 60.2, 80.6, 31.3, 87.6, 31.3, 99.9, 6.6, 109.3, 13.3, 83.4, 71.0, 134.5, 5.7, 127.6, 5.0, 120.7, 7.4, 109.7, 4.6, 130.8, 21.2, 92.6, 24.4, 117.0, 37.2, 100.4, 71.8, 95.3, 77.5, 129.9, 21.6, 108.2, 63.1, 77.3, 90.8, 96.7, 14.8, 84.7, 62.6, 124.8, 35.0, 64.9, 98.2, 80.2, 90.2, 87.0, 85.2, 88.8, 41.6, 80.1, 37.5, 92.1, 79.2, 84.7, 84.8, 67.8, 95.3, 101.8, 68.2, 73.3, 94.8, 123.4, 36.5, 75.1, 60.4, 76.4, 63.0, 77.3, 66.3, 77.7, 70.0, 77.3, 75.1, 82.9, 57.0, 84.7, 56.5, 86.2, 55.8, 94.5, 52.6, 118.8, 38.8, 81.0, 57.1, 111.8, 54.8, 78.7, 80.2, 69.6, 83.9, 92.5, 68.8, 96.6, 30.6, 85.7, 75.5, 110.5, 31.8, 100.5, 38.7, 111.0, 43.4, 69.6, 90.4, 94.4, 73.2, 86.6, 79.4, 99.0, 60.9, 118.7, 46.2, 104.1, 61.8, 116.1, 50.6, 101.7, 48.4, 134.5, 6.4, 128.6, 4.9]}, {"rect": [268, 460, 546, 738], "points": [0.36518, 0.05616, 0.09072, 0.0, -0.06765, 0.37768, -0.0052, 0.0, -0.10618, -0.03292, 0.36731, 0.0, -88.01029, -269.17347, -63.22253, 1.0, 69.8, 46.4, 73.8, 30.4, 69.4, 49.2, 68.4, 52.0, 67.5, 53.8, 65.8, 60.7, 65.7, 64.0, 65.0, 68.1, 64.0, 71.9, 61.4, 77.7, 33.2, 81.4, 38.1, 11.9, 62.0, 44.2, 61.1, 51.1, 52.8, 46.0, 45.9, 48.0, 53.9, 50.8, 48.2, 51.2, 32.7, 59.4, 14.6, 7.4, 29.5, 51.1, -17.6, 37.2, 36.8, 52.4, 38.6, 52.9, 61.5, 47.8, 53.3, 48.4, 47.0, 49.7, 37.7, 52.8, 40.5, 56.1, 39.5, 52.9, 48.8, 52.4, 54.6, 52.1, 60.7, 52.5, 52.1, 76.3, 55.6, 70.1, 56.9, 66.4, 58.0, 62.3, 59.3, 59.4, 47.8, 56.6, 46.4, 57.6, 44.1, 59.5, 42.4, 61.3, 41.1, 39.5, -23.0, -2.2, 43.7, 54.9, 42.2, 55.3, 65.5, 29.4, 54.4, 26.7, 46.1, -1.5, 33.5, 1.4, 37.4, 65.7, -4.2, -16.4, 9.0, -13.3, 17.9, -8.8, 32.3, -7.8, -5.1, 0.5, 50.2, 18.3, -21.7, 17.0, 3.6, 60.3, -0.6, 67.2, -16.2, -0.8, -5.9, 48.7, 30.4, 86.9, 47.8, 7.4, 39.0, 56.7, -5.6, 15.7, 40.2, 96.6, 20.1, 85.5, 10.9, 78.2, 53.1, 99.3, 72.4, 36.2, 49.4, 36.3, 63.6, 35.4, 12.5, 71.2, 21.2, 79.0, 42.0, 93.4, -10.2, 54.6, 55.4, 96.1, 29.8, 91.6, -16.1, 16.2, 53.0, 58.1, 51.5, 60.0, 49.6, 63.1, 48.2, 66.4, 43.8, 71.7, 42.8, 52.0, 41.8, 51.1, 40.5, 50.1, 34.6, 44.6, 6.0, 22.5, 44.1, 52.5, 1.7, 39.6, 37.8, 76.3, 57.7, 90.9, 59.6, 84.0, 48.1, 81.9, 24.9, 60.8, 42.5, 23.0, 30.4, 69.4, 25.2, 18.9, 34.6, 29.3, 16.6, 30.0, 44.7, 88.3, 17.4, 64.4, 24.9, 73.5, 21.7, 50.6, -5.5, 29.0, 11.1, 50.1, -13.4, 32.6, 27.2, 38.1, -14.9, -17.7, -21.7, -19.7, 78.9, 86.3, 103.6, 22.0, 76.8, 46.2, 74.1, 52.9, 82.3, 49.7, 85.1, 52.9, 78.3, 54.0, 81.1, 55.6, 88.5, 66.9, 120.6, 24.1, 94.0, 60.1, 109.0, 54.8, 86.5, 59.3, 84.8, 58.9, 75.8, 49.8, 80.5, 52.0, 83.2, 54.3, 85.6, 59.2, 83.4, 61.6, 83.9, 58.8, 79.2, 56.1, 76.5, 55.2, 72.6, 54.3, 69.2, 78.5, 71.7, 72.2, 72.2, 68.2, 71.9, 64.1, 71.3, 61.1, 78.4, 60.2, 79.7, 62.0, 81.1, 64.0, 82.0, 66.6, 92.7, 46.8, 124.1, 20.9, 80.6, 59.4, 82.1, 60.3, 80.3, 31.6, 87.6, 31.6, 100.0, 6.9, 109.5, 13.7, 83.5, 71.6, 134.8, 6.1, 127.7, 5.3, 120.8, 7.7, 109.8, 4.9, 131.1, 21.7, 92.6, 24.7, 117.2, 37.5, 100.4, 72.4, 95.3, 78.2, 130.2, 21.8, 108.2, 63.6, 77.1, 91.3, 96.8, 15.1, 84.8, 62.9, 125.1, 35.6, 64.7, 98.8, 80.2, 90.5, 86.8, 85.7, 88.6, 42.2, 79.9, 38.0, 92.1, 79.8, 84.8, 85.3, 67.8, 95.7, 102.1, 68.7, 73.3, 95.1, 123.7, 36.9, 75.4, 60.7, 76.5, 63.1, 77.4, 66.6, 77.8, 70.3, 77.1, 75.7, 83.0, 57.1, 84.7, 56.6, 86.5, 56.1, 94.5, 53.1, 119.1, 39.3, 81.1, 57.4, 111.9, 55.3, 78.5, 80.8, 69.6, 84.5, 92.3, 69.3, 96.4, 31.1, 85.8, 75.8, 110.5, 32.1, 100.5, 39.3, 111.0, 43.9, 69.6, 90.9, 94.5, 73.8, 86.6, 79.9, 99.0, 61.4, 118.8, 46.9, 104.1, 62.3, 116.3, 51.1, 101.5, 48.9, 134.8, 6.7, 129.1, 4.9]}, {"rect": [268, 460, 546, 738], "points": [0.36568, 0.05574, 0.09119, 0.0, -0.06739, 0.37725, -0.00281, 0.0, -0.10694, -0.03383, 0.36772, 0.0, -88.55811, -268.80258, -65.04141, 1.0, 69.9, 46.6, 74.1, 30.5, 69.4, 49.3, 68.5, 52.1, 67.6, 53.9, 66.1, 61.0, 65.7, 64.3, 65.2, 68.5, 64.3, 72.2, 61.6, 77.9, 33.5, 81.5, 38.1, 12.0, 62.1, 44.5, 61.1, 51.2, 52.8, 46.1, 45.9, 48.3, 54.1, 51.1, 48.2, 51.5, 33.0, 59.5, 14.6, 7.7, 29.7, 51.2, -17.6, 37.2, 36.8, 52.5, 38.6, 52.9, 61.6, 47.9, 53.3, 48.8, 47.0, 49.8, 37.7, 52.8, 40.5, 56.2, 39.5, 52.9, 48.8, 52.5, 54.7, 52.5, 61.0, 52.7, 52.4, 76.5, 55.6, 70.4, 57.0, 66.7, 58.3, 62.6, 59.3, 59.7, 47.8, 56.9, 46.4, 57.9, 44.1, 59.8, 42.6, 61.6, 41.3, 39.6, -23.0, -2.0, 43.8, 55.1, 42.3, 55.6, 65.8, 29.5, 54.6, 26.7, 46.3, -1.4, 33.6, 1.8, 37.6, 65.8, -4.2, -16.2, 9.0, -13.0, 18.1, -8.8, 32.6, -7.7, -5.1, 0.8, 50.4, 18.2, -21.7, 16.9, 3.6, 60.3, -0.5, 67.2, -16.5, -0.6, -5.7, 48.7, 30.7, 87.0, 47.8, 7.5, 39.0, 56.9, -5.6, 15.9, 40.4, 96.7, 20.2, 85.5, 10.9, 78.2, 53.4, 99.4, 72.7, 36.1, 49.6, 36.4, 63.9, 35.6, 12.7, 71.0, 21.2, 79.1, 42.2, 93.5, -10.2, 54.3, 55.7, 96.2, 29.8, 91.9, -16.2, 16.4, 53.2, 58.4, 51.5, 60.3, 49.7, 63.4, 48.3, 66.7, 44.0, 71.8, 42.8, 52.0, 41.8, 51.1, 40.5, 50.2, 34.8, 44.7, 5.9, 22.5, 44.1, 52.6, 1.7, 39.6, 38.1, 76.4, 58.0, 90.8, 59.8, 83.9, 48.3, 82.0, 25.2, 60.8, 42.7, 23.0, 30.6, 69.5, 25.2, 19.3, 34.8, 29.2, 16.8, 30.3, 45.0, 88.5, 17.4, 64.5, 25.2, 73.6, 21.9, 50.7, -5.6, 29.0, 11.3, 50.1, -13.4, 32.6, 27.4, 38.2, -15.1, -17.3, -22.0, -19.5, 79.2, 86.2, 103.7, 21.9, 76.9, 46.5, 74.4, 53.0, 82.4, 49.8, 85.2, 53.0, 78.3, 54.3, 81.1, 55.8, 88.6, 66.6, 120.7, 23.7, 94.1, 59.7, 109.0, 54.4, 86.6, 59.3, 84.9, 59.0, 75.9, 50.2, 80.5, 52.1, 83.3, 54.4, 85.7, 59.0, 83.7, 61.7, 84.2, 58.9, 79.3, 56.2, 76.7, 55.3, 72.7, 54.5, 69.5, 78.4, 71.8, 72.3, 72.2, 68.5, 72.2, 64.4, 71.4, 61.2, 78.7, 60.3, 80.1, 62.1, 81.4, 64.3, 82.4, 66.7, 92.7, 46.7, 124.1, 20.4, 80.7, 59.7, 82.4, 60.6, 80.6, 31.5, 88.0, 31.5, 100.0, 6.9, 109.6, 13.5, 83.8, 71.5, 134.8, 5.7, 127.9, 5.2, 120.9, 7.5, 110.1, 4.7, 131.1, 21.3, 92.7, 24.6, 117.3, 37.0, 100.7, 71.9, 95.5, 77.6, 130.2, 21.4, 108.2, 63.2, 77.4, 91.2, 96.8, 14.9, 84.9, 63.0, 125.2, 35.2, 65.0, 98.6, 80.5, 90.3, 87.3, 85.3, 88.9, 42.0, 80.2, 37.9, 92.1, 79.4, 85.0, 84.9, 68.1, 95.8, 102.1, 68.2, 73.6, 95.0, 123.7, 36.5, 75.5, 61.1, 76.8, 63.4, 77.7, 66.7, 77.8, 70.4, 77.4, 75.6, 83.3, 57.2, 84.8, 56.7, 86.6, 56.2, 94.6, 52.8, 119.2, 38.9, 81.4, 57.5, 111.9, 54.6, 78.7, 80.7, 69.9, 84.3, 92.6, 69.2, 96.7, 31.0, 86.1, 75.7, 110.6, 31.9, 100.8, 38.9, 111.1, 43.6, 69.9, 90.8, 94.8, 73.4, 86.7, 79.8, 99.1, 61.0, 118.8, 46.3, 104.4, 61.9, 116.4, 50.4, 101.8, 48.6, 134.8, 6.2, 129.2, 4.7]}, {"rect": [268, 461, 546, 739], "points": [0.366, 0.05603, 0.0908, 0.0, -0.06757, 0.37723, -0.00337, 0.0, -0.10796, -0.03508, 0.3668, 0.0, -88.79992, -269.28759, -64.35583, 1.0, 69.7, 46.4, 74.1, 30.4, 69.2, 49.2, 68.2, 52.1, 67.3, 53.9, 65.9, 60.6, 65.6, 63.9, 65.1, 68.1, 64.1, 71.8, 61.7, 77.8, 33.2, 81.2, 37.8, 11.6, 61.9, 44.2, 60.9, 51.1, 52.6, 45.9, 45.7, 47.9, 53.9, 51.0, 48.0, 51.2, 32.8, 59.4, 14.4, 7.1, 29.5, 51.1, -17.6, 36.3, 36.9, 52.0, 38.7, 52.2, 61.3, 47.8, 53.1, 48.4, 47.0, 49.4, 37.8, 52.1, 40.5, 55.7, 39.3, 52.5, 48.8, 52.1, 54.4, 52.4, 60.6, 52.9, 52.5, 76.3, 55.4, 70.0, 56.8, 66.3, 58.1, 62.4, 59.1, 59.3, 47.6, 56.5, 46.2, 57.5, 43.9, 59.3, 42.5, 61.2, 41.3, 39.3, -22.7, -2.9, 43.8, 54.7, 42.1, 55.1, 65.8, 29.2, 54.4, 26.4, 46.1, -2.0, 33.5, 1.2, 37.4, 65.5, -4.2, -16.8, 8.7, -13.7, 17.9, -9.2, 32.6, -8.0, -5.1, -0.1, 50.2, 18.0, -21.7, 16.0, 3.6, 59.9, -0.5, 66.5, -16.3, -1.5, -5.7, 48.1, 30.5, 86.6, 47.8, 7.1, 38.8, 56.3, -5.6, 15.1, 40.3, 96.3, 19.9, 84.9, 10.7, 77.5, 53.5, 99.1, 72.7, 36.0, 49.6, 36.1, 63.9, 35.5, 12.5, 70.6, 21.1, 78.5, 42.1, 93.1, -10.2, 53.6, 55.8, 95.8, 29.6, 91.3, -16.2, 15.5, 53.0, 57.9, 51.3, 60.1, 49.5, 63.0, 48.1, 66.3, 43.8, 71.4, 42.9, 51.6, 41.6, 50.7, 40.5, 49.7, 34.5, 44.3, 5.9, 21.9, 43.9, 52.4, 1.7, 39.2, 37.8, 76.0, 58.1, 90.7, 59.9, 83.8, 48.4, 81.9, 24.9, 60.5, 42.7, 22.7, 30.4, 69.1, 25.0, 18.7, 34.5, 29.1, 16.6, 29.7, 44.8, 88.3, 17.2, 64.1, 25.0, 73.2, 21.6, 50.3, -5.6, 28.3, 11.1, 49.5, -13.4, 31.7, 27.2, 37.9, -14.9, -18.2, -21.8, -20.4, 79.3, 86.0, 104.0, 21.7, 76.9, 46.4, 74.2, 52.9, 82.4, 49.6, 85.3, 52.9, 78.4, 54.2, 81.4, 55.6, 88.9, 66.6, 120.9, 23.5, 94.4, 59.8, 108.8, 53.8, 87.0, 58.9, 85.2, 58.8, 75.7, 50.1, 80.6, 52.0, 83.4, 54.3, 86.0, 58.8, 83.9, 61.5, 84.3, 58.5, 79.5, 56.1, 76.6, 55.2, 72.7, 54.6, 69.6, 78.2, 71.6, 71.9, 72.0, 68.1, 72.0, 64.2, 71.5, 61.0, 78.8, 60.1, 80.2, 61.6, 81.5, 63.9, 82.5, 66.2, 93.3, 46.5, 123.9, 19.9, 81.0, 59.3, 82.5, 60.2, 80.9, 31.4, 88.3, 31.3, 100.3, 6.6, 109.9, 13.3, 83.9, 71.3, 134.8, 5.5, 128.0, 4.9, 121.4, 7.3, 110.4, 4.5, 131.1, 21.1, 93.0, 24.4, 117.0, 36.4, 100.5, 71.4, 95.1, 77.2, 130.2, 21.1, 108.2, 62.7, 77.5, 90.8, 97.3, 14.8, 85.2, 62.5, 125.1, 34.9, 65.1, 98.5, 80.6, 89.9, 87.1, 84.8, 89.2, 41.9, 80.5, 37.8, 92.2, 79.1, 84.9, 84.7, 68.2, 95.7, 101.8, 67.6, 73.7, 94.8, 123.5, 36.0, 75.6, 60.6, 76.9, 63.0, 77.5, 66.3, 77.9, 70.0, 77.7, 75.5, 83.3, 57.0, 85.1, 56.5, 86.6, 56.0, 95.1, 52.8, 119.2, 38.7, 81.5, 57.1, 111.9, 54.3, 78.8, 80.5, 70.0, 84.2, 92.9, 69.0, 97.0, 30.8, 86.2, 75.5, 110.9, 31.8, 101.2, 38.7, 111.3, 43.6, 70.0, 90.7, 94.9, 73.2, 87.0, 79.6, 99.5, 60.8, 118.8, 46.0, 104.5, 61.7, 116.1, 50.1, 102.1, 48.4, 134.8, 6.0, 128.9, 4.2]}, {"rect": [269, 461, 547, 739], "points": [0.36647, 0.05556, 0.08985, 0.0, -0.06702, 0.37655, -0.00295, 0.0, -0.10873, -0.03612, 0.36468, 0.0, -89.7531, -268.67973, -63.90657, 1.0, 69.4, 46.5, 73.7, 30.9, 68.7, 49.3, 67.8, 52.4, 66.9, 54.3, 65.5, 60.4, 65.3, 63.9, 64.8, 68.1, 63.9, 72.1, 61.3, 78.0, 32.8, 81.7, 37.4, 12.1, 61.6, 44.3, 60.4, 51.4, 52.1, 46.0, 45.3, 47.9, 53.4, 51.1, 47.6, 51.5, 32.3, 59.6, 13.9, 7.6, 28.8, 51.4, -18.3, 36.7, 36.4, 52.0, 38.3, 52.4, 60.8, 47.9, 52.9, 48.7, 46.5, 49.6, 37.4, 52.1, 40.1, 55.7, 39.1, 52.5, 48.4, 52.4, 53.9, 52.5, 60.3, 53.3, 52.1, 76.3, 55.2, 70.2, 56.3, 66.3, 57.7, 62.2, 58.9, 59.3, 47.4, 56.3, 45.7, 57.4, 43.7, 59.3, 42.0, 61.2, 40.7, 39.8, -23.4, -2.5, 43.4, 54.7, 41.9, 54.9, 65.4, 29.7, 54.0, 26.9, 45.6, -1.3, 32.9, 1.9, 37.0, 65.7, -4.9, -16.1, 7.8, -13.4, 17.0, -9.2, 31.9, -8.0, -5.8, 0.6, 49.5, 18.5, -22.1, 16.4, 2.9, 60.2, -1.2, 66.7, -16.9, -1.1, -6.6, 48.3, 30.1, 86.9, 47.2, 7.9, 38.4, 56.5, -6.3, 15.8, 40.1, 96.6, 19.5, 85.1, 10.3, 77.7, 53.4, 99.3, 72.4, 36.6, 49.0, 36.6, 63.3, 36.0, 12.0, 70.8, 20.5, 79.0, 41.9, 93.4, -10.8, 53.8, 55.6, 96.1, 29.4, 91.6, -16.9, 15.9, 52.6, 57.9, 51.1, 59.9, 49.3, 63.0, 47.8, 66.6, 43.4, 71.6, 42.5, 51.6, 41.1, 50.7, 40.1, 49.8, 33.9, 44.8, 5.2, 22.4, 43.7, 52.4, 0.8, 39.5, 37.4, 76.3, 57.9, 91.0, 59.5, 84.0, 48.0, 82.2, 24.5, 60.9, 42.0, 23.2, 29.7, 69.4, 24.5, 19.4, 33.8, 29.6, 15.9, 30.2, 44.3, 88.6, 16.7, 64.6, 24.5, 73.5, 20.9, 50.8, -6.3, 28.8, 10.4, 50.0, -14.1, 32.1, 26.5, 38.4, -15.8, -17.7, -22.5, -20.0, 79.2, 86.0, 103.6, 22.2, 76.4, 46.4, 73.7, 53.3, 82.0, 49.7, 85.1, 52.9, 78.2, 54.4, 81.0, 55.7, 88.8, 66.7, 120.3, 23.7, 94.3, 60.1, 108.6, 53.5, 86.6, 58.7, 85.1, 58.5, 75.4, 50.2, 80.1, 52.1, 83.2, 54.4, 85.7, 58.6, 83.7, 61.3, 84.2, 58.5, 79.2, 56.2, 76.4, 55.3, 72.3, 54.8, 69.5, 78.5, 71.4, 72.1, 71.8, 68.1, 71.8, 64.0, 71.3, 60.8, 78.6, 59.9, 80.0, 61.4, 81.4, 63.6, 82.3, 66.2, 92.9, 46.8, 123.4, 20.1, 80.9, 59.1, 82.4, 60.0, 80.5, 32.0, 87.9, 31.6, 99.9, 7.0, 109.2, 13.6, 83.7, 71.3, 134.1, 5.7, 127.8, 4.7, 121.3, 7.2, 110.3, 4.5, 130.4, 21.1, 92.6, 24.6, 116.6, 36.4, 100.3, 71.4, 94.8, 77.0, 129.5, 21.1, 107.8, 62.6, 77.3, 91.0, 96.7, 15.3, 85.0, 62.3, 124.4, 34.9, 65.2, 98.5, 80.5, 90.1, 87.0, 84.7, 88.9, 42.1, 80.1, 38.4, 92.0, 79.2, 84.7, 84.7, 68.0, 95.7, 101.4, 67.3, 73.6, 94.8, 123.0, 35.9, 75.4, 60.4, 76.5, 63.1, 77.4, 66.3, 77.7, 70.0, 77.4, 75.7, 83.0, 57.1, 84.8, 56.6, 86.5, 55.9, 94.8, 52.9, 118.5, 38.9, 81.4, 57.2, 111.4, 54.3, 78.7, 80.5, 69.6, 84.2, 92.5, 69.0, 96.6, 31.1, 86.0, 75.8, 110.5, 32.0, 100.8, 38.9, 110.9, 43.6, 69.6, 91.0, 94.7, 73.2, 86.6, 79.6, 99.3, 61.0, 118.3, 46.0, 104.1, 62.0, 115.7, 49.8, 101.7, 48.6, 134.1, 6.1, 128.2, 4.4]}, {"rect": [269, 461, 547, 739], "points": [0.36625, 0.05514, 0.08984, 0.0, -0.06675, 0.3769, -0.00311, 0.0, -0.10896, -0.03663, 0.36401, 0.0, -89.85697, -268.86805, -63.79456, 1.0, 69.4, 46.8, 74.0, 30.7, 68.9, 49.6, 67.9, 52.7, 67.1, 54.6, 65.7, 60.4, 65.3, 63.9, 64.9, 68.0, 63.9, 71.8, 61.6, 77.8, 33.1, 81.5, 37.4, 11.9, 61.6, 44.5, 60.3, 51.5, 52.1, 46.0, 45.5, 48.2, 53.4, 51.4, 47.8, 51.5, 32.4, 59.4, 14.0, 7.6, 29.1, 51.5, -18.2, 36.7, 36.5, 52.0, 38.3, 52.4, 60.8, 48.2, 52.9, 48.8, 46.6, 49.7, 37.4, 52.1, 40.2, 55.7, 39.2, 52.5, 48.4, 52.5, 53.9, 52.8, 60.3, 53.4, 52.1, 76.3, 55.2, 70.0, 56.5, 66.3, 57.9, 62.2, 58.9, 59.0, 47.5, 56.2, 46.0, 57.2, 43.8, 59.0, 42.3, 61.2, 41.0, 39.6, -23.4, -2.8, 43.7, 54.4, 42.0, 54.8, 65.5, 29.7, 54.0, 26.9, 45.6, -1.5, 33.1, 1.7, 37.3, 65.8, -4.9, -16.3, 8.0, -13.4, 17.2, -9.2, 32.0, -8.2, -5.5, 0.4, 49.7, 18.3, -22.3, 16.1, 2.9, 60.2, -1.0, 66.7, -16.9, -1.4, -6.4, 48.2, 30.4, 86.9, 47.4, 7.7, 38.7, 56.2, -6.3, 15.6, 40.4, 96.6, 19.7, 85.1, 10.5, 77.7, 53.7, 99.4, 72.6, 36.6, 49.3, 36.6, 63.5, 35.9, 12.0, 70.8, 20.7, 78.8, 42.2, 93.4, -10.6, 53.8, 55.7, 96.1, 29.5, 91.6, -16.9, 16.0, 52.9, 57.6, 51.1, 59.8, 49.6, 62.7, 47.9, 66.3, 43.7, 71.4, 42.8, 51.9, 41.4, 51.0, 40.1, 49.8, 34.2, 44.6, 5.2, 22.4, 43.8, 52.5, 1.0, 39.5, 37.7, 76.3, 58.0, 90.7, 59.8, 83.8, 48.3, 82.0, 24.6, 60.8, 42.1, 23.0, 30.0, 69.4, 24.6, 19.2, 34.1, 29.4, 16.2, 30.2, 44.6, 88.4, 17.0, 64.5, 24.8, 73.3, 21.2, 50.7, -6.2, 28.5, 10.6, 49.7, -14.1, 32.1, 26.8, 38.2, -15.6, -18.0, -22.4, -20.3, 79.5, 86.0, 103.6, 22.0, 76.4, 46.5, 73.7, 53.4, 82.0, 49.7, 85.1, 52.9, 78.2, 54.6, 81.0, 55.7, 88.9, 66.6, 120.3, 23.5, 94.4, 59.9, 108.7, 53.4, 86.9, 58.9, 85.2, 58.5, 75.4, 50.5, 80.1, 52.4, 83.3, 54.6, 86.0, 58.9, 83.8, 61.3, 84.3, 58.5, 79.2, 56.5, 76.4, 55.6, 72.3, 55.1, 69.6, 78.3, 71.7, 71.8, 72.1, 68.1, 72.1, 64.0, 71.3, 60.8, 78.7, 59.9, 80.1, 61.4, 81.5, 63.6, 82.4, 65.9, 93.0, 46.8, 123.2, 19.8, 81.0, 59.1, 82.5, 60.0, 80.6, 32.0, 87.9, 31.6, 99.9, 6.8, 109.2, 13.3, 83.8, 71.3, 134.1, 5.4, 127.6, 4.6, 121.1, 7.0, 110.1, 4.2, 130.4, 20.8, 92.9, 24.4, 116.6, 36.3, 100.4, 71.3, 94.9, 76.9, 129.5, 20.8, 107.8, 62.6, 77.7, 90.8, 96.8, 15.1, 85.1, 62.3, 124.4, 34.6, 65.3, 98.5, 80.5, 90.1, 87.0, 84.7, 89.2, 41.9, 80.2, 38.2, 92.1, 79.1, 84.8, 84.6, 68.1, 95.7, 101.4, 67.2, 73.6, 94.8, 123.0, 35.8, 75.5, 60.4, 76.8, 63.0, 77.7, 66.3, 77.8, 69.9, 77.7, 75.5, 83.2, 57.1, 85.1, 56.6, 86.5, 56.1, 94.8, 52.9, 118.5, 38.6, 81.5, 57.4, 111.5, 54.3, 78.8, 80.5, 69.9, 84.2, 92.6, 69.0, 96.7, 30.8, 86.1, 75.5, 110.5, 31.8, 100.8, 38.7, 111.0, 43.3, 69.9, 90.7, 94.8, 73.2, 86.9, 79.6, 99.4, 60.8, 118.4, 45.9, 104.1, 61.7, 116.0, 49.7, 101.8, 48.4, 134.1, 5.6, 128.2, 4.1]}, {"rect": [269, 461, 547, 739], "points": [0.36619, 0.05509, 0.08966, 0.0, -0.06654, 0.37777, -0.00303, 0.0, -0.10817, -0.03648, 0.36534, 0.0, -89.79995, -269.53696, -63.69499, 1.0, 69.1, 46.8, 74.1, 30.4, 68.6, 49.6, 67.7, 52.8, 66.8, 54.6, 65.7, 60.3, 65.3, 63.6, 64.9, 67.7, 63.9, 71.7, 61.6, 77.8, 33.2, 81.5, 37.7, 11.9, 61.4, 44.5, 60.4, 51.5, 52.1, 46.0, 45.5, 48.2, 53.4, 51.4, 47.8, 51.5, 32.7, 59.4, 14.2, 7.4, 29.4, 51.5, -17.8, 36.5, 37.0, 52.0, 38.6, 52.4, 60.8, 48.3, 52.9, 48.8, 46.8, 49.7, 37.9, 52.3, 40.7, 55.7, 39.5, 52.5, 48.7, 52.7, 54.2, 52.8, 60.3, 53.6, 52.4, 76.1, 55.3, 69.9, 56.5, 66.2, 57.9, 62.1, 58.9, 59.0, 47.8, 56.2, 46.3, 57.1, 44.1, 58.9, 42.3, 61.1, 41.0, 39.5, -23.1, -2.8, 44.0, 54.4, 42.2, 54.8, 65.7, 29.4, 54.3, 26.7, 45.7, -1.9, 33.2, 1.4, 37.3, 65.7, -4.6, -16.6, 8.5, -13.5, 17.7, -9.3, 32.5, -8.3, -5.5, 0.3, 49.8, 18.0, -21.9, 16.1, 3.2, 59.9, -0.9, 66.4, -16.7, -1.5, -6.1, 48.0, 30.4, 86.6, 47.5, 7.4, 39.0, 56.2, -6.1, 15.6, 40.4, 96.6, 19.8, 84.8, 10.6, 77.5, 53.8, 99.3, 72.7, 36.3, 49.3, 36.3, 63.6, 35.8, 12.1, 70.6, 20.8, 78.7, 42.0, 93.4, -10.3, 53.5, 55.8, 96.1, 29.5, 91.6, -16.4, 15.7, 52.9, 57.6, 51.4, 59.8, 49.6, 62.6, 47.9, 66.2, 43.8, 71.4, 43.1, 51.9, 41.7, 51.0, 40.4, 50.0, 34.5, 44.6, 5.5, 22.1, 44.1, 52.5, 1.3, 39.2, 37.8, 76.3, 58.0, 90.7, 59.8, 83.8, 48.4, 81.9, 24.8, 60.7, 42.3, 22.9, 30.1, 69.4, 24.8, 18.9, 34.1, 29.1, 16.5, 29.9, 44.7, 88.4, 17.1, 64.5, 24.9, 73.2, 21.3, 50.6, -5.7, 28.5, 10.7, 49.7, -13.9, 31.8, 27.1, 38.1, -15.3, -18.1, -22.2, -20.4, 79.6, 85.8, 103.6, 21.7, 76.1, 46.5, 73.6, 53.6, 82.0, 49.7, 85.1, 52.9, 78.2, 54.7, 81.0, 56.0, 89.1, 66.4, 120.6, 23.4, 94.7, 59.8, 108.8, 53.2, 87.0, 58.9, 85.5, 58.5, 75.1, 50.5, 80.1, 52.4, 83.3, 54.7, 86.1, 58.9, 84.1, 61.2, 84.6, 58.5, 79.2, 56.6, 76.4, 55.9, 72.2, 55.1, 69.8, 78.3, 71.7, 71.7, 71.9, 68.0, 71.9, 63.9, 71.3, 60.8, 78.7, 59.9, 80.1, 61.6, 81.5, 63.5, 82.4, 65.9, 93.0, 46.6, 123.5, 19.7, 81.3, 59.3, 82.8, 60.2, 80.8, 31.7, 87.9, 31.3, 99.9, 6.5, 109.5, 13.2, 84.1, 71.3, 134.4, 5.1, 127.6, 4.5, 120.8, 6.9, 110.0, 4.1, 130.5, 20.7, 92.9, 24.3, 116.7, 36.0, 100.5, 71.1, 95.0, 76.7, 129.6, 20.7, 107.9, 62.4, 77.7, 90.7, 97.0, 14.7, 85.2, 62.5, 124.5, 34.5, 65.3, 98.5, 80.6, 89.9, 87.1, 84.7, 89.2, 41.8, 80.4, 38.1, 92.2, 78.9, 85.1, 84.4, 68.1, 95.7, 101.5, 67.0, 73.7, 94.8, 123.1, 35.6, 75.5, 60.3, 76.8, 63.0, 77.7, 66.2, 77.8, 69.9, 77.7, 75.5, 83.3, 57.1, 85.1, 56.6, 86.5, 56.1, 94.8, 52.9, 118.7, 38.3, 81.5, 57.5, 111.5, 54.1, 79.0, 80.5, 69.9, 84.2, 92.9, 69.0, 96.7, 30.8, 86.1, 75.6, 110.6, 31.7, 100.8, 38.6, 111.0, 43.3, 69.9, 90.7, 94.8, 73.2, 87.0, 79.4, 99.4, 60.8, 118.5, 45.7, 104.4, 61.7, 116.1, 49.5, 102.0, 48.4, 134.2, 5.5, 128.5, 3.7]}, {"rect": [269, 461, 547, 739], "points": [0.36656, 0.05517, 0.08971, 0.0, -0.06637, 0.37914, -0.00287, 0.0, -0.10676, -0.03629, 0.36607, 0.0, -89.82957, -270.61786, -63.88595, 1.0, 68.9, 46.6, 74.0, 30.1, 68.4, 49.6, 67.5, 52.5, 66.8, 54.4, 65.6, 60.2, 65.1, 63.5, 64.6, 67.6, 63.7, 71.4, 61.6, 77.7, 33.5, 81.4, 38.0, 11.6, 61.4, 44.2, 60.4, 51.5, 52.1, 46.0, 45.6, 47.9, 53.5, 51.2, 47.9, 51.5, 33.0, 59.4, 14.5, 7.0, 29.7, 51.2, -17.9, 36.4, 36.8, 51.9, 38.6, 52.4, 60.8, 48.2, 52.9, 48.7, 46.6, 49.7, 37.7, 52.3, 40.5, 55.6, 39.5, 52.4, 48.7, 52.4, 54.0, 52.6, 60.0, 53.4, 52.4, 76.0, 55.3, 69.5, 56.3, 65.9, 57.7, 62.0, 58.9, 58.9, 47.8, 56.1, 46.1, 57.0, 44.1, 58.9, 42.4, 60.8, 41.3, 39.2, -23.1, -3.1, 43.7, 54.3, 42.3, 54.7, 65.7, 29.1, 54.6, 26.4, 45.9, -2.2, 33.4, 1.1, 37.6, 65.5, -4.4, -16.9, 8.5, -13.8, 17.7, -9.6, 32.5, -8.6, -5.2, -0.2, 50.0, 17.7, -22.1, 15.8, 3.2, 59.9, -0.8, 66.4, -16.7, -1.8, -6.0, 47.9, 30.7, 86.6, 47.7, 7.0, 39.0, 56.1, -6.1, 15.3, 40.5, 96.6, 19.8, 85.0, 10.6, 77.7, 53.8, 99.0, 72.6, 36.0, 49.5, 36.0, 63.8, 35.5, 12.3, 70.5, 21.1, 78.7, 42.2, 93.4, -10.5, 53.5, 56.0, 95.8, 29.8, 91.5, -16.6, 15.4, 52.9, 57.5, 51.2, 59.4, 49.4, 62.5, 47.9, 65.8, 44.0, 71.4, 42.8, 51.6, 41.5, 50.7, 40.5, 49.7, 34.8, 44.4, 5.8, 21.8, 44.1, 52.4, 1.4, 39.2, 38.1, 76.1, 58.0, 90.6, 59.8, 83.8, 48.6, 81.9, 25.1, 60.5, 42.6, 22.6, 30.6, 69.2, 25.1, 18.6, 34.4, 29.0, 16.8, 29.6, 44.9, 88.3, 17.3, 64.4, 25.2, 73.2, 21.5, 50.6, -5.6, 28.2, 11.0, 49.7, -13.9, 31.8, 27.4, 37.8, -15.3, -18.6, -22.1, -20.9, 79.6, 86.0, 103.6, 21.3, 76.1, 46.4, 73.4, 53.4, 82.0, 49.6, 84.9, 52.9, 78.0, 54.4, 81.0, 55.7, 88.9, 66.4, 120.6, 23.1, 94.4, 59.6, 109.2, 53.4, 87.0, 58.9, 85.6, 58.7, 75.1, 50.3, 80.1, 52.4, 83.1, 54.4, 86.1, 58.8, 84.2, 61.2, 84.7, 58.4, 79.3, 56.5, 76.4, 55.7, 72.0, 54.9, 69.8, 78.2, 71.5, 71.4, 71.9, 67.7, 71.9, 63.6, 71.1, 60.7, 78.7, 59.8, 80.1, 61.6, 81.5, 63.5, 82.4, 65.8, 92.9, 46.6, 123.9, 19.5, 81.2, 59.3, 82.8, 60.2, 80.6, 31.4, 87.8, 31.0, 99.9, 6.1, 109.5, 12.9, 84.1, 71.0, 134.6, 4.7, 127.9, 4.2, 121.0, 6.8, 110.0, 4.1, 130.8, 20.4, 92.9, 24.0, 117.4, 36.0, 100.8, 71.4, 95.4, 76.9, 130.2, 20.4, 108.3, 62.6, 77.8, 90.7, 97.0, 14.4, 85.2, 62.5, 124.9, 34.3, 65.3, 98.4, 80.6, 90.1, 87.4, 84.8, 89.2, 41.6, 80.1, 37.8, 92.5, 79.2, 85.1, 84.6, 68.1, 95.7, 102.1, 67.3, 73.7, 94.8, 123.5, 35.5, 75.5, 60.3, 76.6, 62.7, 77.5, 65.9, 77.8, 69.6, 77.7, 75.2, 83.3, 57.1, 85.2, 56.6, 86.6, 56.1, 94.8, 52.6, 118.8, 38.3, 81.5, 57.4, 111.8, 54.3, 79.0, 80.5, 69.9, 84.2, 93.0, 68.8, 96.7, 30.5, 86.1, 75.6, 110.8, 31.4, 100.8, 38.3, 111.0, 43.3, 69.9, 90.7, 94.8, 73.2, 87.0, 79.6, 99.5, 60.8, 118.8, 45.7, 104.5, 61.8, 116.6, 49.7, 101.8, 48.4, 134.6, 5.2, 128.9, 3.4]}, {"rect": [269, 460, 547, 738], "points": [0.36711, 0.05518, 0.08969, 0.0, -0.06585, 0.38043, -0.00315, 0.0, -0.10488, -0.03599, 0.36766, 0.0, -90.15688, -271.39343, -63.8101, 1.0, 69.1, 47.0, 73.9, 30.4, 68.6, 49.8, 67.7, 52.7, 66.8, 54.6, 65.8, 60.5, 65.3, 63.9, 64.9, 67.7, 63.9, 71.5, 61.6, 77.9, 33.4, 81.5, 37.9, 11.9, 61.6, 44.6, 60.6, 51.7, 52.3, 46.4, 45.6, 48.3, 53.7, 51.6, 47.8, 51.6, 32.9, 59.8, 14.4, 7.6, 29.8, 51.6, -17.9, 37.0, 36.7, 52.3, 38.6, 52.5, 60.8, 48.4, 52.9, 48.9, 46.8, 50.1, 37.7, 52.4, 40.5, 55.7, 39.4, 52.8, 48.7, 52.6, 54.2, 53.0, 60.2, 53.6, 52.3, 76.4, 55.5, 69.6, 56.6, 66.2, 57.9, 62.1, 58.9, 59.2, 47.8, 56.4, 46.3, 57.4, 44.1, 59.2, 42.6, 61.1, 41.3, 39.6, -23.3, -2.6, 43.7, 54.6, 42.2, 55.1, 65.6, 29.5, 54.5, 26.7, 45.9, -1.9, 33.3, 1.6, 37.6, 65.9, -4.7, -16.5, 8.4, -13.5, 17.6, -9.0, 32.3, -8.1, -5.3, 0.5, 50.0, 18.2, -22.1, 16.6, 3.5, 60.5, -0.6, 67.0, -16.7, -1.3, -6.0, 48.5, 30.7, 86.9, 47.7, 7.3, 39.0, 56.5, -6.1, 15.8, 40.4, 96.7, 20.1, 85.2, 10.9, 78.1, 53.7, 99.4, 72.2, 36.4, 49.5, 36.4, 63.7, 35.9, 12.4, 71.2, 21.1, 79.1, 42.2, 93.5, -10.2, 54.1, 56.0, 96.2, 29.8, 91.7, -16.6, 16.1, 52.9, 57.8, 51.4, 59.8, 49.6, 62.6, 48.1, 65.9, 44.0, 71.8, 42.8, 52.0, 41.4, 51.0, 40.4, 50.1, 34.7, 45.0, 5.8, 22.4, 44.1, 52.8, 1.6, 39.8, 38.0, 76.5, 57.9, 90.8, 59.7, 84.2, 48.6, 82.0, 25.1, 61.1, 42.5, 22.9, 30.6, 69.6, 25.0, 19.1, 34.3, 29.3, 16.8, 30.2, 44.9, 88.5, 17.3, 64.8, 25.2, 73.6, 21.8, 51.0, -5.7, 28.7, 11.2, 50.1, -13.8, 32.4, 27.4, 38.2, -15.6, -18.0, -22.1, -20.2, 79.5, 86.2, 103.5, 21.7, 76.3, 46.6, 73.6, 53.6, 81.9, 49.8, 85.1, 53.3, 78.2, 54.8, 81.0, 56.2, 88.8, 66.9, 120.7, 23.5, 94.4, 60.3, 109.7, 54.0, 87.0, 59.3, 85.5, 58.9, 75.1, 50.6, 80.1, 52.6, 83.3, 54.8, 86.1, 59.0, 84.1, 61.6, 84.6, 58.8, 79.5, 56.7, 76.4, 55.9, 72.2, 55.3, 69.5, 78.4, 71.7, 71.7, 71.8, 68.0, 71.8, 63.9, 71.3, 61.0, 78.7, 60.2, 80.1, 62.0, 81.5, 63.9, 82.4, 66.2, 92.6, 47.0, 124.1, 19.8, 81.4, 59.7, 82.9, 60.3, 80.4, 31.8, 87.5, 31.4, 99.9, 6.5, 109.2, 13.0, 83.8, 71.5, 135.0, 5.1, 127.6, 4.5, 120.7, 6.9, 109.7, 4.2, 131.3, 20.8, 92.6, 24.4, 117.6, 36.5, 100.9, 71.9, 95.8, 77.5, 130.5, 20.8, 108.7, 63.2, 77.7, 91.2, 96.7, 14.7, 85.2, 62.6, 125.3, 35.0, 65.3, 98.6, 80.9, 90.4, 87.5, 85.3, 88.9, 42.0, 80.0, 38.2, 92.5, 79.7, 85.2, 84.9, 68.0, 95.9, 102.4, 68.1, 73.7, 95.0, 123.9, 36.0, 75.5, 60.6, 76.8, 63.0, 77.7, 66.2, 77.8, 69.9, 77.4, 75.6, 83.3, 57.4, 85.2, 57.0, 86.5, 56.2, 94.5, 53.1, 118.9, 38.8, 81.8, 57.6, 112.0, 54.8, 78.8, 80.8, 69.9, 84.4, 92.9, 69.5, 96.6, 30.9, 86.1, 76.0, 110.6, 31.8, 100.8, 38.8, 111.0, 43.8, 69.9, 91.1, 94.8, 73.7, 87.0, 79.8, 99.4, 61.3, 118.9, 46.2, 104.6, 62.3, 117.0, 50.3, 101.8, 48.9, 135.0, 5.5, 129.2, 3.7]}, {"rect": [269, 460, 547, 738], "points": [0.36854, 0.0557, 0.08865, 0.0, -0.06557, 0.38213, -0.00432, 0.0, -0.10221, -0.03628, 0.36954, 0.0, -90.67265, -272.96728, -62.44357, 1.0, 69.4, 46.8, 73.2, 30.3, 68.8, 49.7, 67.9, 52.9, 66.7, 54.7, 65.8, 59.9, 65.3, 63.5, 64.8, 67.6, 63.9, 71.3, 61.2, 77.9, 33.1, 81.4, 37.3, 11.5, 61.6, 44.3, 60.6, 51.9, 52.3, 46.0, 45.5, 47.9, 53.4, 51.5, 47.8, 51.5, 32.6, 59.5, 13.8, 7.0, 29.5, 51.5, -17.9, 36.4, 36.4, 51.7, 38.3, 52.1, 61.0, 48.3, 52.9, 48.8, 46.5, 49.7, 37.3, 52.1, 40.4, 55.3, 39.1, 52.4, 48.4, 52.5, 53.9, 52.9, 60.2, 53.8, 52.0, 76.4, 55.3, 69.4, 56.6, 65.8, 57.9, 61.7, 58.9, 58.9, 47.5, 55.7, 46.1, 57.0, 44.1, 58.5, 42.3, 60.7, 40.9, 39.5, -23.1, -3.3, 43.3, 54.3, 41.9, 54.7, 65.2, 29.4, 53.9, 26.6, 45.5, -2.3, 32.7, 1.0, 37.2, 65.8, -5.1, -17.4, 7.5, -14.2, 16.7, -9.6, 31.4, -8.6, -5.6, -0.3, 49.7, 17.9, -22.1, 16.0, 3.2, 60.0, -0.6, 66.7, -17.0, -2.1, -6.1, 48.0, 30.4, 86.6, 47.3, 6.9, 38.7, 56.1, -6.4, 15.3, 40.1, 96.6, 19.8, 85.1, 10.6, 77.8, 53.4, 99.1, 71.8, 36.3, 48.9, 36.3, 63.1, 35.8, 12.3, 70.9, 21.0, 78.7, 41.8, 93.4, -10.2, 53.8, 55.7, 95.9, 29.5, 91.6, -16.6, 15.3, 52.9, 57.4, 51.1, 59.4, 49.6, 62.2, 47.9, 65.8, 43.7, 71.7, 42.7, 51.6, 41.3, 50.7, 40.4, 49.7, 34.2, 44.7, 5.4, 22.1, 43.7, 52.5, 1.3, 39.3, 37.7, 76.4, 57.6, 90.7, 59.4, 84.2, 48.0, 82.0, 24.9, 60.8, 41.9, 22.6, 30.0, 69.5, 24.4, 18.6, 34.0, 29.0, 16.2, 29.9, 44.3, 88.4, 17.0, 64.5, 24.9, 73.3, 21.2, 50.7, -6.0, 28.2, 10.7, 49.8, -13.9, 31.8, 26.8, 37.9, -15.7, -18.8, -22.1, -21.1, 79.2, 86.4, 103.4, 21.6, 76.3, 46.4, 73.6, 53.8, 81.9, 49.7, 85.1, 53.0, 78.2, 54.7, 81.0, 56.1, 88.7, 67.1, 120.9, 23.7, 94.3, 60.6, 110.4, 54.5, 87.0, 58.9, 85.2, 58.5, 75.4, 50.6, 80.1, 52.5, 83.3, 54.7, 86.0, 58.8, 83.8, 61.2, 84.4, 58.5, 79.5, 56.6, 76.4, 56.1, 72.2, 55.5, 69.1, 78.6, 71.4, 71.4, 71.8, 67.7, 71.8, 63.5, 71.3, 60.3, 78.7, 59.8, 80.1, 61.6, 81.4, 63.5, 82.4, 65.9, 92.4, 47.2, 125.1, 20.0, 81.1, 59.3, 82.8, 60.2, 80.0, 31.7, 87.3, 31.6, 99.8, 6.4, 109.4, 12.8, 83.7, 71.7, 135.5, 5.0, 127.8, 4.1, 120.9, 6.7, 109.8, 4.0, 131.8, 21.0, 92.4, 24.4, 118.6, 36.9, 101.2, 72.2, 96.2, 78.1, 131.4, 21.0, 109.1, 63.7, 77.5, 91.2, 96.6, 14.6, 85.1, 62.5, 125.9, 35.2, 65.0, 98.6, 80.7, 90.6, 87.5, 85.5, 88.7, 42.2, 79.6, 38.2, 92.6, 79.9, 85.1, 85.1, 67.7, 95.8, 103.0, 68.4, 73.6, 95.2, 124.6, 36.5, 75.5, 60.2, 76.8, 62.6, 77.4, 65.8, 77.8, 69.5, 77.3, 75.9, 83.3, 57.1, 85.1, 56.7, 86.5, 56.1, 94.7, 53.3, 119.5, 39.0, 81.5, 57.5, 112.3, 55.1, 78.6, 81.0, 69.5, 84.6, 92.9, 69.8, 96.5, 30.8, 86.0, 76.2, 110.8, 32.0, 100.7, 39.0, 111.2, 44.0, 69.5, 91.1, 94.8, 74.0, 87.0, 80.0, 99.4, 61.5, 119.5, 46.7, 104.8, 62.5, 117.7, 50.8, 101.7, 49.1, 135.9, 5.4, 130.1, 3.5]}, {"rect": [268, 459, 546, 737], "points": [0.3693, 0.05563, 0.08722, 0.0, -0.06473, 0.38299, -0.00422, 0.0, -0.09963, -0.03638, 0.37072, 0.0, -91.14752, -273.44324, -61.62698, 1.0, 69.8, 46.9, 73.2, 30.5, 69.0, 50.1, 68.1, 53.2, 67.1, 55.2, 66.2, 59.9, 65.7, 63.5, 65.2, 67.6, 64.3, 71.4, 61.3, 78.3, 33.2, 81.6, 37.3, 11.6, 62.0, 44.6, 60.7, 52.1, 52.5, 46.1, 45.9, 48.0, 53.8, 51.6, 47.9, 51.6, 32.7, 59.9, 13.9, 7.1, 29.8, 51.6, -17.3, 36.5, 36.7, 52.0, 38.6, 52.5, 61.2, 48.7, 53.3, 49.1, 46.8, 49.8, 37.6, 52.2, 40.5, 55.3, 39.2, 52.5, 48.7, 52.9, 54.2, 53.4, 60.6, 54.2, 52.1, 76.8, 55.6, 69.5, 56.9, 65.6, 58.3, 61.7, 59.3, 58.9, 47.8, 55.7, 46.4, 56.8, 44.2, 58.6, 42.7, 60.8, 41.0, 39.7, -22.7, -3.4, 43.7, 54.4, 42.3, 54.8, 65.0, 29.5, 53.9, 26.8, 45.6, -2.2, 32.7, 1.1, 37.3, 66.2, -5.1, -17.3, 7.5, -14.1, 16.7, -9.5, 31.4, -8.2, -5.5, -0.3, 49.7, 18.1, -21.5, 15.9, 3.6, 60.4, -0.2, 66.9, -16.7, -2.1, -5.7, 48.3, 30.7, 87.0, 47.4, 7.0, 39.0, 56.2, -6.1, 15.3, 40.5, 96.8, 20.2, 85.3, 11.0, 77.9, 53.5, 99.5, 71.8, 36.4, 49.2, 36.5, 63.1, 36.0, 12.7, 71.0, 21.2, 78.9, 41.9, 93.6, -9.8, 54.0, 55.8, 96.3, 29.9, 91.7, -16.3, 15.4, 53.3, 57.2, 51.5, 59.4, 50.0, 62.2, 48.3, 65.8, 43.8, 71.9, 42.8, 52.0, 41.4, 51.1, 40.5, 49.8, 34.4, 45.0, 5.5, 22.2, 43.8, 52.6, 1.7, 39.6, 37.8, 76.8, 57.9, 91.2, 59.7, 84.3, 48.2, 82.4, 25.2, 61.2, 42.0, 22.7, 30.4, 69.9, 24.4, 18.9, 34.0, 29.1, 16.5, 30.0, 44.7, 88.8, 17.4, 64.9, 25.2, 73.6, 21.5, 51.1, -5.7, 28.2, 11.0, 50.1, -13.5, 31.9, 27.1, 38.2, -15.3, -19.0, -21.4, -21.0, 79.6, 86.7, 103.6, 21.7, 76.8, 46.6, 74.0, 54.2, 82.3, 50.1, 85.5, 53.3, 78.6, 55.1, 81.4, 56.2, 88.9, 67.6, 121.4, 23.6, 94.4, 60.8, 111.5, 54.7, 87.3, 59.2, 85.6, 58.9, 75.8, 50.7, 80.5, 52.8, 83.7, 54.8, 86.4, 58.9, 84.2, 61.5, 85.0, 58.8, 79.9, 57.0, 76.8, 56.5, 72.6, 55.7, 69.4, 79.1, 71.7, 71.4, 72.2, 67.7, 72.2, 63.5, 71.7, 60.3, 79.1, 59.8, 80.5, 61.6, 81.8, 63.8, 82.7, 66.2, 92.5, 47.4, 126.2, 19.9, 81.7, 59.4, 83.2, 60.3, 80.0, 31.8, 87.4, 31.8, 99.9, 6.5, 109.5, 12.9, 83.8, 72.2, 136.0, 5.1, 128.0, 4.2, 121.0, 6.6, 110.0, 4.1, 132.4, 21.1, 92.4, 24.5, 119.4, 36.9, 102.0, 72.7, 97.0, 78.6, 132.0, 21.1, 109.9, 64.0, 78.1, 91.6, 96.6, 14.8, 85.5, 62.6, 126.4, 35.1, 65.3, 99.0, 81.3, 91.1, 88.2, 86.0, 88.7, 42.4, 79.6, 38.3, 93.3, 80.2, 85.6, 85.6, 68.1, 96.2, 103.9, 68.9, 74.1, 95.7, 125.5, 36.5, 75.9, 60.3, 77.2, 62.9, 77.7, 65.9, 78.1, 69.6, 77.4, 76.3, 83.7, 57.5, 85.5, 57.0, 86.9, 56.1, 94.8, 53.7, 119.9, 39.2, 81.9, 57.9, 113.0, 55.3, 78.7, 81.4, 69.9, 84.8, 93.0, 70.0, 96.6, 31.0, 86.4, 76.4, 110.9, 31.9, 100.8, 39.2, 111.4, 44.2, 69.9, 91.3, 95.2, 74.2, 87.4, 80.5, 99.8, 61.7, 120.0, 46.9, 105.3, 63.0, 118.5, 51.0, 102.1, 49.2, 136.5, 5.5, 131.0, 3.6]}, {"rect": [268, 458, 546, 736], "points": [0.3698, 0.0552, 0.0857, 0.0, -0.06402, 0.38334, -0.00368, 0.0, -0.09787, -0.03651, 0.37154, 0.0, -91.7664, -273.3188, -60.9266, 1.0, 69.5, 47.0, 72.5, 31.1, 68.7, 50.1, 67.7, 53.4, 66.8, 55.5, 65.8, 59.9, 65.4, 63.3, 64.9, 67.7, 63.7, 71.7, 60.9, 78.7, 32.8, 82.0, 36.9, 12.0, 61.7, 44.6, 60.4, 52.4, 52.1, 46.4, 45.5, 48.3, 53.4, 52.0, 47.5, 52.0, 32.3, 60.3, 13.4, 7.4, 29.2, 52.0, -17.8, 36.9, 36.3, 52.1, 38.2, 52.6, 60.8, 48.8, 52.9, 49.2, 46.5, 50.2, 37.3, 52.5, 40.1, 55.4, 39.0, 52.6, 48.3, 53.0, 53.9, 53.7, 60.0, 54.3, 51.7, 76.9, 55.3, 69.6, 56.6, 65.9, 58.0, 61.8, 59.0, 58.7, 47.4, 55.6, 46.0, 56.9, 43.8, 58.7, 42.1, 60.9, 40.6, 40.0, -23.1, -3.1, 43.3, 54.5, 41.9, 54.9, 64.5, 29.9, 53.5, 27.1, 45.1, -1.8, 32.3, 1.4, 37.0, 66.3, -5.5, -17.2, 7.3, -13.7, 16.2, -9.1, 30.9, -7.8, -6.0, 0.1, 49.3, 18.4, -22.0, 16.2, 3.2, 60.8, -0.8, 67.3, -17.0, -1.7, -6.3, 48.5, 30.1, 87.2, 46.7, 7.4, 38.7, 56.3, -6.7, 15.7, 40.2, 97.1, 19.9, 85.6, 10.7, 78.3, 53.1, 99.9, 71.1, 36.8, 48.5, 36.8, 62.4, 36.3, 12.1, 71.4, 20.8, 79.2, 41.6, 93.9, -10.2, 54.4, 55.4, 96.6, 29.6, 92.1, -16.9, 15.8, 52.9, 57.3, 51.2, 59.5, 49.4, 62.3, 48.0, 65.9, 43.4, 72.3, 42.4, 52.1, 41.1, 51.2, 40.1, 50.2, 33.8, 45.2, 4.8, 22.6, 43.6, 52.9, 1.1, 39.8, 37.4, 76.9, 57.3, 91.6, 59.1, 84.7, 47.6, 82.8, 24.6, 61.3, 41.5, 23.3, 30.0, 70.0, 24.0, 19.3, 33.4, 29.5, 15.8, 30.4, 44.3, 89.0, 16.8, 65.0, 24.6, 73.8, 20.9, 51.3, -6.3, 28.6, 10.6, 50.3, -13.8, 32.3, 26.4, 38.6, -15.7, -18.7, -21.7, -20.9, 79.3, 87.3, 103.2, 22.3, 76.5, 46.8, 73.7, 54.2, 82.0, 50.1, 85.1, 53.4, 78.2, 55.2, 81.1, 56.5, 88.5, 67.9, 121.0, 24.1, 94.0, 61.1, 111.4, 55.1, 87.0, 59.0, 85.2, 58.9, 75.4, 51.0, 80.2, 52.9, 83.3, 55.1, 86.1, 58.9, 83.8, 61.3, 84.6, 58.9, 79.3, 57.1, 76.5, 56.6, 72.3, 56.0, 68.8, 79.2, 71.4, 71.7, 71.9, 67.7, 71.9, 63.6, 71.3, 60.1, 78.8, 59.6, 80.1, 61.4, 81.5, 63.7, 82.4, 66.2, 92.1, 47.7, 126.0, 20.1, 81.1, 59.4, 82.8, 60.3, 79.3, 32.1, 86.7, 32.1, 99.4, 6.8, 109.1, 13.2, 83.5, 72.6, 135.7, 5.3, 127.9, 4.4, 120.6, 6.8, 109.5, 4.1, 132.0, 21.4, 91.7, 25.1, 119.5, 37.2, 101.8, 73.0, 97.0, 79.0, 131.9, 21.4, 109.9, 64.3, 77.5, 91.9, 96.2, 15.1, 85.1, 62.6, 126.1, 35.7, 65.0, 99.3, 81.1, 91.5, 88.0, 86.4, 88.1, 42.7, 78.9, 38.9, 93.0, 80.8, 85.3, 85.9, 67.8, 96.6, 103.9, 69.3, 73.8, 96.1, 125.5, 37.0, 75.5, 60.1, 76.9, 62.7, 77.4, 65.9, 77.8, 69.9, 77.0, 76.4, 83.3, 57.5, 85.2, 57.0, 86.5, 56.2, 94.4, 54.1, 119.6, 39.8, 81.5, 57.9, 112.8, 55.9, 78.4, 81.8, 69.3, 85.1, 92.7, 70.3, 95.9, 31.5, 86.1, 76.8, 110.6, 32.5, 100.4, 39.8, 111.3, 44.5, 69.3, 91.9, 94.9, 74.8, 87.1, 80.9, 99.4, 62.3, 120.0, 47.2, 105.0, 63.3, 118.3, 51.3, 101.7, 49.6, 136.2, 5.5, 131.0, 3.7]}, {"rect": [267, 457, 545, 735], "points": [0.36997, 0.05395, 0.08446, 0.0, -0.0627, 0.38338, -0.00267, 0.0, -0.09671, -0.03613, 0.37199, 0.0, -92.58897, -272.52234, -60.63684, 1.0, 69.6, 47.0, 72.7, 31.1, 69.0, 50.2, 68.1, 53.4, 67.1, 55.6, 65.9, 60.2, 65.7, 63.5, 65.0, 67.7, 64.0, 71.7, 61.3, 79.0, 33.2, 82.3, 36.9, 12.3, 62.0, 44.7, 60.7, 52.5, 52.4, 46.5, 45.6, 48.7, 53.4, 52.0, 47.8, 52.0, 32.7, 60.6, 13.4, 7.8, 29.5, 52.4, -17.5, 37.3, 36.4, 52.5, 38.2, 52.9, 61.1, 48.8, 52.9, 49.3, 46.5, 50.5, 37.3, 52.8, 40.4, 55.7, 39.1, 52.9, 48.3, 53.3, 53.9, 53.8, 60.3, 54.6, 52.0, 77.2, 55.6, 69.9, 56.7, 66.2, 58.1, 62.0, 59.2, 58.9, 47.5, 56.1, 46.0, 57.4, 44.1, 59.2, 42.3, 61.2, 40.6, 40.4, -23.0, -2.6, 43.6, 54.8, 41.9, 55.2, 64.6, 30.2, 53.5, 27.4, 45.1, -1.5, 32.3, 1.7, 37.3, 66.7, -5.5, -16.6, 7.1, -13.3, 16.2, -8.7, 30.9, -7.5, -5.9, 0.5, 49.3, 18.7, -21.7, 16.6, 3.3, 61.1, -0.4, 67.7, -17.0, -1.0, -6.0, 49.1, 30.4, 87.7, 46.9, 7.7, 38.7, 56.6, -6.4, 16.1, 40.6, 97.5, 20.3, 86.0, 11.1, 78.7, 53.5, 100.2, 71.3, 37.1, 48.7, 37.2, 62.6, 36.3, 12.5, 71.7, 21.2, 79.6, 42.0, 94.3, -10.1, 54.8, 55.8, 97.0, 29.9, 92.4, -16.6, 16.4, 53.0, 57.5, 51.5, 59.8, 49.7, 62.9, 48.3, 66.2, 43.7, 72.6, 42.7, 52.4, 41.3, 51.5, 40.1, 50.5, 34.1, 45.5, 5.1, 22.9, 43.7, 53.2, 1.4, 40.4, 37.8, 77.2, 57.7, 91.9, 59.5, 85.0, 48.0, 83.1, 24.9, 61.7, 41.8, 23.4, 30.3, 70.3, 24.0, 19.7, 33.6, 29.8, 16.1, 30.8, 44.7, 89.5, 17.1, 65.4, 24.9, 74.4, 21.2, 51.8, -6.0, 29.0, 10.7, 50.6, -13.7, 32.7, 26.7, 39.0, -15.6, -18.0, -21.6, -20.3, 79.7, 87.3, 103.2, 22.1, 76.8, 46.9, 74.0, 54.3, 82.3, 50.1, 85.2, 53.4, 78.3, 55.2, 81.4, 56.5, 88.9, 68.0, 121.1, 24.0, 94.3, 61.2, 111.8, 54.9, 87.1, 59.0, 85.5, 58.9, 75.5, 51.0, 80.5, 52.9, 83.4, 54.9, 86.2, 59.0, 84.2, 61.3, 84.7, 58.9, 79.6, 57.1, 76.8, 56.6, 72.6, 56.1, 69.1, 79.5, 71.7, 71.7, 72.2, 67.9, 72.2, 63.6, 71.4, 60.3, 79.1, 59.9, 80.4, 61.6, 81.5, 63.9, 82.4, 66.2, 92.2, 47.7, 126.4, 19.9, 81.4, 59.4, 82.9, 60.3, 79.3, 32.2, 86.7, 32.1, 99.4, 6.8, 109.1, 13.3, 83.8, 72.7, 135.8, 5.1, 127.9, 4.2, 120.6, 6.9, 109.5, 4.1, 132.1, 21.2, 91.7, 25.1, 119.7, 37.0, 102.1, 73.1, 97.5, 79.1, 132.1, 21.2, 110.4, 64.4, 77.9, 92.0, 96.2, 15.1, 85.2, 62.6, 126.4, 35.4, 65.4, 99.4, 81.5, 91.6, 88.5, 86.5, 88.1, 42.8, 78.9, 38.9, 93.5, 80.9, 85.7, 86.0, 68.2, 96.7, 104.4, 69.2, 74.2, 96.2, 125.6, 36.8, 75.9, 60.3, 76.9, 63.0, 77.7, 66.2, 77.8, 69.9, 77.4, 76.7, 83.4, 57.5, 85.2, 57.0, 86.6, 56.2, 94.5, 53.9, 119.7, 39.6, 81.9, 58.0, 113.1, 55.7, 78.7, 81.9, 69.6, 85.5, 93.0, 70.4, 95.9, 31.6, 86.2, 76.8, 110.8, 32.5, 100.4, 39.6, 111.4, 44.5, 69.7, 92.0, 95.3, 74.9, 87.5, 81.0, 99.5, 62.2, 120.1, 47.0, 105.3, 63.4, 118.7, 51.1, 101.8, 49.6, 136.5, 5.5, 131.1, 3.7]}, {"rect": [266, 456, 544, 734], "points": [0.36977, 0.0528, 0.08348, 0.0, -0.06124, 0.38294, -0.00308, 0.0, -0.09618, -0.03501, 0.37192, 0.0, -93.41659, -271.35174, -59.65702, 1.0, 69.8, 47.2, 72.7, 30.9, 69.0, 50.4, 68.1, 53.6, 67.2, 55.5, 66.1, 60.2, 65.8, 63.5, 65.2, 67.6, 64.3, 71.7, 61.6, 79.0, 33.5, 82.6, 37.1, 12.4, 62.0, 44.9, 60.7, 52.6, 52.4, 46.8, 45.6, 48.7, 53.7, 52.2, 47.8, 52.3, 33.0, 60.7, 13.7, 8.2, 29.8, 52.4, -17.2, 37.8, 36.4, 52.8, 38.2, 53.2, 61.2, 49.0, 53.0, 49.5, 46.5, 50.5, 37.3, 52.9, 40.5, 56.0, 39.1, 53.3, 48.4, 53.6, 54.2, 53.8, 60.3, 54.6, 52.4, 77.2, 55.7, 69.9, 56.9, 66.2, 58.3, 62.1, 59.3, 58.9, 47.7, 56.4, 46.1, 57.5, 44.2, 59.3, 42.6, 61.5, 40.9, 40.5, -22.7, -1.9, 43.7, 55.1, 42.2, 55.5, 64.8, 30.0, 53.7, 27.3, 45.1, -1.4, 32.5, 1.8, 37.6, 66.7, -5.2, -16.1, 7.6, -12.9, 16.5, -8.3, 31.2, -7.3, -5.7, 0.9, 49.6, 18.8, -21.3, 17.1, 3.6, 61.3, -0.1, 68.1, -16.7, -0.8, -5.6, 49.3, 30.8, 87.8, 46.9, 7.8, 39.0, 56.9, -6.1, 16.3, 41.0, 97.5, 20.7, 86.1, 11.4, 79.0, 54.2, 100.2, 71.4, 36.9, 48.8, 37.2, 62.9, 36.4, 12.8, 71.9, 21.6, 80.0, 42.4, 94.3, -9.8, 55.2, 56.2, 97.0, 30.3, 92.5, -16.3, 16.7, 53.2, 57.8, 51.5, 59.8, 50.0, 62.9, 48.6, 66.2, 43.8, 72.6, 42.8, 52.7, 41.4, 51.8, 40.3, 50.6, 34.4, 45.6, 5.4, 23.1, 43.7, 53.3, 1.7, 40.5, 38.1, 77.3, 58.3, 91.9, 59.8, 85.0, 48.3, 83.2, 25.2, 62.0, 41.9, 23.5, 30.4, 70.4, 24.3, 19.8, 33.9, 30.0, 16.4, 30.9, 45.0, 89.6, 17.4, 65.7, 25.3, 74.5, 21.6, 51.9, -5.7, 29.4, 11.0, 51.0, -13.5, 33.1, 27.0, 39.1, -15.4, -17.5, -21.4, -19.8, 80.0, 87.3, 103.4, 22.1, 76.8, 46.8, 74.1, 54.2, 82.4, 50.1, 85.2, 53.3, 78.6, 55.4, 81.5, 56.4, 89.2, 67.7, 121.1, 23.9, 94.6, 61.1, 111.9, 55.1, 87.4, 59.2, 85.6, 59.1, 75.5, 51.0, 80.5, 52.8, 83.7, 55.0, 86.4, 59.2, 84.2, 61.5, 84.7, 58.8, 79.7, 57.3, 76.8, 56.8, 72.7, 56.0, 69.5, 79.5, 71.8, 71.7, 72.3, 67.7, 72.3, 63.8, 71.7, 60.6, 79.2, 60.1, 80.5, 61.6, 81.8, 63.9, 82.4, 66.2, 92.5, 47.5, 126.2, 20.1, 81.5, 59.6, 82.9, 60.5, 79.5, 32.2, 86.9, 31.8, 99.4, 6.6, 109.1, 13.3, 84.1, 72.6, 135.7, 5.0, 127.9, 4.4, 120.5, 6.9, 109.5, 4.1, 132.1, 21.1, 92.0, 24.9, 119.7, 37.1, 102.3, 73.1, 97.6, 79.1, 132.1, 21.1, 110.5, 64.4, 78.6, 92.0, 96.2, 15.1, 85.2, 62.6, 126.2, 35.4, 65.9, 99.7, 82.0, 91.6, 89.2, 86.5, 88.3, 42.8, 79.1, 38.7, 93.8, 80.9, 86.3, 86.0, 68.6, 96.9, 104.5, 69.4, 74.9, 96.2, 125.7, 36.8, 75.9, 60.6, 77.2, 62.9, 77.8, 66.2, 78.1, 69.8, 77.7, 76.7, 83.7, 57.7, 85.5, 57.0, 86.9, 56.4, 94.8, 53.9, 119.7, 39.5, 81.9, 57.9, 113.2, 55.6, 79.1, 81.8, 70.2, 85.5, 93.3, 70.3, 96.2, 31.3, 86.5, 76.8, 110.8, 32.3, 100.7, 39.6, 111.4, 44.2, 70.3, 92.0, 95.7, 74.6, 87.8, 81.0, 99.8, 62.1, 120.2, 46.9, 105.4, 63.1, 118.8, 51.1, 102.0, 49.3, 136.3, 5.4, 131.1, 4.0]}, {"rect": [266, 455, 544, 733], "points": [0.36957, 0.05103, 0.08236, 0.0, -0.0596, 0.38227, -0.0038, 0.0, -0.09579, -0.03412, 0.37146, 0.0, -94.64397, -269.83861, -58.42295, 1.0, 69.2, 46.9, 72.3, 30.9, 68.6, 49.8, 67.7, 53.0, 66.8, 54.9, 65.5, 59.9, 65.4, 63.5, 64.6, 67.3, 63.7, 71.4, 61.3, 78.5, 33.2, 82.5, 36.5, 12.5, 61.4, 44.6, 60.3, 52.1, 51.8, 46.5, 45.1, 48.7, 53.1, 52.0, 47.4, 52.1, 32.4, 60.8, 13.0, 8.3, 29.2, 52.5, -17.7, 38.5, 36.0, 52.9, 37.8, 53.0, 60.5, 48.8, 52.5, 49.3, 46.1, 50.3, 36.9, 52.9, 40.0, 56.1, 38.7, 53.4, 47.9, 53.4, 53.6, 53.5, 59.9, 54.0, 52.1, 77.0, 55.3, 69.6, 56.3, 65.9, 57.7, 61.8, 58.6, 58.9, 47.1, 56.2, 45.6, 57.5, 43.8, 59.4, 42.0, 61.3, 40.5, 40.5, -23.3, -1.5, 43.3, 54.9, 41.5, 55.4, 64.4, 30.0, 53.1, 27.5, 44.6, -1.4, 31.8, 1.9, 37.3, 66.7, -5.8, -15.7, 7.0, -12.4, 15.9, -7.9, 30.5, -7.0, -6.3, 1.3, 48.9, 18.9, -21.9, 17.8, 3.3, 61.6, -0.6, 68.5, -17.3, -0.1, -6.2, 49.7, 30.6, 87.9, 46.5, 7.9, 38.3, 56.8, -6.7, 16.9, 41.0, 97.5, 20.4, 86.4, 11.2, 79.1, 53.9, 100.0, 70.9, 36.8, 48.4, 37.3, 62.2, 36.4, 12.5, 72.2, 21.3, 80.1, 42.4, 94.3, -10.3, 55.6, 56.1, 96.8, 30.0, 92.5, -16.9, 17.3, 52.6, 57.6, 51.1, 59.8, 49.3, 62.7, 48.0, 66.0, 43.7, 72.4, 42.3, 52.5, 41.0, 51.6, 39.7, 50.6, 33.8, 45.6, 4.8, 23.4, 43.3, 53.0, 1.1, 40.9, 37.8, 77.3, 58.1, 91.7, 59.8, 84.8, 48.3, 82.9, 24.7, 62.1, 41.4, 23.9, 30.1, 70.4, 23.6, 19.9, 33.3, 30.3, 15.8, 31.2, 44.8, 89.3, 17.1, 65.8, 25.0, 74.6, 21.2, 52.0, -6.2, 29.8, 10.7, 51.1, -14.0, 33.6, 26.4, 39.1, -16.1, -17.0, -22.3, -19.1, 79.7, 87.0, 102.7, 22.0, 76.2, 46.5, 73.4, 53.9, 82.0, 49.7, 84.8, 53.0, 78.0, 54.8, 81.1, 55.9, 88.8, 67.6, 120.5, 23.8, 94.0, 60.8, 111.5, 55.0, 86.7, 59.0, 85.2, 58.6, 75.1, 50.6, 80.1, 52.5, 83.0, 54.5, 85.8, 59.0, 83.9, 61.3, 84.3, 58.6, 79.3, 56.8, 76.2, 56.2, 72.0, 55.7, 69.4, 79.2, 71.4, 71.4, 71.9, 67.4, 71.9, 63.5, 71.0, 60.3, 78.7, 59.9, 79.9, 61.3, 81.2, 63.6, 82.0, 65.9, 92.1, 47.4, 125.7, 20.0, 81.1, 59.1, 82.5, 60.0, 79.1, 32.1, 86.5, 31.8, 98.9, 6.7, 108.6, 13.2, 83.8, 72.3, 135.0, 4.9, 127.1, 4.1, 119.8, 6.8, 108.7, 4.0, 131.4, 21.0, 91.5, 24.8, 119.3, 37.0, 102.1, 73.0, 97.3, 79.0, 131.4, 21.0, 110.1, 64.2, 78.3, 92.0, 95.7, 15.1, 84.8, 62.3, 125.7, 35.3, 65.8, 99.4, 81.9, 91.5, 88.9, 86.4, 87.9, 42.7, 78.7, 38.6, 93.5, 80.5, 86.0, 86.0, 68.5, 96.6, 104.2, 69.2, 74.6, 96.1, 125.3, 36.6, 75.5, 60.3, 76.6, 62.7, 77.4, 65.9, 77.5, 69.3, 77.3, 76.5, 83.0, 57.2, 84.9, 56.7, 86.6, 55.9, 94.3, 53.8, 119.3, 39.4, 81.5, 57.6, 112.8, 55.5, 78.8, 81.5, 69.9, 85.2, 93.0, 70.0, 95.7, 31.2, 86.2, 76.7, 110.1, 32.2, 100.0, 39.5, 111.0, 44.1, 70.0, 91.7, 95.4, 74.5, 87.5, 80.9, 99.4, 62.1, 119.8, 46.8, 105.0, 63.0, 118.3, 50.9, 101.4, 49.2, 135.5, 5.3, 130.4, 3.8]}, {"rect": [265, 454, 543, 732], "points": [0.36868, 0.04905, 0.08128, 0.0, -0.05789, 0.38161, -0.00358, 0.0, -0.09459, -0.03373, 0.3705, 0.0, -95.19131, -268.3457, -57.73987, 1.0, 69.2, 46.5, 72.3, 30.8, 68.7, 49.7, 67.7, 52.9, 66.8, 54.7, 65.5, 60.1, 65.5, 63.4, 64.7, 67.5, 63.7, 71.4, 61.7, 78.6, 33.7, 82.4, 36.5, 12.5, 61.3, 44.3, 60.4, 52.0, 52.0, 46.4, 45.2, 48.4, 53.1, 51.6, 47.4, 52.0, 32.8, 60.8, 13.3, 8.7, 29.5, 52.5, -17.0, 38.6, 36.3, 52.9, 37.9, 53.0, 60.8, 48.4, 52.6, 49.2, 46.1, 50.2, 36.9, 52.9, 40.1, 56.2, 38.7, 53.4, 48.0, 53.1, 53.9, 53.4, 60.0, 53.9, 52.5, 77.2, 55.3, 69.8, 56.4, 66.1, 57.7, 62.0, 58.7, 59.1, 47.1, 56.5, 45.7, 57.6, 43.8, 59.4, 42.0, 61.6, 40.6, 40.5, -23.0, -1.0, 43.3, 55.1, 41.6, 55.6, 64.1, 29.9, 53.3, 27.3, 44.6, -1.3, 31.8, 2.3, 37.4, 66.8, -5.6, -15.2, 7.3, -12.0, 16.5, -7.7, 30.8, -6.8, -6.0, 1.7, 48.9, 18.9, -21.6, 18.0, 3.8, 61.7, 0.0, 68.6, -17.0, 0.3, -5.5, 50.1, 31.3, 87.9, 46.5, 7.9, 38.3, 57.0, -6.4, 17.1, 41.4, 97.2, 20.8, 86.2, 11.6, 79.2, 54.4, 99.9, 71.0, 36.8, 48.5, 37.3, 62.3, 36.3, 13.0, 72.3, 21.7, 80.1, 42.8, 94.3, -9.6, 55.7, 56.3, 96.7, 30.5, 92.5, -16.5, 17.5, 52.6, 57.9, 51.2, 59.8, 49.4, 62.9, 48.0, 66.2, 43.8, 72.6, 42.4, 52.5, 41.0, 51.6, 39.7, 50.6, 34.1, 45.7, 5.1, 23.6, 43.4, 53.0, 1.5, 41.0, 38.3, 77.4, 58.5, 91.6, 59.9, 84.7, 48.5, 82.8, 25.3, 62.1, 41.5, 23.9, 30.5, 70.4, 23.9, 20.2, 33.6, 30.3, 16.1, 31.3, 45.2, 89.3, 17.5, 65.8, 25.4, 74.6, 21.6, 52.1, -5.6, 30.0, 11.1, 51.2, -13.4, 34.0, 26.7, 39.2, -16.1, -16.6, -22.1, -18.8, 80.1, 86.6, 102.7, 21.7, 76.4, 46.1, 73.7, 53.5, 82.0, 49.3, 85.1, 52.9, 78.2, 54.4, 81.1, 55.8, 88.9, 67.3, 120.2, 23.4, 94.0, 60.7, 111.9, 54.3, 87.0, 58.9, 85.3, 58.5, 75.2, 50.2, 80.2, 52.4, 83.3, 54.3, 86.1, 58.9, 83.9, 61.2, 84.4, 58.5, 79.6, 56.6, 76.4, 55.8, 72.3, 55.3, 69.6, 79.1, 71.4, 71.4, 72.0, 67.5, 71.9, 63.5, 71.1, 60.2, 78.8, 59.8, 80.1, 61.3, 81.5, 63.5, 82.1, 65.9, 92.1, 47.0, 125.7, 19.4, 81.1, 59.3, 82.6, 60.2, 78.8, 31.8, 86.5, 31.7, 98.6, 6.5, 108.6, 12.9, 83.9, 72.2, 134.9, 4.5, 127.0, 3.8, 119.7, 6.5, 108.6, 3.7, 131.5, 20.4, 91.3, 24.5, 119.6, 36.4, 102.2, 72.4, 97.6, 78.4, 131.6, 20.4, 110.4, 63.6, 78.7, 91.6, 95.7, 14.8, 85.1, 62.5, 125.7, 34.6, 66.3, 99.1, 82.3, 91.1, 89.3, 86.1, 87.9, 42.4, 78.7, 38.3, 93.9, 80.2, 86.2, 85.6, 68.7, 96.3, 104.5, 68.6, 75.0, 95.8, 125.3, 36.0, 75.6, 60.2, 76.6, 62.6, 77.4, 65.8, 77.5, 69.4, 77.4, 76.3, 83.3, 57.1, 85.2, 56.6, 86.6, 55.8, 94.3, 53.4, 119.3, 38.8, 81.6, 57.5, 112.9, 54.9, 79.2, 81.4, 70.1, 85.1, 93.1, 69.9, 95.7, 30.9, 86.5, 76.4, 110.1, 31.8, 100.0, 39.1, 111.0, 43.8, 70.4, 91.5, 95.7, 74.2, 87.6, 80.5, 99.5, 61.7, 120.0, 46.1, 105.0, 62.5, 118.4, 50.3, 101.4, 48.8, 135.4, 4.7, 130.4, 3.2]}, {"rect": [264, 453, 542, 731], "points": [0.36795, 0.0474, 0.08055, 0.0, -0.05595, 0.38075, -0.00435, 0.0, -0.09394, -0.03317, 0.36931, 0.0, -96.04406, -266.85021, -56.67987, 1.0, 69.7, 46.1, 72.2, 30.8, 68.9, 49.3, 68.0, 52.5, 67.1, 54.3, 66.0, 59.5, 65.7, 63.1, 65.2, 67.0, 64.3, 71.1, 62.0, 78.0, 34.1, 82.4, 36.8, 12.8, 61.6, 44.2, 60.6, 51.6, 52.3, 46.1, 45.4, 48.4, 53.6, 51.5, 47.5, 51.9, 33.2, 60.8, 13.4, 8.8, 29.7, 52.6, -16.6, 38.8, 36.4, 52.9, 38.2, 53.0, 61.0, 48.3, 52.8, 48.9, 46.4, 50.2, 37.3, 52.9, 40.1, 56.2, 38.8, 53.4, 48.3, 53.0, 54.1, 53.3, 60.5, 53.7, 52.9, 76.7, 55.6, 69.3, 56.9, 65.6, 58.2, 61.7, 59.2, 58.6, 47.4, 56.2, 46.0, 57.5, 44.1, 59.4, 42.3, 61.4, 40.9, 40.5, -22.9, -0.8, 43.3, 54.9, 41.9, 55.4, 64.4, 29.9, 53.4, 27.5, 44.6, -1.0, 31.8, 2.3, 37.8, 66.7, -5.5, -14.8, 7.4, -11.6, 16.6, -7.4, 30.8, -6.5, -5.9, 1.9, 49.1, 18.9, -21.2, 18.4, 4.2, 61.8, 0.5, 68.6, -16.9, 0.5, -5.1, 50.2, 31.7, 87.6, 46.4, 8.2, 38.7, 57.1, -6.0, 17.5, 41.8, 97.2, 21.5, 86.2, 12.1, 79.2, 54.8, 99.8, 71.2, 36.4, 48.7, 37.3, 62.5, 36.3, 13.4, 72.3, 22.1, 80.1, 43.3, 94.0, -9.1, 55.8, 57.0, 96.6, 31.2, 92.5, -16.1, 17.9, 52.9, 57.6, 51.5, 59.5, 49.7, 62.7, 48.3, 66.0, 44.2, 72.3, 42.4, 52.5, 41.0, 51.6, 40.0, 50.6, 34.5, 45.9, 5.5, 23.9, 43.7, 52.9, 1.8, 41.4, 38.7, 77.3, 58.9, 91.2, 60.3, 84.4, 49.1, 82.5, 25.5, 62.1, 41.5, 23.9, 30.9, 70.4, 24.0, 20.3, 33.7, 30.4, 16.2, 31.4, 45.6, 89.0, 18.0, 65.9, 25.8, 74.6, 21.8, 52.1, -5.4, 30.4, 11.5, 51.5, -13.2, 34.2, 26.8, 39.2, -16.1, -16.1, -22.1, -18.4, 80.5, 86.5, 102.8, 21.5, 76.6, 46.0, 73.9, 53.3, 82.2, 49.2, 85.4, 52.5, 78.5, 54.3, 81.4, 55.6, 89.2, 67.1, 120.3, 23.0, 94.3, 60.3, 112.2, 53.9, 87.3, 58.9, 85.5, 58.4, 75.6, 50.0, 80.3, 52.0, 83.6, 54.2, 86.4, 58.9, 84.4, 61.1, 84.9, 58.4, 79.9, 56.5, 76.7, 55.6, 72.5, 55.1, 69.9, 78.7, 71.7, 71.1, 72.4, 67.0, 72.2, 63.1, 71.5, 59.9, 79.0, 59.4, 80.4, 61.2, 81.7, 63.4, 82.6, 65.8, 92.3, 46.9, 125.9, 19.2, 81.4, 59.0, 83.0, 59.9, 79.0, 31.7, 86.4, 31.6, 98.7, 6.4, 108.5, 12.7, 84.1, 71.8, 135.0, 4.1, 126.9, 3.6, 119.5, 6.4, 108.2, 3.6, 131.5, 20.1, 91.4, 24.3, 119.6, 36.2, 102.5, 72.2, 98.0, 78.2, 131.5, 20.1, 110.7, 63.4, 79.1, 91.5, 95.6, 14.7, 85.4, 62.2, 125.9, 34.4, 66.7, 98.9, 82.7, 90.7, 89.6, 85.7, 87.9, 42.2, 78.7, 38.1, 94.2, 80.0, 86.5, 85.2, 69.4, 96.2, 104.9, 68.2, 75.4, 95.6, 125.5, 35.7, 75.8, 59.9, 77.0, 62.2, 77.7, 65.5, 78.0, 69.1, 77.8, 76.0, 83.6, 57.1, 85.4, 56.5, 86.9, 55.7, 94.3, 53.2, 119.5, 38.6, 81.9, 57.4, 113.1, 54.7, 79.6, 81.0, 70.4, 84.7, 93.3, 69.5, 95.6, 30.8, 86.8, 76.0, 110.3, 31.6, 100.2, 38.7, 111.2, 43.6, 70.8, 91.2, 96.0, 74.0, 87.9, 80.1, 99.8, 61.5, 120.0, 45.9, 105.3, 62.1, 118.6, 50.1, 101.6, 48.6, 135.6, 4.5, 130.5, 2.8]}, {"rect": [263, 452, 541, 730], "points": [0.36668, 0.04546, 0.08027, 0.0, -0.05392, 0.38005, -0.00377, 0.0, -0.09277, -0.03284, 0.36774, 0.0, -96.69947, -265.36923, -56.82607, 1.0, 69.4, 45.7, 72.0, 30.7, 68.9, 48.9, 68.0, 52.1, 67.1, 53.9, 65.8, 59.4, 65.7, 63.0, 65.2, 67.1, 64.3, 71.2, 61.9, 78.1, 34.5, 82.4, 36.8, 12.8, 61.5, 43.8, 60.7, 51.2, 52.1, 46.0, 45.3, 48.3, 53.5, 51.2, 47.6, 51.6, 33.5, 60.7, 13.4, 9.1, 30.2, 52.8, -16.2, 39.2, 36.5, 52.9, 38.3, 53.0, 61.1, 47.9, 52.9, 48.8, 46.5, 50.1, 37.4, 52.9, 40.2, 56.1, 38.9, 53.4, 48.4, 52.9, 54.0, 53.0, 60.3, 53.1, 53.0, 76.8, 55.7, 69.5, 57.0, 65.7, 58.1, 61.6, 59.3, 58.5, 47.5, 56.2, 46.1, 57.5, 44.2, 59.4, 42.4, 61.6, 41.0, 40.5, -22.6, -0.4, 43.4, 54.8, 42.0, 55.6, 64.1, 29.9, 53.4, 27.5, 44.3, -1.0, 31.8, 2.6, 38.2, 66.7, -5.5, -14.4, 7.7, -11.5, 16.9, -7.0, 30.9, -6.4, -5.6, 2.3, 48.9, 18.9, -20.8, 18.6, 4.9, 62.1, 1.2, 68.7, -16.6, 1.0, -4.7, 50.3, 32.2, 87.6, 46.2, 8.2, 38.8, 57.1, -5.7, 17.8, 42.0, 97.1, 21.7, 86.2, 12.7, 79.3, 55.2, 99.5, 71.0, 36.3, 48.8, 37.2, 62.3, 35.9, 14.1, 72.4, 22.6, 80.1, 43.7, 93.9, -8.4, 56.2, 57.2, 96.3, 31.4, 92.5, -15.8, 18.1, 53.0, 57.5, 51.6, 59.7, 49.7, 62.6, 48.4, 66.2, 44.6, 72.3, 42.5, 52.4, 41.1, 51.5, 40.1, 50.3, 34.8, 45.9, 5.9, 24.3, 43.8, 52.9, 2.2, 41.5, 39.1, 77.3, 59.0, 91.1, 60.5, 84.3, 49.3, 82.4, 26.1, 62.1, 41.5, 23.9, 31.3, 70.4, 24.3, 20.6, 34.0, 30.4, 16.5, 31.7, 46.0, 88.9, 18.4, 65.9, 26.2, 74.5, 22.4, 52.4, -4.8, 30.7, 11.9, 51.6, -12.6, 34.5, 27.4, 39.5, -16.0, -15.7, -22.0, -17.9, 80.6, 86.1, 102.1, 21.2, 76.3, 45.6, 73.7, 52.9, 81.9, 48.8, 85.1, 52.4, 78.2, 53.8, 81.4, 55.3, 89.0, 66.7, 119.6, 22.6, 94.1, 59.9, 112.0, 53.3, 87.0, 58.8, 85.6, 58.3, 75.4, 49.4, 80.1, 51.6, 83.3, 53.8, 86.2, 58.8, 84.2, 60.8, 84.7, 58.3, 79.7, 56.1, 76.5, 55.2, 72.3, 54.4, 70.0, 78.4, 71.7, 71.2, 72.3, 67.1, 72.2, 63.0, 71.3, 59.8, 78.8, 59.3, 80.2, 61.1, 81.5, 63.1, 82.4, 65.7, 91.9, 46.5, 125.5, 18.4, 81.4, 58.8, 82.8, 59.8, 78.6, 31.4, 86.0, 31.3, 98.0, 6.1, 107.9, 12.1, 84.0, 71.4, 134.3, 3.5, 126.3, 3.3, 118.9, 6.0, 107.8, 3.4, 130.9, 19.5, 91.0, 24.0, 119.4, 35.4, 102.4, 71.5, 98.1, 77.5, 131.0, 19.5, 110.3, 62.5, 79.2, 90.9, 95.1, 14.3, 85.2, 62.1, 125.5, 33.8, 66.9, 98.6, 82.6, 90.4, 89.5, 85.3, 87.7, 41.6, 78.5, 37.8, 94.1, 79.4, 86.6, 84.8, 69.5, 95.8, 105.0, 67.5, 75.6, 95.0, 125.0, 34.9, 75.6, 59.8, 76.8, 62.1, 77.7, 65.4, 77.8, 69.0, 77.9, 75.6, 83.4, 56.9, 85.2, 56.2, 86.9, 55.6, 94.1, 52.6, 119.0, 37.9, 81.9, 57.1, 112.9, 54.0, 79.7, 80.7, 70.6, 84.4, 93.1, 69.1, 95.1, 30.4, 86.7, 75.6, 109.8, 31.0, 99.7, 38.3, 110.7, 42.9, 70.9, 90.8, 95.9, 73.4, 88.0, 79.8, 99.6, 60.9, 119.6, 45.3, 105.1, 61.4, 118.2, 49.5, 101.4, 48.0, 135.0, 3.9, 130.0, 2.2]}, {"rect": [262, 450, 540, 728], "points": [0.36592, 0.04395, 0.07978, 0.0, -0.05228, 0.37938, -0.00401, 0.0, -0.09193, -0.03178, 0.36669, 0.0, -97.29927, -263.79133, -56.29729, 1.0, 68.9, 46.1, 72.2, 30.9, 68.4, 49.2, 67.5, 52.4, 66.9, 54.2, 65.6, 59.8, 65.5, 63.2, 65.0, 67.6, 64.2, 71.6, 62.5, 78.3, 35.1, 82.8, 36.8, 13.3, 61.1, 44.2, 60.5, 51.5, 52.2, 46.4, 45.6, 48.7, 53.5, 51.5, 47.9, 52.0, 33.9, 61.2, 13.7, 9.7, 30.6, 53.2, -15.8, 40.1, 36.9, 53.4, 38.7, 53.5, 60.6, 48.3, 52.7, 49.2, 46.6, 50.6, 37.8, 53.4, 40.6, 56.6, 39.5, 53.8, 48.5, 53.3, 54.0, 53.3, 60.1, 53.4, 53.3, 77.2, 55.8, 70.2, 56.8, 65.9, 58.1, 61.8, 59.1, 59.0, 47.8, 56.6, 46.2, 57.9, 44.3, 59.8, 42.8, 62.1, 41.3, 40.9, -22.3, 0.6, 43.8, 55.3, 42.4, 55.8, 64.4, 30.2, 53.4, 27.9, 44.5, -0.5, 32.1, 3.1, 38.5, 67.1, -5.2, -13.7, 7.8, -10.7, 16.9, -6.4, 31.1, -5.7, -5.3, 3.1, 49.2, 19.3, -20.4, 19.7, 5.3, 62.6, 1.7, 69.5, -16.3, 1.8, -4.3, 51.1, 32.6, 88.2, 46.4, 8.7, 39.2, 57.5, -5.6, 18.4, 42.7, 97.6, 22.4, 86.9, 13.2, 80.0, 55.7, 99.9, 71.2, 36.7, 49.1, 37.6, 62.5, 36.3, 14.6, 73.1, 23.2, 80.5, 44.1, 94.3, -8.0, 57.0, 57.8, 96.6, 32.0, 93.0, -15.4, 18.9, 53.1, 57.9, 51.6, 59.9, 49.8, 63.0, 48.5, 66.7, 45.0, 72.7, 42.9, 52.9, 41.5, 52.0, 40.5, 51.0, 34.9, 46.4, 6.2, 24.8, 43.9, 53.4, 2.6, 42.2, 39.5, 77.7, 59.4, 91.5, 61.1, 84.6, 49.6, 82.8, 26.5, 62.5, 41.8, 24.4, 31.9, 70.9, 24.7, 21.1, 34.3, 30.8, 16.8, 32.2, 46.4, 89.3, 18.8, 66.6, 26.9, 75.0, 22.8, 52.8, -4.7, 31.3, 12.2, 52.3, -12.2, 35.4, 27.5, 39.9, -15.7, -14.7, -21.7, -17.0, 80.9, 86.2, 102.2, 21.3, 75.8, 45.7, 73.4, 53.0, 81.6, 48.9, 84.9, 52.5, 78.0, 53.9, 81.1, 55.6, 89.3, 66.8, 119.7, 22.6, 94.3, 59.9, 112.3, 53.8, 87.0, 58.9, 85.5, 58.5, 74.9, 49.7, 79.8, 51.6, 83.3, 53.9, 86.4, 58.8, 84.2, 61.1, 84.7, 58.4, 79.6, 56.1, 76.5, 55.3, 72.1, 54.7, 70.4, 78.7, 71.6, 71.6, 72.0, 67.2, 71.9, 63.2, 71.1, 60.0, 78.8, 59.4, 80.1, 61.2, 81.5, 63.4, 82.4, 65.8, 92.1, 46.5, 125.7, 18.9, 81.4, 58.9, 82.8, 59.9, 79.0, 31.7, 86.4, 31.4, 98.1, 6.4, 107.8, 12.5, 84.5, 71.4, 134.4, 3.8, 126.1, 3.6, 118.8, 6.3, 107.7, 3.9, 130.8, 19.8, 91.1, 24.4, 119.7, 35.9, 102.7, 71.8, 98.5, 77.8, 131.2, 19.8, 110.6, 63.0, 79.6, 91.2, 95.2, 14.7, 85.2, 62.2, 125.7, 34.0, 67.5, 98.9, 83.2, 90.7, 90.1, 85.6, 87.9, 41.9, 78.7, 38.1, 94.4, 79.6, 87.0, 85.1, 69.9, 96.2, 105.4, 68.1, 76.0, 95.3, 125.2, 35.4, 75.6, 59.9, 76.6, 62.3, 77.5, 65.7, 77.9, 69.4, 78.2, 75.9, 83.4, 57.0, 85.2, 56.5, 86.6, 55.6, 94.3, 52.9, 119.2, 38.2, 81.9, 57.1, 113.2, 54.3, 80.0, 81.0, 71.2, 84.7, 93.4, 69.1, 95.3, 30.7, 87.0, 75.9, 110.0, 31.3, 99.9, 38.6, 110.9, 43.2, 71.3, 91.1, 96.2, 73.6, 88.3, 80.1, 99.8, 61.1, 120.1, 45.6, 105.4, 61.7, 118.7, 49.7, 101.6, 48.3, 135.0, 4.2, 129.9, 2.5]}, {"rect": [261, 449, 539, 727], "points": [0.36552, 0.04241, 0.07829, 0.0, -0.05064, 0.37855, -0.00374, 0.0, -0.09106, -0.03054, 0.36637, 0.0, -98.15931, -262.25324, -55.39725, 1.0, 69.1, 46.0, 72.2, 30.6, 68.6, 48.9, 67.8, 51.8, 66.9, 53.6, 65.8, 59.6, 65.5, 63.1, 65.1, 67.3, 64.4, 71.2, 62.6, 78.0, 35.1, 82.6, 36.8, 13.1, 61.3, 43.8, 60.5, 51.2, 52.5, 46.1, 45.7, 48.5, 53.9, 51.2, 48.3, 51.7, 34.0, 60.9, 13.8, 9.8, 30.5, 52.8, -15.6, 40.5, 37.3, 53.1, 39.1, 53.5, 60.9, 48.0, 53.0, 48.9, 47.0, 50.3, 38.2, 53.2, 41.0, 56.4, 40.0, 53.6, 48.8, 52.8, 54.4, 52.7, 60.4, 53.0, 53.4, 76.7, 56.1, 69.7, 57.1, 65.6, 58.2, 61.8, 59.4, 58.9, 47.9, 56.4, 46.5, 57.7, 44.7, 59.5, 42.9, 61.8, 41.1, 40.7, -22.4, 1.2, 44.2, 55.3, 42.8, 55.8, 64.3, 29.7, 53.4, 27.5, 44.3, -0.7, 31.9, 3.0, 38.6, 66.9, -5.4, -13.3, 7.8, -10.6, 16.7, -6.3, 30.8, -5.8, -5.4, 3.3, 49.2, 19.1, -20.5, 20.2, 5.2, 62.7, 1.9, 69.6, -16.5, 2.3, -4.1, 51.2, 32.7, 88.0, 46.1, 8.5, 39.6, 57.3, -5.5, 18.6, 42.9, 97.3, 22.6, 86.7, 13.4, 80.1, 56.1, 99.6, 71.0, 36.2, 48.9, 37.2, 62.5, 35.8, 14.8, 72.9, 23.2, 80.3, 44.2, 94.0, -7.8, 57.1, 58.0, 96.3, 32.2, 92.7, -15.5, 19.3, 53.4, 57.7, 51.7, 59.9, 50.2, 62.8, 48.8, 66.5, 45.1, 72.4, 43.3, 52.6, 41.9, 51.7, 40.6, 50.8, 35.0, 45.9, 6.1, 24.9, 44.3, 53.1, 2.5, 42.1, 39.6, 77.5, 59.8, 91.0, 61.2, 84.4, 49.7, 82.6, 26.4, 62.3, 41.8, 24.1, 31.9, 70.6, 24.5, 20.9, 34.1, 30.6, 16.7, 32.0, 46.5, 89.0, 18.9, 66.4, 26.8, 74.7, 22.6, 52.6, -4.5, 31.4, 12.1, 52.1, -12.2, 35.5, 27.3, 39.7, -15.7, -14.3, -21.6, -16.5, 81.0, 85.9, 102.2, 20.9, 76.0, 45.6, 73.7, 52.6, 81.6, 48.5, 84.8, 52.1, 77.9, 53.6, 81.1, 55.0, 89.3, 66.4, 119.7, 22.3, 94.4, 59.5, 112.4, 53.5, 86.7, 58.3, 85.3, 58.1, 75.1, 49.4, 79.8, 51.3, 83.0, 53.6, 86.2, 58.3, 83.9, 60.5, 84.4, 57.9, 79.3, 55.6, 76.5, 54.9, 72.3, 54.1, 70.5, 78.4, 71.8, 71.1, 72.3, 66.9, 71.9, 63.1, 71.4, 59.9, 78.8, 59.1, 80.1, 60.9, 81.5, 62.9, 82.4, 65.5, 92.1, 46.2, 125.7, 18.9, 81.1, 58.6, 82.5, 59.5, 78.7, 31.5, 86.1, 31.1, 98.0, 6.1, 107.7, 12.1, 84.3, 71.1, 134.1, 3.7, 125.8, 3.0, 118.4, 5.8, 107.3, 3.4, 130.8, 19.5, 91.1, 24.0, 119.8, 35.6, 103.1, 71.5, 98.6, 77.5, 131.2, 19.5, 110.9, 62.7, 79.7, 90.9, 94.9, 14.4, 85.2, 61.8, 125.7, 33.7, 67.7, 98.7, 83.4, 90.4, 90.3, 85.3, 87.9, 41.6, 78.7, 37.6, 94.5, 79.3, 87.1, 84.8, 70.0, 95.9, 105.5, 67.8, 76.4, 95.0, 125.3, 35.1, 75.6, 59.6, 76.6, 62.2, 77.5, 65.4, 77.9, 69.1, 78.3, 75.3, 83.4, 56.4, 84.9, 55.9, 86.6, 55.1, 94.4, 52.3, 119.2, 37.8, 81.6, 56.8, 113.3, 53.9, 80.1, 80.7, 71.3, 84.4, 93.5, 68.8, 95.3, 30.2, 87.0, 75.3, 110.0, 31.0, 99.9, 38.0, 110.9, 42.6, 71.4, 90.8, 96.3, 73.3, 88.4, 79.7, 99.9, 60.5, 120.1, 45.3, 105.5, 61.4, 118.8, 49.4, 101.4, 48.0, 134.9, 4.1, 129.9, 2.7]}, {"rect": [261, 448, 539, 726], "points": [0.36503, 0.04111, 0.0772, 0.0, -0.04909, 0.37797, -0.00444, 0.0, -0.08998, -0.02987, 0.36536, 0.0, -99.02374, -260.99675, -54.20854, 1.0, 68.9, 45.7, 71.7, 30.8, 68.4, 48.8, 67.8, 51.7, 67.0, 53.5, 65.6, 59.8, 65.5, 63.1, 65.1, 67.1, 64.2, 71.2, 62.3, 78.0, 34.8, 82.6, 36.1, 13.4, 61.4, 43.8, 60.5, 51.1, 52.3, 46.1, 45.6, 48.7, 53.7, 51.2, 48.2, 51.9, 33.5, 61.0, 13.2, 10.2, 29.9, 52.8, -15.8, 40.9, 37.3, 53.4, 39.1, 53.8, 60.9, 47.9, 52.8, 48.8, 46.9, 50.3, 38.2, 53.5, 40.9, 56.6, 40.0, 53.9, 48.8, 52.9, 54.2, 52.6, 60.2, 52.9, 53.1, 76.7, 55.9, 69.5, 56.9, 65.6, 58.2, 61.8, 59.2, 59.0, 47.8, 56.6, 46.4, 57.7, 44.6, 59.6, 43.1, 61.9, 40.7, 40.7, -22.5, 1.7, 44.1, 55.4, 42.7, 55.9, 63.6, 29.9, 52.7, 27.7, 43.8, -0.4, 31.4, 3.3, 38.1, 67.0, -5.9, -12.9, 7.1, -10.4, 16.2, -5.9, 30.2, -5.5, -5.8, 3.7, 48.5, 19.4, -20.5, 20.6, 5.0, 63.0, 1.6, 69.9, -16.8, 2.7, -4.4, 51.5, 32.4, 88.0, 45.7, 8.8, 39.5, 57.6, -5.8, 18.9, 42.8, 97.6, 22.3, 87.0, 13.1, 80.2, 55.8, 99.5, 70.5, 36.4, 48.5, 37.4, 61.9, 35.9, 14.5, 73.2, 23.1, 80.6, 44.0, 94.0, -8.0, 57.5, 57.7, 96.3, 32.0, 93.0, -15.8, 19.7, 53.2, 57.7, 51.8, 60.0, 50.0, 62.9, 48.7, 66.6, 44.8, 72.5, 43.2, 52.6, 41.8, 51.9, 40.5, 51.0, 34.4, 46.2, 5.8, 25.0, 44.2, 53.4, 2.2, 42.4, 39.3, 77.5, 59.5, 91.2, 60.9, 84.4, 49.4, 82.6, 26.0, 62.3, 41.2, 24.4, 31.5, 70.9, 24.1, 21.2, 33.5, 30.9, 16.4, 32.3, 46.2, 89.0, 18.6, 66.5, 26.5, 74.8, 22.1, 52.7, -4.8, 31.8, 11.9, 52.2, -12.3, 35.9, 27.0, 39.8, -16.0, -13.9, -22.0, -15.8, 80.7, 86.0, 101.7, 21.1, 75.8, 45.5, 73.5, 52.5, 81.4, 48.7, 84.6, 52.0, 77.7, 53.5, 80.6, 54.9, 88.9, 66.4, 119.2, 22.4, 94.0, 59.5, 112.1, 53.6, 86.2, 58.4, 84.8, 58.1, 74.8, 49.3, 79.5, 51.2, 82.8, 53.5, 85.7, 58.2, 83.4, 60.5, 83.9, 58.0, 78.8, 55.7, 76.0, 54.8, 72.1, 54.0, 70.1, 78.4, 71.7, 70.9, 72.0, 66.9, 71.7, 62.8, 71.1, 59.9, 78.3, 59.0, 79.7, 60.8, 81.0, 63.1, 82.0, 65.5, 91.6, 46.1, 125.1, 19.0, 80.7, 58.5, 82.1, 59.5, 78.2, 31.4, 85.6, 31.3, 97.5, 6.0, 107.2, 12.3, 84.0, 71.0, 133.6, 3.6, 125.0, 3.1, 117.7, 5.9, 106.6, 3.6, 130.3, 19.6, 90.6, 24.0, 119.4, 35.7, 102.8, 71.4, 98.3, 77.7, 130.5, 19.6, 110.6, 62.6, 79.4, 91.1, 94.4, 14.3, 84.7, 61.8, 125.3, 33.6, 67.4, 98.6, 83.1, 90.3, 90.0, 85.2, 87.4, 41.5, 78.2, 37.7, 94.1, 79.2, 87.1, 84.8, 69.7, 95.8, 105.2, 67.9, 76.1, 95.2, 124.9, 35.2, 75.4, 59.8, 76.3, 62.2, 77.2, 65.2, 77.7, 68.9, 77.9, 75.2, 82.9, 56.3, 84.7, 55.8, 86.2, 55.2, 94.0, 52.5, 118.7, 37.7, 81.1, 56.7, 112.8, 53.8, 79.8, 80.6, 71.0, 84.3, 93.1, 68.7, 94.8, 30.4, 86.7, 75.5, 109.5, 30.9, 99.4, 38.2, 110.4, 42.7, 71.0, 90.8, 95.9, 73.2, 88.1, 79.6, 99.5, 60.4, 119.7, 45.4, 105.1, 61.6, 118.4, 49.5, 100.9, 47.9, 134.5, 4.0, 129.5, 2.8]}, {"rect": [260, 447, 538, 725], "points": [0.36436, 0.03948, 0.07576, 0.0, -0.04748, 0.37742, -0.00441, 0.0, -0.08792, -0.02963, 0.36352, 0.0, -99.46948, -259.67115, -53.25031, 1.0, 68.4, 45.6, 71.5, 30.8, 68.0, 48.5, 67.4, 51.6, 66.6, 53.5, 65.2, 59.9, 65.1, 63.2, 64.7, 67.7, 63.9, 71.8, 62.6, 78.3, 35.4, 82.9, 36.4, 13.8, 61.0, 43.8, 60.1, 50.8, 52.2, 46.1, 45.7, 48.5, 53.6, 51.2, 48.1, 51.7, 34.1, 61.3, 13.7, 10.6, 30.7, 53.4, -15.1, 41.1, 37.7, 53.5, 39.3, 53.9, 60.5, 47.6, 52.7, 48.8, 47.0, 50.3, 38.6, 53.8, 41.1, 56.8, 40.2, 53.9, 48.9, 52.9, 54.4, 52.6, 60.1, 52.7, 53.4, 77.0, 55.6, 70.3, 56.8, 66.2, 57.8, 62.2, 58.8, 59.1, 48.0, 56.8, 46.6, 58.1, 44.7, 59.9, 43.0, 62.2, 41.0, 41.0, -22.0, 1.9, 44.3, 55.7, 42.9, 56.2, 63.6, 29.9, 52.9, 27.7, 43.8, -0.1, 31.7, 3.7, 38.7, 67.3, -5.6, -12.5, 7.4, -10.0, 16.2, -5.5, 30.4, -5.1, -5.5, 4.2, 48.8, 19.7, -19.9, 20.8, 5.9, 63.2, 2.3, 70.1, -16.2, 2.9, -3.7, 51.7, 33.1, 88.1, 46.0, 9.1, 39.6, 57.7, -5.2, 19.4, 43.3, 97.7, 23.0, 87.1, 13.8, 80.3, 56.2, 99.6, 70.5, 36.4, 48.8, 37.7, 62.2, 36.0, 15.2, 73.3, 23.5, 80.7, 44.6, 94.1, -7.3, 57.7, 58.1, 96.3, 32.7, 93.1, -15.2, 19.9, 53.1, 58.1, 51.7, 60.3, 49.9, 63.5, 48.6, 67.1, 45.1, 72.8, 43.4, 52.6, 42.0, 51.8, 41.0, 50.8, 35.0, 46.5, 6.3, 25.4, 44.6, 53.4, 3.1, 42.8, 39.7, 77.8, 59.9, 91.3, 61.3, 84.4, 49.8, 82.9, 26.7, 62.7, 41.4, 24.5, 32.2, 71.0, 24.4, 21.6, 34.0, 31.2, 17.0, 32.7, 46.6, 89.3, 19.3, 66.8, 27.1, 75.1, 22.9, 53.0, -4.2, 32.2, 12.7, 52.6, -11.6, 36.1, 27.6, 40.1, -15.7, -13.7, -21.6, -15.6, 81.1, 85.8, 101.4, 21.1, 75.3, 45.2, 73.1, 52.2, 81.2, 48.4, 84.4, 51.7, 77.5, 53.4, 80.7, 54.8, 89.0, 66.4, 119.0, 22.2, 94.1, 59.5, 112.7, 53.1, 86.5, 58.2, 84.9, 58.1, 74.4, 49.0, 79.4, 51.1, 82.6, 53.4, 85.8, 58.1, 83.5, 60.5, 84.2, 58.0, 78.9, 55.4, 76.1, 54.5, 72.0, 53.9, 70.5, 78.4, 71.5, 71.4, 71.6, 67.2, 71.5, 63.1, 70.7, 60.0, 78.4, 59.1, 79.7, 60.8, 81.1, 63.1, 82.0, 65.5, 91.7, 46.1, 125.6, 18.5, 80.7, 58.5, 82.1, 59.5, 78.0, 31.7, 85.4, 31.3, 97.2, 6.0, 106.9, 12.1, 84.3, 71.1, 133.6, 3.3, 125.2, 2.8, 118.2, 5.6, 106.8, 3.3, 130.3, 19.3, 90.4, 24.0, 119.7, 35.2, 103.1, 71.4, 99.0, 77.4, 130.8, 19.0, 111.0, 62.3, 80.1, 90.9, 94.1, 14.3, 84.8, 61.8, 125.3, 33.3, 67.8, 98.7, 83.7, 90.3, 90.6, 84.9, 87.3, 41.5, 78.1, 37.7, 94.8, 78.9, 87.5, 84.7, 70.4, 95.8, 105.9, 67.5, 76.5, 95.0, 125.2, 34.7, 75.2, 59.9, 76.2, 62.2, 77.1, 65.4, 77.5, 69.2, 78.3, 75.5, 83.0, 56.2, 84.7, 55.8, 86.2, 55.0, 94.0, 52.5, 118.5, 37.4, 81.2, 56.7, 112.9, 53.5, 80.2, 80.6, 71.4, 84.4, 93.5, 68.6, 94.6, 30.4, 87.1, 75.2, 109.2, 30.8, 99.2, 38.2, 110.2, 42.4, 71.4, 90.8, 96.3, 72.9, 88.5, 79.4, 99.6, 60.4, 119.8, 44.8, 105.4, 61.3, 118.8, 49.0, 101.0, 47.9, 134.5, 3.7, 129.8, 2.1]}, {"rect": [260, 446, 538, 724], "points": [0.36363, 0.03805, 0.07477, 0.0, -0.04574, 0.37729, -0.00493, 0.0, -0.08666, -0.02879, 0.36271, 0.0, -100.21992, -258.62897, -52.18957, 1.0, 68.5, 45.6, 71.1, 30.8, 68.0, 48.7, 67.3, 51.9, 66.6, 53.8, 65.3, 60.1, 65.0, 63.6, 64.5, 67.9, 63.9, 72.0, 62.6, 78.4, 35.4, 83.3, 36.0, 14.2, 60.8, 43.7, 60.2, 51.1, 52.0, 46.1, 45.9, 48.8, 53.7, 51.5, 48.2, 52.0, 34.1, 61.7, 13.4, 11.0, 30.7, 53.8, -14.9, 41.5, 37.7, 53.9, 39.4, 54.3, 60.3, 47.8, 52.8, 48.8, 46.9, 50.6, 38.6, 54.2, 41.3, 57.1, 40.3, 54.3, 49.1, 53.0, 54.2, 52.9, 60.2, 52.9, 53.4, 77.4, 55.7, 70.6, 56.7, 66.5, 57.9, 62.4, 58.8, 59.5, 47.9, 57.2, 46.5, 58.5, 44.6, 60.4, 43.2, 62.6, 41.0, 41.4, -22.1, 2.4, 44.2, 55.8, 42.8, 56.6, 63.2, 30.0, 52.6, 28.0, 43.4, 0.1, 31.3, 4.1, 38.7, 67.7, -5.9, -12.2, 7.0, -9.6, 15.9, -5.1, 30.0, -4.9, -5.8, 4.6, 48.4, 19.8, -19.8, 21.3, 5.9, 63.6, 2.3, 70.5, -16.5, 3.3, -3.7, 52.1, 33.1, 88.5, 45.6, 9.3, 39.6, 58.3, -5.5, 19.8, 43.3, 98.0, 23.0, 87.5, 13.8, 80.6, 56.2, 100.0, 70.1, 36.4, 48.4, 37.8, 61.8, 36.3, 15.2, 73.7, 23.5, 81.1, 44.6, 94.4, -7.0, 58.1, 58.1, 96.7, 32.7, 93.4, -15.2, 20.4, 53.0, 58.5, 51.5, 60.5, 50.1, 63.7, 48.7, 67.4, 45.1, 73.2, 43.5, 52.9, 42.1, 52.1, 40.9, 51.1, 35.0, 46.9, 6.1, 25.8, 44.6, 53.5, 3.2, 43.3, 39.6, 77.9, 59.8, 91.6, 61.2, 84.7, 49.8, 83.0, 26.6, 63.1, 41.1, 24.9, 32.2, 71.4, 24.0, 21.7, 33.7, 31.4, 17.0, 33.1, 46.8, 89.4, 19.3, 67.2, 27.1, 75.5, 22.9, 53.4, -4.2, 32.7, 12.8, 53.0, -11.6, 36.5, 27.6, 40.5, -16.0, -13.2, -21.6, -15.1, 81.0, 86.1, 101.0, 20.8, 75.4, 45.2, 73.2, 52.4, 81.0, 48.4, 84.3, 51.7, 77.4, 53.4, 80.5, 54.8, 88.9, 66.4, 118.7, 22.1, 94.0, 59.5, 112.6, 53.1, 86.2, 58.4, 84.7, 58.1, 74.5, 49.2, 79.2, 51.1, 82.4, 53.4, 85.6, 58.4, 83.4, 60.8, 83.9, 58.1, 78.7, 55.6, 75.9, 54.7, 71.8, 54.2, 70.4, 78.7, 71.4, 71.8, 71.4, 67.4, 71.4, 63.3, 70.5, 60.1, 78.2, 59.4, 79.3, 60.9, 80.7, 63.2, 81.6, 65.9, 91.3, 46.1, 125.7, 18.2, 80.6, 58.6, 82.0, 59.5, 77.5, 31.7, 85.2, 31.3, 96.7, 6.0, 106.5, 12.0, 84.3, 71.4, 133.3, 3.3, 124.7, 2.8, 117.7, 5.6, 106.4, 3.3, 130.1, 19.0, 89.9, 24.0, 119.8, 35.2, 103.0, 71.4, 99.2, 77.4, 130.6, 18.9, 110.8, 62.3, 80.0, 91.1, 93.9, 14.3, 84.4, 62.1, 125.1, 33.2, 68.0, 98.9, 83.7, 90.3, 90.6, 85.1, 87.1, 41.4, 77.9, 37.7, 94.7, 79.1, 87.5, 84.7, 70.4, 95.9, 106.0, 67.6, 76.7, 95.3, 125.0, 34.6, 75.0, 60.0, 76.0, 62.3, 76.9, 65.6, 77.4, 69.6, 78.3, 75.6, 82.9, 56.3, 84.4, 55.8, 86.1, 55.2, 93.9, 52.5, 118.3, 37.4, 81.0, 56.7, 112.7, 53.5, 80.1, 80.7, 71.3, 84.4, 93.5, 68.7, 94.4, 30.3, 87.0, 75.5, 108.8, 30.5, 99.0, 38.2, 110.0, 42.4, 71.4, 91.1, 96.2, 73.2, 88.7, 79.6, 99.5, 60.4, 119.6, 44.8, 105.3, 61.3, 118.6, 48.9, 100.8, 47.9, 134.2, 3.4, 129.6, 2.0]}, {"rect": [259, 446, 537, 724], "points": [0.36259, 0.03663, 0.07411, 0.0, -0.04444, 0.37725, -0.00538, 0.0, -0.08614, -0.02777, 0.36118, 0.0, -100.46719, -257.77767, -51.39563, 1.0, 68.5, 45.1, 71.4, 30.4, 68.1, 48.3, 67.5, 51.2, 66.7, 53.3, 65.4, 60.2, 65.3, 63.6, 64.9, 68.1, 64.0, 72.2, 62.8, 78.6, 35.9, 83.0, 36.3, 13.9, 61.1, 43.3, 60.3, 50.7, 52.1, 45.6, 46.0, 48.4, 53.9, 51.1, 48.4, 51.6, 34.5, 61.7, 13.7, 11.0, 31.0, 53.8, -14.3, 41.5, 37.9, 53.8, 39.4, 53.9, 60.6, 47.4, 52.9, 48.4, 47.1, 50.2, 38.8, 53.9, 41.5, 57.1, 40.3, 53.9, 49.2, 52.6, 54.3, 52.5, 60.3, 52.5, 53.6, 77.4, 55.8, 70.8, 57.0, 66.7, 58.0, 62.6, 58.9, 59.5, 48.3, 57.1, 46.6, 58.5, 44.8, 60.4, 43.4, 62.6, 41.4, 41.1, -21.4, 2.5, 44.3, 55.7, 43.0, 56.3, 63.5, 29.8, 52.9, 27.6, 43.6, 0.0, 31.4, 3.8, 39.1, 67.7, -5.6, -12.0, 7.3, -9.3, 16.4, -5.1, 30.3, -4.7, -5.2, 4.7, 48.4, 19.7, -19.4, 21.3, 6.4, 63.6, 2.8, 70.4, -15.8, 3.4, -3.1, 52.1, 33.3, 88.4, 45.6, 9.2, 39.7, 58.1, -5.1, 19.8, 43.7, 97.8, 23.5, 87.2, 14.3, 80.6, 56.7, 99.9, 70.4, 35.9, 48.8, 37.7, 62.1, 35.9, 15.6, 73.7, 24.0, 81.0, 44.8, 94.4, -6.5, 58.1, 58.5, 96.3, 33.1, 93.1, -14.8, 20.6, 53.3, 58.5, 51.7, 60.8, 50.2, 63.9, 48.8, 67.6, 45.3, 73.2, 43.5, 52.6, 42.1, 51.9, 41.1, 50.7, 35.4, 46.9, 6.5, 25.8, 44.8, 53.4, 3.7, 43.3, 40.1, 77.9, 60.0, 91.2, 61.4, 84.6, 50.2, 83.2, 26.9, 63.1, 41.4, 24.8, 32.4, 71.4, 24.4, 21.7, 34.1, 31.3, 17.5, 33.1, 47.1, 89.3, 19.8, 67.2, 27.6, 75.5, 23.2, 53.4, -3.7, 32.7, 13.0, 52.9, -11.1, 36.8, 28.1, 40.5, -15.4, -13.2, -21.0, -15.0, 81.5, 85.7, 101.2, 20.6, 75.4, 44.7, 73.5, 52.0, 81.3, 47.9, 84.5, 51.5, 77.7, 53.0, 80.9, 54.4, 89.3, 66.2, 118.7, 21.6, 94.3, 59.3, 112.7, 52.8, 86.5, 58.0, 85.1, 57.9, 74.5, 48.7, 79.5, 50.7, 82.8, 53.0, 85.9, 58.0, 83.7, 60.7, 84.2, 57.9, 79.1, 55.2, 76.2, 54.3, 72.1, 53.5, 70.9, 78.7, 71.7, 71.8, 71.8, 67.6, 71.7, 63.5, 70.8, 60.3, 78.6, 59.4, 79.6, 60.8, 81.0, 63.1, 81.9, 65.7, 91.6, 45.9, 125.3, 17.9, 80.9, 58.5, 82.3, 59.4, 77.8, 31.3, 85.2, 30.8, 96.7, 5.6, 106.6, 11.8, 84.7, 71.2, 133.0, 2.8, 124.6, 2.3, 117.7, 5.4, 106.6, 3.1, 129.8, 18.7, 90.2, 23.8, 119.7, 34.9, 103.2, 70.9, 99.4, 76.9, 130.6, 18.4, 110.9, 62.0, 80.2, 90.7, 93.9, 13.8, 84.7, 61.7, 125.1, 32.7, 68.2, 98.6, 83.9, 89.9, 90.8, 84.7, 87.4, 41.0, 78.2, 37.3, 94.9, 78.7, 87.9, 84.3, 70.6, 95.7, 105.9, 67.1, 77.0, 94.9, 124.8, 34.1, 75.1, 59.9, 76.4, 62.3, 77.3, 65.7, 77.7, 69.5, 78.7, 75.5, 83.2, 56.1, 84.7, 55.6, 86.4, 54.8, 94.0, 52.0, 118.3, 37.1, 81.4, 56.5, 112.8, 53.2, 80.5, 80.5, 71.5, 84.5, 93.9, 68.5, 94.4, 29.9, 87.4, 75.3, 109.0, 30.3, 99.1, 37.7, 110.0, 41.9, 71.9, 90.8, 96.6, 72.7, 88.9, 79.2, 99.8, 60.1, 119.6, 44.5, 105.4, 60.8, 118.7, 48.6, 100.9, 47.4, 134.0, 3.2, 129.4, 1.8]}, {"rect": [258, 445, 536, 723], "points": [0.36161, 0.03507, 0.0742, 0.0, -0.04265, 0.37707, -0.00572, 0.0, -0.08609, -0.02655, 0.36044, 0.0, -101.18178, -256.57442, -51.19973, 1.0, 68.3, 45.2, 71.7, 30.2, 68.2, 48.1, 67.4, 51.3, 66.8, 53.2, 65.5, 60.7, 65.1, 64.3, 65.0, 68.6, 64.2, 72.7, 63.4, 78.8, 36.4, 83.4, 36.4, 14.3, 60.9, 43.4, 60.4, 50.8, 52.5, 45.7, 46.2, 48.5, 54.0, 51.1, 48.5, 51.7, 35.0, 62.2, 13.9, 11.1, 31.7, 54.3, -13.8, 42.2, 38.3, 54.0, 40.1, 54.3, 60.5, 47.5, 53.1, 48.5, 47.5, 50.3, 39.3, 54.0, 41.9, 57.5, 40.7, 54.3, 49.4, 52.9, 54.5, 52.6, 60.4, 52.6, 54.2, 77.8, 56.2, 71.3, 57.2, 67.5, 58.1, 63.3, 59.0, 60.1, 48.4, 57.8, 47.0, 59.2, 45.2, 61.1, 43.8, 63.1, 41.8, 41.5, -21.2, 3.5, 44.8, 56.2, 43.4, 57.0, 63.9, 29.7, 53.0, 27.8, 43.7, 0.4, 31.7, 4.2, 39.6, 68.1, -5.5, -11.5, 7.4, -8.8, 16.6, -4.6, 30.5, -4.5, -5.0, 5.4, 48.8, 19.8, -18.9, 22.0, 6.9, 64.0, 3.3, 70.9, -15.6, 4.3, -2.4, 52.8, 34.0, 88.8, 45.7, 9.3, 40.2, 58.5, -4.6, 20.3, 44.2, 98.3, 23.9, 87.8, 14.7, 81.0, 57.4, 100.2, 70.8, 36.0, 49.2, 37.8, 62.5, 36.0, 16.1, 74.1, 24.4, 81.5, 45.5, 94.8, -6.0, 58.8, 59.2, 96.7, 33.6, 93.7, -14.3, 21.1, 53.5, 59.2, 52.1, 61.5, 50.4, 64.4, 49.0, 68.1, 46.0, 73.6, 43.9, 52.9, 42.5, 52.1, 41.5, 51.1, 35.9, 47.1, 6.9, 26.2, 45.2, 53.5, 4.1, 43.7, 40.5, 78.3, 60.6, 91.6, 62.0, 84.8, 50.9, 83.4, 27.6, 63.5, 41.8, 24.9, 33.1, 71.8, 24.8, 22.1, 34.5, 31.7, 17.9, 33.5, 47.7, 89.7, 20.3, 67.6, 28.1, 75.9, 23.9, 53.9, -3.3, 33.2, 13.7, 53.4, -10.6, 37.3, 28.5, 41.0, -15.2, -12.2, -21.1, -14.0, 81.9, 85.7, 101.3, 20.4, 75.2, 44.7, 73.3, 51.8, 81.2, 47.9, 84.4, 51.6, 77.8, 53.1, 80.7, 54.4, 89.7, 66.3, 118.5, 21.4, 94.7, 59.4, 112.6, 52.5, 86.6, 58.1, 85.2, 58.0, 74.6, 48.6, 79.6, 50.7, 82.8, 53.1, 85.8, 58.1, 83.8, 60.8, 84.3, 58.0, 79.2, 55.3, 76.1, 54.4, 72.0, 53.6, 71.3, 78.8, 71.8, 72.3, 71.9, 68.1, 71.5, 63.9, 71.0, 61.0, 78.4, 59.7, 79.7, 61.2, 81.1, 63.5, 82.0, 65.9, 92.0, 45.7, 125.1, 17.9, 81.1, 58.9, 82.5, 59.8, 78.2, 31.1, 85.5, 30.6, 96.7, 5.6, 106.4, 11.6, 85.1, 71.4, 132.7, 2.7, 124.2, 2.3, 117.2, 5.1, 106.1, 3.2, 129.5, 18.5, 90.2, 23.6, 119.5, 34.9, 103.5, 70.9, 99.5, 76.9, 130.1, 18.4, 111.0, 61.7, 80.9, 90.8, 93.9, 13.9, 84.8, 62.1, 124.9, 32.7, 68.9, 98.9, 84.6, 90.2, 91.2, 84.7, 87.7, 41.0, 78.6, 37.4, 95.3, 78.7, 88.3, 84.4, 71.2, 95.8, 106.0, 66.8, 77.7, 95.2, 124.6, 34.1, 75.1, 60.6, 76.5, 62.9, 77.4, 66.2, 77.8, 69.9, 79.1, 75.6, 83.0, 56.2, 84.8, 55.7, 86.2, 54.8, 94.3, 52.0, 118.3, 36.9, 81.5, 56.3, 112.8, 53.0, 80.9, 80.6, 72.1, 84.7, 94.3, 68.3, 94.7, 29.7, 87.9, 75.2, 108.8, 30.0, 99.4, 37.4, 110.1, 41.9, 72.6, 91.1, 96.7, 72.7, 89.3, 79.2, 99.9, 59.9, 119.4, 44.3, 105.5, 60.8, 118.5, 48.4, 101.2, 47.1, 133.7, 3.2, 129.1, 1.8]}, {"rect": [258, 445, 536, 723], "points": [0.361, 0.03381, 0.07398, 0.0, -0.04141, 0.37699, -0.00498, 0.0, -0.08564, -0.02635, 0.35969, 0.0, -101.7673, -255.92631, -51.49404, 1.0, 68.1, 44.8, 71.4, 30.0, 67.8, 47.9, 67.2, 51.1, 66.7, 53.0, 65.3, 60.4, 65.3, 64.1, 64.8, 68.6, 64.3, 72.7, 63.1, 78.8, 36.4, 83.4, 36.3, 14.2, 60.8, 43.0, 60.3, 50.7, 52.4, 45.6, 46.1, 48.4, 53.9, 50.8, 48.7, 51.6, 35.0, 62.2, 13.7, 11.1, 31.7, 54.3, -13.9, 42.2, 38.6, 53.9, 40.1, 54.0, 60.4, 47.1, 53.0, 48.4, 47.4, 50.2, 39.5, 53.9, 41.9, 57.2, 40.9, 54.0, 49.3, 52.6, 54.4, 52.5, 60.3, 52.5, 54.2, 77.8, 56.1, 71.4, 57.1, 67.3, 58.0, 63.1, 58.9, 59.9, 48.4, 57.6, 47.0, 58.9, 45.5, 60.8, 43.8, 63.1, 41.5, 41.5, -21.3, 3.5, 45.0, 56.1, 43.6, 56.7, 63.5, 29.6, 52.9, 27.7, 43.3, 0.1, 31.3, 4.2, 39.6, 68.1, -5.6, -11.5, 7.3, -8.8, 16.5, -4.6, 30.3, -4.6, -5.1, 5.4, 48.4, 19.5, -19.0, 22.0, 6.9, 64.0, 3.6, 70.8, -15.7, 4.2, -2.4, 52.8, 34.0, 88.8, 45.5, 9.2, 40.4, 58.4, -4.7, 20.3, 44.2, 98.0, 23.9, 87.5, 14.7, 81.0, 57.1, 99.9, 70.4, 35.6, 48.9, 37.5, 62.2, 35.7, 16.1, 74.1, 24.5, 81.4, 45.5, 94.5, -6.0, 58.8, 59.0, 96.6, 33.6, 93.5, -14.4, 21.2, 53.4, 58.9, 52.0, 61.2, 50.6, 64.4, 49.2, 68.1, 45.9, 73.4, 44.1, 52.6, 42.7, 51.8, 41.5, 50.8, 35.9, 47.0, 6.8, 26.2, 45.1, 53.4, 4.1, 43.7, 40.5, 78.3, 60.4, 91.3, 61.8, 84.7, 50.7, 83.4, 27.6, 63.5, 41.5, 24.9, 33.1, 71.8, 24.5, 22.1, 34.4, 31.4, 17.9, 33.3, 47.5, 89.4, 20.2, 67.6, 28.1, 75.6, 23.9, 53.9, -3.3, 33.2, 13.7, 53.4, -10.6, 37.3, 28.5, 41.0, -15.4, -12.1, -21.2, -14.0, 81.6, 85.6, 100.9, 19.9, 75.0, 44.3, 73.2, 51.7, 81.0, 47.5, 84.2, 51.2, 77.4, 52.9, 80.6, 54.3, 89.4, 65.9, 118.0, 21.2, 94.4, 59.0, 112.4, 52.1, 86.5, 58.0, 84.9, 57.7, 74.2, 48.4, 79.2, 50.3, 82.5, 52.9, 85.7, 58.0, 83.7, 60.7, 84.2, 57.6, 79.1, 54.9, 76.0, 54.0, 71.8, 53.5, 71.0, 78.8, 71.5, 72.3, 71.7, 68.1, 71.4, 63.9, 70.9, 60.7, 78.3, 59.4, 79.6, 61.1, 81.0, 63.2, 81.9, 65.8, 91.6, 45.3, 124.9, 17.4, 81.0, 58.6, 82.4, 59.4, 77.8, 30.9, 85.2, 30.4, 96.3, 5.5, 106.0, 11.1, 84.8, 71.0, 132.3, 2.3, 124.0, 1.9, 117.0, 4.7, 105.9, 2.8, 129.1, 18.0, 89.8, 23.2, 119.3, 34.5, 103.2, 70.5, 99.2, 76.5, 129.7, 18.0, 110.7, 61.3, 80.6, 90.6, 93.5, 13.5, 84.7, 61.8, 124.5, 32.2, 68.7, 98.6, 84.3, 89.8, 91.2, 84.3, 87.2, 40.6, 78.3, 37.0, 95.0, 78.3, 88.0, 84.2, 71.0, 95.7, 105.7, 66.4, 77.4, 94.8, 124.4, 33.6, 75.0, 60.3, 76.4, 62.6, 77.3, 65.9, 77.7, 69.9, 78.8, 75.5, 82.9, 55.8, 84.7, 55.3, 86.1, 54.4, 94.0, 51.6, 117.6, 36.4, 81.4, 56.2, 112.5, 52.5, 80.7, 80.2, 71.9, 84.4, 93.9, 68.1, 94.1, 29.4, 87.6, 75.0, 108.3, 29.6, 99.0, 37.0, 109.7, 41.5, 72.3, 90.8, 96.4, 72.3, 89.0, 78.9, 99.6, 59.5, 119.0, 43.8, 105.1, 60.3, 118.1, 47.9, 100.8, 46.9, 133.2, 2.7, 128.7, 1.3]}, {"rect": [258, 445, 536, 723], "points": [0.36087, 0.03261, 0.07389, 0.0, -0.04047, 0.37711, -0.00401, 0.0, -0.08505, -0.02675, 0.3593, 0.0, -102.32803, -255.53652, -52.03514, 1.0, 67.7, 44.7, 71.0, 30.0, 67.6, 47.8, 66.8, 51.0, 66.3, 53.0, 65.0, 60.4, 64.9, 64.0, 64.5, 68.6, 64.0, 72.7, 63.1, 78.7, 36.3, 83.3, 36.0, 13.9, 60.4, 43.2, 60.0, 50.6, 52.1, 45.6, 46.1, 48.4, 53.8, 50.7, 48.4, 51.6, 35.0, 62.2, 13.4, 11.1, 31.7, 54.1, -13.9, 42.0, 38.6, 53.9, 40.3, 53.9, 60.3, 47.0, 52.9, 48.4, 47.3, 50.2, 39.5, 53.9, 41.9, 57.2, 40.9, 53.9, 49.3, 52.6, 54.3, 52.5, 60.0, 52.5, 54.0, 77.8, 56.1, 71.4, 57.0, 67.3, 57.9, 63.1, 58.9, 59.9, 48.4, 57.3, 47.0, 58.7, 45.4, 60.8, 43.7, 63.1, 41.5, 41.4, -21.6, 3.3, 45.0, 55.9, 43.6, 56.7, 63.2, 29.5, 52.6, 27.6, 42.9, 0.0, 31.0, 4.1, 39.6, 68.1, -5.9, -11.5, 7.0, -8.7, 16.1, -4.6, 30.0, -4.6, -5.5, 5.2, 48.3, 19.4, -19.2, 22.1, 6.9, 64.0, 3.6, 70.6, -16.0, 4.2, -2.3, 52.6, 34.0, 88.5, 45.2, 9.1, 40.5, 58.2, -5.0, 20.3, 44.2, 97.7, 23.9, 87.2, 14.7, 80.7, 57.1, 99.6, 70.1, 35.5, 48.8, 37.6, 61.8, 35.8, 16.1, 73.8, 24.7, 81.1, 45.6, 94.4, -6.0, 58.6, 59.0, 96.3, 33.6, 93.2, -14.6, 21.2, 53.3, 58.7, 51.9, 61.0, 50.5, 64.5, 49.1, 68.1, 45.7, 73.6, 44.1, 52.6, 42.7, 51.9, 41.7, 50.7, 35.9, 47.0, 6.5, 26.3, 45.1, 53.4, 4.1, 43.7, 40.5, 78.3, 60.4, 91.2, 61.7, 84.7, 50.7, 83.3, 27.6, 63.5, 41.5, 24.8, 33.1, 71.8, 24.4, 22.1, 34.1, 31.4, 17.6, 33.5, 47.5, 89.4, 20.2, 67.4, 28.1, 75.6, 23.9, 53.9, -3.6, 33.2, 13.7, 53.4, -10.7, 37.3, 28.2, 40.9, -15.9, -12.4, -21.6, -14.2, 81.6, 85.3, 100.5, 19.8, 74.6, 44.2, 72.8, 51.6, 80.6, 47.4, 83.9, 51.1, 77.3, 52.6, 80.2, 54.0, 89.4, 65.8, 117.9, 20.8, 94.1, 58.6, 112.4, 51.7, 86.2, 57.7, 84.8, 57.6, 73.8, 48.3, 78.9, 50.2, 82.1, 52.6, 85.4, 57.7, 83.4, 60.4, 83.9, 57.2, 78.8, 54.8, 75.6, 53.9, 71.5, 53.4, 71.0, 78.7, 71.3, 72.3, 71.4, 68.1, 71.3, 63.7, 70.6, 60.5, 78.2, 59.2, 79.3, 60.9, 80.7, 63.1, 81.6, 65.5, 91.3, 45.1, 124.7, 16.8, 80.7, 58.5, 82.1, 59.1, 77.5, 30.8, 84.9, 30.0, 95.9, 5.1, 105.6, 10.8, 84.8, 70.9, 131.9, 1.6, 123.8, 1.5, 116.7, 4.3, 105.6, 2.4, 128.9, 17.6, 89.5, 23.0, 119.2, 33.8, 103.2, 70.1, 99.4, 76.1, 129.8, 17.6, 110.6, 60.9, 80.6, 90.3, 93.2, 13.4, 84.4, 61.4, 124.3, 31.5, 68.6, 98.2, 84.3, 89.4, 91.2, 83.9, 86.8, 40.5, 77.9, 36.9, 94.9, 77.9, 88.0, 83.9, 71.0, 95.4, 105.8, 66.0, 77.4, 94.5, 124.3, 33.2, 74.7, 60.0, 76.1, 62.4, 76.9, 65.9, 77.4, 69.6, 78.8, 75.5, 82.5, 55.7, 84.4, 55.2, 85.8, 54.3, 93.6, 51.3, 117.5, 36.0, 81.1, 55.8, 112.4, 52.1, 80.6, 80.2, 71.9, 84.3, 93.6, 67.8, 93.7, 29.1, 87.5, 74.7, 108.2, 29.4, 98.7, 36.9, 109.6, 41.1, 72.3, 90.7, 96.3, 71.9, 88.9, 78.7, 99.5, 59.4, 118.9, 43.4, 105.0, 60.0, 118.3, 47.5, 100.5, 46.6, 133.1, 2.0, 128.7, 0.6]}, {"rect": [257, 444, 535, 722], "points": [0.3609, 0.03164, 0.07411, 0.0, -0.03965, 0.37712, -0.00387, 0.0, -0.08505, -0.02677, 0.35927, 0.0, -102.80544, -254.90337, -52.34287, 1.0, 67.9, 45.0, 71.4, 30.4, 67.8, 48.0, 67.0, 51.2, 66.4, 53.4, 65.4, 61.1, 65.1, 64.5, 64.7, 69.1, 64.1, 73.2, 63.6, 79.2, 36.8, 83.8, 36.4, 14.4, 60.8, 43.3, 60.4, 50.8, 52.5, 46.0, 46.5, 48.8, 54.0, 51.1, 48.8, 52.0, 35.5, 62.6, 13.8, 11.6, 32.2, 54.7, -13.7, 42.5, 39.1, 54.3, 40.6, 54.3, 60.4, 47.4, 53.1, 48.8, 47.5, 50.4, 40.0, 54.3, 42.4, 57.9, 41.4, 54.4, 49.7, 53.0, 54.5, 52.7, 60.4, 52.7, 54.4, 78.2, 56.3, 71.8, 57.2, 67.7, 58.1, 63.6, 59.0, 60.3, 48.8, 58.0, 47.4, 59.4, 45.7, 61.3, 44.2, 63.6, 41.9, 41.9, -21.2, 3.8, 45.2, 56.6, 43.8, 57.1, 63.6, 29.9, 53.0, 28.1, 43.3, 0.5, 31.3, 4.6, 40.0, 68.6, -5.6, -11.0, 7.3, -8.3, 16.2, -4.1, 30.3, -4.1, -5.1, 5.7, 48.5, 19.9, -18.8, 22.3, 7.3, 64.5, 4.1, 71.1, -15.7, 4.7, -1.9, 53.1, 34.5, 88.9, 45.6, 9.3, 41.0, 58.9, -4.6, 20.8, 44.7, 98.1, 24.4, 87.6, 15.2, 81.2, 57.6, 100.0, 70.5, 35.9, 49.2, 37.9, 62.2, 36.0, 16.5, 74.3, 25.0, 81.6, 46.0, 94.9, -5.6, 59.1, 59.5, 96.7, 34.0, 93.6, -14.2, 21.7, 53.5, 59.4, 52.1, 61.7, 50.7, 64.9, 49.4, 68.6, 46.1, 74.1, 44.3, 53.0, 42.9, 52.2, 41.9, 51.2, 36.3, 47.5, 6.9, 26.7, 45.6, 53.6, 4.5, 44.2, 40.9, 78.7, 60.8, 91.6, 62.2, 85.1, 51.2, 83.7, 28.0, 64.0, 41.9, 25.0, 33.3, 72.3, 24.8, 22.6, 34.5, 31.8, 17.9, 33.8, 48.0, 89.8, 20.7, 67.8, 28.5, 76.0, 24.4, 54.4, -3.2, 33.7, 13.9, 53.9, -10.5, 37.8, 28.6, 41.2, -15.6, -11.9, -21.2, -13.7, 82.0, 85.7, 100.9, 20.0, 74.8, 44.3, 72.9, 52.0, 80.7, 47.5, 84.3, 51.2, 77.5, 53.0, 80.6, 54.4, 89.8, 66.0, 118.0, 20.9, 94.5, 59.0, 112.8, 51.8, 86.6, 58.0, 85.2, 58.0, 74.2, 48.4, 79.2, 50.6, 82.5, 53.0, 86.0, 58.0, 83.8, 60.8, 84.3, 57.6, 79.2, 55.3, 76.0, 54.3, 71.9, 53.6, 71.4, 79.2, 71.5, 72.7, 71.6, 68.6, 71.5, 64.3, 70.9, 61.1, 78.4, 59.8, 79.7, 61.3, 81.1, 63.6, 82.0, 65.9, 91.7, 45.3, 124.9, 16.8, 81.1, 58.9, 82.5, 59.8, 77.9, 30.9, 85.2, 30.4, 96.3, 5.2, 105.9, 11.1, 85.2, 71.0, 132.2, 1.9, 124.0, 1.9, 117.0, 4.6, 105.9, 2.8, 129.1, 17.7, 89.8, 23.2, 119.4, 33.9, 103.6, 70.2, 99.9, 76.2, 130.0, 17.7, 111.0, 61.0, 81.1, 90.5, 93.5, 13.5, 84.8, 62.1, 124.5, 31.9, 69.1, 98.6, 84.8, 89.5, 91.6, 84.0, 87.5, 40.7, 78.3, 37.3, 95.4, 78.0, 88.5, 84.0, 71.7, 95.8, 106.1, 66.1, 77.9, 94.6, 124.5, 33.3, 75.1, 60.6, 76.4, 63.0, 77.1, 66.3, 77.6, 70.0, 79.2, 75.9, 82.9, 55.9, 84.7, 55.4, 86.1, 54.4, 94.1, 51.6, 117.9, 36.1, 81.5, 56.2, 112.8, 52.3, 81.1, 80.6, 72.3, 84.7, 94.1, 68.2, 94.4, 29.2, 88.0, 75.1, 108.4, 29.6, 99.0, 37.0, 109.8, 41.2, 72.8, 90.9, 96.8, 72.1, 89.4, 78.9, 99.9, 59.5, 119.3, 43.5, 105.5, 60.1, 118.5, 47.7, 100.9, 46.7, 133.2, 2.1, 128.7, 0.7]}, {"rect": [257, 444, 535, 722], "points": [0.36149, 0.03091, 0.07414, 0.0, -0.03891, 0.37711, -0.00448, 0.0, -0.08471, -0.0265, 0.35955, 0.0, -103.58801, -254.44165, -51.97474, 1.0, 68.0, 44.8, 71.4, 30.4, 67.7, 47.9, 67.1, 51.1, 66.4, 53.4, 65.4, 60.9, 65.3, 64.5, 64.8, 69.1, 64.1, 73.2, 63.6, 79.2, 36.6, 83.8, 36.1, 14.4, 60.8, 43.3, 60.3, 50.7, 52.5, 46.0, 46.5, 48.8, 53.9, 51.1, 48.8, 52.0, 35.5, 62.6, 13.5, 11.6, 31.9, 54.8, -13.8, 42.5, 39.1, 54.3, 40.5, 54.3, 60.4, 47.4, 53.0, 48.8, 47.5, 50.6, 39.8, 54.3, 42.4, 58.0, 41.4, 54.6, 49.7, 53.2, 54.7, 52.9, 60.3, 52.9, 54.4, 78.0, 56.2, 71.9, 57.2, 67.7, 58.1, 63.5, 59.0, 60.3, 48.8, 58.0, 47.4, 59.4, 45.6, 61.3, 44.2, 63.6, 41.6, 41.9, -21.5, 3.8, 45.2, 56.6, 43.8, 57.1, 63.6, 29.9, 52.9, 28.1, 43.0, 0.5, 31.0, 4.6, 39.8, 68.6, -5.9, -10.9, 6.9, -8.2, 16.1, -4.1, 29.9, -4.1, -5.4, 5.9, 48.4, 19.9, -18.9, 22.6, 7.1, 64.6, 3.9, 71.3, -16.0, 4.7, -2.1, 53.4, 34.3, 88.9, 45.3, 9.3, 41.0, 58.9, -4.9, 20.9, 44.5, 98.1, 24.2, 87.9, 15.3, 81.4, 57.7, 100.2, 70.5, 35.9, 49.0, 37.9, 62.2, 36.0, 16.3, 74.5, 25.0, 81.6, 45.8, 94.8, -5.8, 59.4, 59.5, 96.7, 33.8, 93.8, -14.3, 21.8, 53.5, 59.4, 52.1, 61.7, 50.7, 64.9, 49.3, 68.6, 46.1, 73.8, 44.2, 53.2, 42.9, 52.4, 41.9, 51.4, 36.1, 47.5, 6.6, 26.8, 45.6, 53.8, 4.2, 44.2, 40.7, 78.7, 60.9, 91.6, 62.3, 84.9, 51.2, 83.5, 27.8, 64.0, 41.6, 25.3, 33.3, 72.3, 24.6, 22.6, 34.3, 31.9, 17.7, 34.0, 48.0, 89.8, 20.5, 68.1, 28.3, 76.1, 24.1, 54.4, -3.5, 33.7, 13.9, 54.0, -10.5, 37.9, 28.6, 41.4, -15.7, -11.8, -21.6, -13.4, 82.1, 85.6, 100.8, 20.1, 74.9, 44.2, 72.8, 52.0, 80.6, 47.5, 84.2, 51.1, 77.4, 52.9, 80.6, 54.3, 89.8, 66.2, 118.2, 21.0, 94.5, 58.9, 112.8, 52.0, 86.6, 58.0, 85.2, 57.9, 74.1, 48.4, 79.2, 50.6, 82.4, 52.9, 85.7, 58.0, 83.8, 60.7, 84.3, 57.6, 79.2, 55.2, 76.0, 54.3, 71.8, 53.8, 71.4, 79.2, 71.4, 72.7, 71.7, 68.6, 71.4, 64.1, 70.9, 60.8, 78.3, 59.8, 79.7, 61.2, 81.0, 63.5, 82.0, 65.9, 91.7, 45.5, 125.1, 17.0, 81.0, 58.9, 82.4, 59.7, 77.9, 30.9, 85.2, 30.4, 96.2, 5.4, 105.9, 11.1, 85.3, 70.9, 132.4, 1.8, 124.2, 1.8, 117.2, 4.6, 105.9, 2.7, 129.3, 17.8, 89.8, 23.4, 119.7, 34.0, 103.6, 70.3, 99.9, 76.4, 130.2, 17.8, 111.0, 61.2, 81.1, 90.6, 93.4, 13.7, 84.7, 62.0, 124.7, 31.8, 69.2, 98.8, 84.8, 89.7, 91.7, 84.2, 87.4, 40.9, 78.3, 37.3, 95.7, 78.2, 88.5, 84.2, 71.6, 95.7, 106.3, 66.3, 77.9, 94.8, 124.8, 33.5, 75.1, 60.4, 76.4, 63.0, 77.3, 66.3, 77.7, 70.0, 79.3, 75.6, 82.9, 56.0, 84.7, 55.3, 86.1, 54.4, 94.3, 51.6, 117.9, 36.2, 81.5, 56.2, 112.8, 52.4, 81.1, 80.5, 72.4, 84.7, 94.3, 68.1, 94.3, 29.4, 88.0, 75.0, 108.6, 29.5, 99.0, 37.2, 110.0, 41.4, 72.8, 91.0, 97.1, 72.2, 89.4, 79.1, 99.9, 59.7, 119.6, 43.6, 105.5, 60.2, 118.8, 47.8, 100.8, 46.9, 133.4, 2.2, 128.8, 0.9]}, {"rect": [257, 444, 535, 722], "points": [0.36178, 0.02996, 0.07499, 0.0, -0.03768, 0.37703, -0.0047, 0.0, -0.08483, -0.02629, 0.35941, 0.0, -104.63835, -253.85164, -52.50893, 1.0, 67.8, 44.7, 71.3, 30.4, 67.7, 47.9, 66.9, 51.1, 66.4, 53.4, 65.4, 60.9, 65.0, 64.4, 64.6, 69.0, 64.1, 73.2, 63.6, 79.2, 36.8, 83.8, 36.2, 14.6, 60.7, 43.3, 60.3, 50.9, 52.4, 46.0, 46.5, 48.8, 53.9, 51.1, 48.8, 52.0, 35.5, 62.6, 13.7, 11.9, 32.1, 54.8, -13.8, 42.8, 39.1, 54.3, 40.5, 54.3, 60.3, 47.4, 53.0, 48.8, 47.4, 50.6, 40.0, 54.3, 42.4, 58.0, 41.4, 54.4, 49.7, 53.0, 54.5, 52.9, 60.3, 52.9, 54.7, 78.2, 56.3, 71.9, 57.2, 67.7, 58.1, 63.5, 59.0, 60.3, 48.8, 58.0, 47.4, 59.4, 45.6, 61.3, 44.2, 63.6, 41.8, 41.9, -21.6, 4.2, 45.4, 56.6, 43.8, 57.1, 63.8, 29.9, 52.9, 28.1, 43.1, 0.5, 31.2, 4.6, 40.0, 68.6, -6.0, -10.6, 6.6, -8.2, 15.7, -4.1, 29.6, -4.1, -5.6, 6.0, 48.3, 20.2, -18.9, 23.0, 7.3, 64.8, 4.1, 71.4, -15.8, 5.1, -2.0, 53.5, 34.5, 88.9, 45.4, 9.6, 41.0, 58.9, -4.7, 21.2, 45.0, 98.1, 24.4, 87.9, 15.6, 81.5, 58.0, 100.0, 70.7, 35.9, 49.2, 38.1, 62.1, 36.2, 16.6, 74.5, 25.3, 81.9, 46.3, 94.8, -5.6, 59.4, 59.8, 96.6, 34.1, 93.9, -14.3, 22.1, 53.5, 59.4, 52.1, 61.7, 50.7, 64.9, 49.3, 68.6, 46.4, 74.0, 44.2, 53.0, 43.2, 52.5, 41.9, 51.5, 36.3, 47.7, 6.8, 27.1, 45.6, 53.8, 4.2, 44.3, 41.0, 78.7, 61.2, 91.6, 62.5, 85.1, 51.4, 83.7, 28.1, 64.0, 41.8, 25.3, 33.5, 72.3, 24.7, 22.6, 34.4, 32.1, 17.8, 34.0, 48.3, 89.8, 20.7, 68.1, 28.5, 76.3, 24.3, 54.7, -3.3, 34.0, 14.2, 54.2, -10.6, 38.2, 28.6, 41.4, -16.1, -11.5, -21.7, -13.3, 82.4, 85.5, 100.7, 19.8, 74.7, 44.2, 72.8, 51.9, 80.6, 47.4, 83.9, 51.1, 77.4, 52.9, 80.6, 54.3, 89.8, 66.2, 117.9, 20.7, 94.7, 58.8, 112.9, 51.9, 86.6, 57.9, 85.1, 57.6, 74.1, 48.3, 79.2, 50.5, 82.4, 52.9, 85.7, 57.9, 83.7, 60.7, 84.3, 57.5, 79.2, 55.2, 76.0, 54.3, 71.8, 53.8, 71.7, 79.2, 71.5, 72.7, 71.5, 68.6, 71.4, 64.0, 70.9, 60.8, 78.3, 59.8, 79.7, 61.2, 81.0, 63.5, 82.0, 65.8, 91.9, 45.4, 124.9, 16.9, 81.0, 58.8, 82.4, 59.5, 78.1, 30.8, 85.2, 30.4, 96.1, 5.1, 105.8, 11.0, 85.5, 70.9, 132.2, 1.7, 123.9, 1.5, 117.0, 4.5, 105.9, 2.4, 129.4, 17.5, 89.7, 23.3, 119.7, 34.0, 103.7, 70.0, 100.0, 76.3, 130.0, 17.5, 111.1, 61.1, 81.4, 90.6, 93.4, 13.7, 84.7, 61.8, 124.5, 31.7, 69.5, 98.6, 85.2, 89.7, 91.7, 84.2, 87.4, 40.8, 78.2, 37.3, 95.8, 78.1, 88.8, 84.1, 72.1, 95.7, 106.4, 66.3, 78.2, 94.7, 124.8, 33.2, 75.1, 60.3, 76.2, 63.0, 77.0, 66.3, 77.5, 70.0, 79.5, 75.5, 82.9, 55.8, 84.7, 55.2, 86.1, 54.3, 94.3, 51.5, 117.9, 36.0, 81.5, 56.2, 112.9, 52.4, 81.4, 80.5, 72.6, 84.7, 94.3, 68.0, 94.3, 29.4, 88.3, 74.9, 108.6, 29.4, 99.0, 37.2, 110.0, 41.3, 73.1, 90.8, 97.1, 72.2, 89.7, 78.8, 99.9, 59.4, 119.4, 43.3, 105.5, 60.2, 118.8, 47.8, 100.8, 46.8, 133.2, 2.2, 128.6, 0.8]}, {"rect": [257, 444, 535, 722], "points": [0.36203, 0.0287, 0.07511, 0.0, -0.03629, 0.37682, -0.00463, 0.0, -0.08439, -0.02597, 0.3588, 0.0, -105.71981, -253.02616, -52.63966, 1.0, 68.0, 44.6, 71.3, 30.3, 67.6, 47.8, 67.1, 51.1, 66.6, 53.4, 65.4, 61.1, 65.3, 64.4, 64.9, 69.0, 64.4, 73.2, 63.8, 79.1, 37.1, 83.8, 36.2, 14.7, 60.7, 43.2, 60.3, 50.7, 52.4, 45.7, 46.5, 48.8, 53.9, 51.1, 48.8, 52.0, 35.7, 62.6, 13.6, 11.9, 32.1, 54.8, -13.6, 43.2, 39.1, 54.3, 40.5, 54.3, 60.3, 47.3, 53.2, 48.8, 47.4, 50.3, 40.0, 54.3, 42.4, 58.0, 41.4, 54.4, 49.7, 53.0, 54.7, 52.9, 60.3, 52.9, 54.7, 78.2, 56.5, 72.1, 57.4, 67.7, 58.3, 63.5, 59.3, 60.3, 48.8, 58.0, 47.4, 59.4, 45.6, 61.5, 44.2, 63.8, 41.8, 41.9, -21.5, 4.5, 45.2, 56.6, 43.8, 57.1, 63.6, 29.9, 52.9, 28.1, 43.1, 0.8, 31.1, 4.6, 40.0, 68.6, -6.2, -10.2, 6.5, -7.9, 15.6, -4.1, 29.5, -3.8, -5.7, 6.4, 48.3, 20.2, -19.0, 23.4, 7.6, 64.9, 4.4, 71.7, -15.9, 5.4, -2.0, 53.8, 34.8, 88.9, 45.4, 9.6, 41.0, 58.9, -4.8, 21.5, 45.1, 98.1, 24.7, 87.9, 15.9, 81.5, 58.3, 99.9, 70.5, 35.9, 49.1, 38.1, 62.1, 35.9, 16.8, 74.6, 25.6, 81.9, 46.4, 94.8, -5.3, 59.8, 60.1, 96.6, 34.4, 93.9, -14.4, 22.5, 53.7, 59.4, 52.3, 61.7, 50.7, 64.9, 49.6, 68.6, 46.4, 74.0, 44.2, 53.1, 43.2, 52.5, 41.9, 51.3, 36.2, 47.5, 6.7, 27.2, 45.5, 53.9, 4.4, 44.6, 41.2, 78.7, 61.5, 91.5, 62.6, 85.0, 51.5, 83.7, 28.3, 64.0, 41.7, 25.3, 33.5, 72.3, 24.7, 22.9, 34.4, 32.2, 17.8, 34.1, 48.6, 89.8, 21.0, 68.1, 28.8, 76.4, 24.3, 54.7, -3.4, 34.1, 14.2, 54.3, -10.4, 38.3, 28.7, 41.4, -16.2, -11.2, -21.8, -12.9, 82.7, 85.2, 100.5, 19.8, 74.9, 44.1, 73.0, 51.6, 80.6, 47.3, 83.9, 51.0, 77.4, 52.9, 80.6, 54.2, 89.8, 65.9, 117.9, 20.4, 94.7, 58.5, 113.2, 51.7, 86.6, 57.6, 84.9, 57.6, 74.1, 48.3, 79.2, 50.3, 82.4, 52.6, 85.7, 57.6, 83.5, 60.4, 84.3, 57.5, 79.1, 55.2, 76.0, 54.2, 71.8, 53.7, 71.7, 79.1, 71.7, 72.7, 71.8, 68.5, 71.4, 64.0, 70.9, 60.8, 78.3, 59.8, 79.7, 61.1, 81.0, 63.4, 82.0, 65.8, 91.7, 45.2, 125.2, 16.7, 81.0, 58.6, 82.4, 59.4, 77.8, 30.8, 85.1, 30.3, 95.8, 5.1, 105.6, 11.0, 85.5, 70.9, 132.1, 1.4, 123.8, 1.4, 116.9, 4.2, 105.9, 2.3, 129.4, 17.2, 89.4, 23.1, 120.0, 33.7, 104.0, 70.0, 100.3, 76.1, 130.2, 17.5, 111.3, 60.9, 81.5, 90.3, 93.1, 13.4, 84.7, 61.7, 124.7, 31.4, 69.8, 98.5, 85.5, 89.4, 92.0, 83.9, 87.4, 40.6, 78.2, 37.3, 96.1, 77.8, 88.8, 83.8, 72.2, 95.4, 106.7, 66.2, 78.2, 94.4, 125.0, 33.1, 75.1, 60.3, 76.4, 63.0, 77.3, 66.2, 77.7, 70.0, 79.5, 75.5, 82.9, 55.7, 84.4, 55.2, 85.8, 54.3, 94.3, 51.3, 117.9, 35.9, 81.5, 56.1, 113.2, 52.1, 81.5, 80.2, 72.7, 84.6, 94.4, 67.7, 94.0, 29.1, 88.4, 74.6, 108.3, 29.1, 99.0, 36.9, 110.0, 41.0, 73.2, 90.7, 97.1, 71.9, 89.8, 78.7, 99.9, 59.1, 119.6, 43.3, 105.8, 59.9, 119.1, 47.5, 100.8, 46.5, 133.4, 1.9, 128.8, 0.5]}, {"rect": [257, 444, 535, 722], "points": [0.36239, 0.02757, 0.07511, 0.0, -0.03506, 0.37663, -0.00594, 0.0, -0.08482, -0.02486, 0.35867, 0.0, -106.98523, -252.13973, -51.80734, 1.0, 67.7, 44.6, 71.0, 30.3, 67.4, 47.8, 66.9, 51.1, 66.4, 53.3, 65.4, 60.8, 65.1, 64.4, 64.9, 68.7, 64.4, 73.2, 63.6, 78.9, 37.0, 83.7, 35.6, 14.7, 60.5, 42.9, 60.0, 50.7, 52.1, 45.6, 46.2, 48.8, 53.9, 51.1, 48.8, 52.0, 35.2, 62.6, 13.0, 12.0, 31.9, 54.8, -14.1, 43.6, 38.8, 54.3, 40.5, 54.3, 60.3, 47.1, 53.0, 48.7, 47.4, 50.6, 39.7, 54.3, 42.3, 58.0, 41.4, 54.7, 49.4, 53.3, 54.5, 52.9, 60.0, 52.9, 54.8, 77.9, 56.3, 71.9, 57.2, 67.7, 58.1, 63.5, 59.1, 60.3, 48.8, 58.0, 47.4, 59.4, 45.6, 61.3, 44.2, 63.6, 41.5, 41.8, -22.3, 4.8, 45.2, 56.6, 43.8, 57.1, 63.5, 29.9, 52.6, 28.0, 42.5, 0.6, 30.5, 4.7, 39.8, 68.6, -6.7, -10.1, 6.3, -7.8, 15.2, -3.8, 29.3, -3.7, -6.2, 6.5, 48.0, 20.2, -19.6, 23.6, 7.2, 65.0, 3.9, 71.9, -16.7, 5.6, -2.5, 53.9, 34.7, 88.9, 44.8, 9.6, 41.0, 58.9, -5.3, 21.7, 45.1, 98.1, 24.6, 88.0, 15.5, 81.8, 58.1, 99.9, 70.4, 35.8, 48.9, 38.1, 61.8, 35.9, 16.7, 74.6, 25.4, 81.9, 46.3, 94.8, -5.8, 59.9, 59.9, 96.3, 34.3, 93.9, -14.9, 22.6, 53.5, 59.3, 52.1, 61.6, 50.7, 64.9, 49.4, 68.6, 46.2, 73.8, 44.2, 53.3, 42.9, 52.5, 41.9, 51.5, 35.7, 47.5, 6.2, 27.5, 45.3, 53.9, 3.9, 44.7, 41.1, 78.7, 61.3, 91.3, 62.6, 84.7, 51.3, 83.4, 27.8, 64.0, 41.2, 25.3, 33.3, 72.2, 24.1, 22.9, 34.1, 32.2, 17.3, 34.1, 48.4, 89.7, 20.8, 68.2, 28.6, 76.4, 24.0, 54.7, -3.9, 34.4, 13.9, 54.4, -10.8, 38.7, 28.2, 41.5, -16.8, -11.0, -22.4, -12.4, 82.5, 85.1, 100.4, 19.7, 74.7, 43.8, 72.8, 51.6, 80.6, 47.1, 83.9, 50.7, 77.3, 52.6, 80.6, 54.0, 89.8, 65.8, 117.8, 20.5, 94.5, 58.4, 113.2, 51.8, 86.5, 57.6, 85.1, 57.5, 74.1, 48.0, 79.2, 50.2, 82.4, 52.5, 85.7, 57.6, 83.7, 60.4, 84.2, 57.2, 78.9, 54.9, 76.0, 54.0, 71.8, 53.4, 71.6, 78.8, 71.8, 72.7, 71.8, 68.2, 71.4, 64.0, 70.9, 60.7, 78.3, 59.5, 79.7, 60.9, 81.0, 63.2, 82.0, 65.7, 91.7, 45.1, 125.1, 16.9, 81.0, 58.5, 82.4, 59.4, 77.7, 30.7, 85.1, 30.3, 95.7, 5.0, 105.7, 10.9, 85.3, 70.8, 132.0, 1.3, 123.8, 1.3, 116.9, 4.1, 105.8, 2.2, 129.3, 17.3, 89.4, 23.0, 119.8, 33.9, 104.0, 69.9, 100.3, 76.2, 130.2, 17.4, 111.4, 61.0, 81.5, 90.2, 93.0, 13.3, 84.8, 61.6, 124.7, 31.5, 69.7, 98.5, 85.3, 89.3, 92.1, 84.1, 87.1, 40.5, 77.9, 37.2, 95.9, 77.7, 88.9, 83.7, 72.0, 95.3, 106.8, 66.2, 78.3, 94.3, 124.8, 33.0, 75.1, 60.3, 76.4, 62.7, 77.3, 65.9, 77.8, 69.9, 79.3, 75.4, 82.9, 55.6, 84.6, 54.9, 86.0, 54.2, 94.0, 51.4, 118.1, 35.8, 81.5, 56.1, 113.2, 52.0, 81.5, 80.1, 72.5, 84.3, 94.4, 67.6, 94.0, 29.2, 88.4, 74.5, 108.5, 29.2, 98.9, 36.8, 110.0, 40.9, 73.2, 90.6, 97.1, 71.8, 89.8, 78.6, 99.9, 59.2, 119.6, 43.2, 105.8, 59.8, 118.9, 47.6, 100.8, 46.4, 133.4, 1.8, 128.8, 0.7]}, {"rect": [257, 444, 535, 722], "points": [0.3622, 0.02589, 0.07497, 0.0, -0.03327, 0.37596, -0.00645, 0.0, -0.08502, -0.02375, 0.35783, 0.0, -108.32037, -250.65913, -51.4008, 1.0, 67.7, 44.3, 70.9, 30.0, 67.6, 47.6, 67.1, 50.8, 66.3, 53.0, 65.4, 60.8, 65.3, 64.2, 64.9, 68.6, 64.4, 73.2, 63.7, 78.8, 37.3, 83.5, 35.5, 14.5, 60.6, 42.9, 60.2, 50.7, 52.1, 45.6, 46.4, 48.8, 53.8, 51.1, 48.8, 52.0, 35.4, 62.7, 12.9, 12.2, 31.8, 54.8, -13.9, 43.6, 39.0, 54.4, 40.5, 54.4, 60.3, 47.0, 52.9, 48.5, 47.4, 50.6, 39.6, 54.4, 42.3, 58.1, 41.4, 54.7, 49.6, 53.0, 54.7, 52.6, 60.2, 52.6, 54.8, 77.9, 56.6, 71.9, 57.4, 67.7, 58.4, 63.2, 59.3, 60.0, 48.8, 58.1, 47.4, 59.4, 45.6, 61.3, 44.2, 63.6, 41.5, 41.6, -22.2, 5.3, 45.4, 56.7, 43.7, 57.1, 63.2, 29.6, 52.5, 27.8, 42.3, 0.6, 30.4, 4.8, 40.0, 68.3, -6.9, -9.9, 5.9, -7.7, 15.1, -3.9, 28.9, -3.7, -6.1, 6.7, 47.9, 20.0, -19.5, 23.8, 7.4, 65.1, 4.2, 72.0, -16.6, 5.9, -2.3, 54.1, 35.1, 89.0, 44.7, 9.4, 40.9, 59.0, -5.1, 21.9, 45.3, 98.1, 24.9, 88.0, 15.8, 81.7, 58.2, 99.6, 70.1, 35.6, 48.8, 37.9, 61.8, 35.6, 16.7, 74.7, 25.5, 81.7, 46.6, 94.6, -5.6, 60.1, 60.0, 96.3, 34.6, 93.7, -14.8, 22.9, 53.8, 59.1, 52.1, 61.4, 50.7, 64.9, 49.6, 68.6, 46.5, 73.8, 44.2, 53.3, 42.9, 52.5, 41.8, 51.5, 35.8, 47.5, 6.4, 27.5, 45.4, 53.9, 4.1, 44.8, 41.1, 78.4, 61.4, 91.2, 62.7, 84.5, 51.6, 83.4, 28.0, 64.1, 41.1, 25.1, 33.6, 72.0, 24.0, 22.8, 34.1, 32.0, 17.4, 34.2, 48.5, 89.5, 20.8, 68.2, 28.7, 76.2, 24.0, 54.5, -3.7, 34.4, 13.9, 54.5, -10.7, 38.9, 28.2, 41.5, -16.7, -10.7, -22.6, -12.1, 82.5, 84.8, 100.3, 19.4, 74.6, 43.8, 72.8, 51.3, 80.6, 47.0, 84.1, 50.7, 77.3, 52.5, 80.5, 53.9, 89.8, 65.4, 117.7, 19.9, 94.7, 58.1, 113.1, 51.5, 86.5, 57.5, 85.1, 57.2, 74.1, 47.9, 79.2, 49.9, 82.4, 52.5, 85.9, 57.5, 83.7, 60.3, 84.2, 57.1, 79.1, 54.8, 75.9, 53.9, 71.8, 53.1, 71.8, 78.7, 71.8, 72.4, 71.8, 68.2, 71.4, 64.0, 70.9, 60.5, 78.6, 59.4, 79.6, 60.8, 81.0, 63.1, 82.3, 65.5, 91.6, 44.7, 124.9, 16.6, 81.0, 58.5, 82.4, 59.4, 77.5, 30.4, 84.8, 30.0, 95.3, 4.7, 105.4, 10.6, 85.3, 70.5, 131.5, 1.0, 123.4, 0.9, 116.6, 3.7, 105.5, 1.9, 129.2, 16.7, 89.3, 22.7, 119.9, 33.6, 104.0, 69.6, 100.3, 75.6, 130.0, 17.0, 111.3, 60.4, 81.6, 89.8, 92.9, 13.0, 85.0, 61.3, 124.6, 31.0, 70.0, 98.2, 85.6, 88.9, 92.1, 83.8, 87.1, 40.1, 77.9, 36.9, 96.1, 77.4, 88.9, 83.4, 72.3, 95.3, 106.7, 65.9, 78.4, 94.0, 124.7, 32.7, 75.1, 60.0, 76.4, 62.6, 77.3, 65.9, 77.8, 69.9, 79.3, 75.2, 82.8, 55.3, 84.6, 54.8, 86.0, 53.9, 94.0, 51.1, 117.8, 35.4, 81.4, 55.8, 113.1, 51.6, 81.5, 79.7, 72.7, 84.0, 94.4, 67.3, 93.9, 28.7, 88.4, 74.2, 108.2, 28.7, 98.6, 36.4, 109.9, 40.6, 73.3, 90.3, 97.1, 71.4, 89.8, 78.3, 99.9, 58.9, 119.6, 42.8, 105.8, 59.4, 119.0, 47.1, 100.8, 46.1, 133.2, 1.4, 128.6, 0.2]}, {"rect": [257, 444, 535, 722], "points": [0.36196, 0.02393, 0.0753, 0.0, -0.03124, 0.37513, -0.00635, 0.0, -0.08603, -0.02259, 0.35661, 0.0, -109.97023, -248.80216, -51.659, 1.0, 67.7, 44.3, 70.8, 29.9, 67.6, 47.5, 66.8, 51.0, 66.3, 53.0, 65.4, 60.8, 65.3, 64.4, 64.9, 68.6, 64.5, 73.1, 63.9, 79.0, 37.6, 83.7, 35.6, 14.8, 60.3, 42.8, 60.2, 50.6, 52.0, 45.6, 46.3, 48.8, 53.8, 51.1, 48.7, 52.0, 35.6, 62.9, 12.7, 12.6, 31.9, 55.1, -13.9, 44.3, 38.9, 54.4, 40.6, 54.4, 60.2, 47.0, 52.9, 48.5, 47.3, 50.3, 39.7, 54.4, 42.2, 58.1, 41.2, 54.5, 49.6, 53.0, 54.6, 52.5, 60.2, 52.5, 54.8, 78.0, 56.6, 71.8, 57.4, 67.7, 58.4, 63.2, 59.3, 60.2, 48.7, 58.1, 47.3, 59.4, 45.8, 61.3, 44.1, 63.6, 41.6, 41.8, -22.6, 5.8, 45.3, 56.7, 43.9, 57.2, 63.3, 29.8, 52.6, 28.0, 42.1, 1.0, 30.2, 5.1, 40.2, 68.5, -7.1, -9.4, 5.6, -7.2, 14.8, -3.6, 28.7, -3.6, -6.2, 7.2, 47.7, 20.2, -19.8, 24.6, 7.7, 65.5, 4.4, 72.4, -16.8, 6.6, -2.1, 54.5, 35.4, 89.2, 44.5, 9.7, 40.8, 59.0, -5.3, 22.3, 45.6, 98.1, 25.3, 88.3, 16.0, 82.0, 58.5, 99.8, 70.3, 35.7, 48.7, 38.1, 61.9, 35.8, 16.9, 75.0, 25.7, 82.0, 46.9, 94.7, -5.6, 60.8, 60.3, 96.2, 35.0, 93.9, -15.0, 23.6, 53.7, 59.3, 52.3, 61.6, 50.9, 64.9, 49.6, 68.6, 46.5, 74.0, 44.3, 53.1, 43.0, 52.5, 41.8, 51.5, 35.7, 47.7, 6.3, 28.0, 45.4, 53.9, 4.0, 45.2, 41.3, 78.6, 61.7, 91.1, 63.0, 84.6, 51.9, 83.6, 28.0, 64.4, 41.1, 25.3, 33.8, 72.2, 24.1, 23.1, 33.9, 32.3, 17.3, 34.6, 48.8, 89.7, 21.0, 68.5, 28.9, 76.4, 24.1, 54.8, -3.9, 35.0, 14.0, 54.8, -10.8, 39.3, 28.3, 41.8, -17.1, -9.9, -23.0, -11.3, 82.8, 84.7, 99.9, 19.3, 74.6, 43.7, 72.7, 51.5, 80.5, 47.0, 83.8, 50.6, 77.2, 52.4, 80.5, 53.8, 89.7, 65.3, 117.3, 19.8, 94.4, 57.9, 113.0, 51.2, 86.4, 57.4, 85.0, 57.1, 74.0, 47.9, 79.1, 50.0, 82.3, 52.4, 85.6, 57.4, 83.7, 60.3, 84.1, 57.1, 79.0, 54.7, 75.9, 53.8, 71.7, 53.3, 71.8, 78.7, 71.8, 72.3, 71.8, 68.1, 71.6, 63.9, 70.9, 60.7, 78.5, 59.4, 79.6, 60.8, 81.0, 63.0, 82.3, 65.4, 91.5, 44.6, 124.4, 16.3, 80.8, 58.4, 82.3, 59.3, 77.3, 30.4, 84.7, 29.9, 95.1, 4.7, 104.9, 10.3, 85.5, 70.3, 130.9, 0.6, 123.2, 0.6, 116.7, 3.4, 105.3, 1.6, 128.7, 16.6, 89.2, 22.6, 119.4, 33.3, 104.0, 69.4, 100.3, 75.4, 129.5, 16.7, 111.2, 60.3, 81.9, 89.7, 92.5, 12.9, 84.7, 61.2, 124.2, 30.8, 70.3, 98.1, 85.6, 88.8, 92.3, 83.4, 87.0, 40.0, 77.8, 36.8, 96.1, 77.3, 89.1, 83.2, 72.6, 95.2, 106.6, 65.7, 78.6, 93.9, 124.5, 32.3, 75.0, 60.2, 76.3, 62.6, 77.3, 65.8, 77.8, 69.6, 79.5, 75.3, 82.8, 55.3, 84.5, 54.7, 85.9, 53.9, 93.9, 50.9, 117.7, 35.1, 81.3, 55.7, 112.8, 51.5, 81.5, 79.6, 72.8, 84.1, 94.3, 67.1, 93.8, 28.6, 88.4, 74.0, 108.0, 28.5, 98.4, 36.3, 109.6, 40.4, 73.5, 90.2, 97.0, 71.3, 90.0, 78.2, 99.8, 58.8, 119.4, 42.5, 105.7, 59.3, 118.6, 46.9, 100.7, 46.0, 132.6, 1.1, 128.0, 0.1]}, {"rect": [257, 443, 535, 721], "points": [0.36166, 0.02168, 0.07426, 0.0, -0.02883, 0.37349, -0.00783, 0.0, -0.08765, -0.02051, 0.3544, 0.0, -112.08897, -245.88928, -49.9316, 1.0, 67.6, 44.9, 70.7, 30.1, 67.3, 48.2, 66.7, 51.4, 66.2, 53.4, 65.3, 61.1, 65.3, 64.7, 64.9, 69.0, 64.4, 73.2, 63.9, 79.0, 37.6, 84.2, 34.9, 15.6, 60.2, 43.3, 59.9, 51.0, 51.9, 46.3, 46.0, 49.2, 53.4, 51.5, 48.3, 52.4, 35.0, 63.1, 12.3, 13.6, 31.3, 55.3, -14.3, 45.7, 38.2, 55.1, 39.8, 55.1, 59.9, 47.4, 52.5, 49.1, 47.0, 51.0, 39.1, 55.1, 41.8, 58.7, 40.6, 55.1, 49.2, 53.7, 54.3, 52.9, 59.9, 52.9, 54.7, 78.1, 56.5, 72.2, 57.1, 68.1, 58.1, 63.8, 58.9, 60.6, 48.4, 58.7, 47.0, 60.1, 45.2, 62.0, 43.8, 64.3, 40.9, 42.3, -23.1, 7.7, 44.8, 57.4, 43.3, 57.8, 62.9, 30.0, 52.0, 28.5, 41.4, 1.7, 29.5, 6.2, 39.6, 68.9, -7.8, -7.8, 4.5, -6.2, 13.7, -2.8, 27.5, -2.9, -6.9, 8.7, 47.3, 20.7, -20.0, 26.2, 7.5, 66.5, 4.4, 73.4, -17.5, 8.3, -2.5, 55.8, 35.7, 89.6, 43.8, 10.5, 40.4, 59.7, -5.7, 23.6, 45.9, 98.5, 25.5, 88.8, 16.2, 82.7, 58.8, 99.9, 69.9, 35.6, 48.2, 38.3, 61.5, 36.0, 16.9, 75.8, 25.9, 82.7, 47.2, 95.1, -5.7, 61.8, 60.6, 96.6, 35.2, 94.3, -15.6, 25.0, 53.4, 59.7, 52.0, 62.1, 50.6, 65.3, 49.3, 69.0, 46.4, 74.3, 43.7, 53.8, 42.4, 52.9, 41.4, 52.0, 35.0, 47.9, 5.8, 28.9, 44.8, 54.3, 3.6, 46.3, 41.3, 79.0, 61.9, 91.5, 62.9, 84.9, 51.9, 83.7, 27.9, 64.8, 40.4, 25.8, 33.6, 72.7, 23.4, 23.9, 33.5, 33.0, 16.9, 35.3, 49.0, 90.1, 20.9, 69.0, 28.9, 76.8, 23.5, 55.2, -4.3, 36.1, 13.6, 55.5, -11.2, 40.7, 27.6, 42.3, -17.7, -8.0, -23.6, -9.4, 82.8, 84.7, 99.4, 19.4, 74.5, 44.1, 72.7, 51.8, 80.4, 47.4, 83.7, 51.0, 76.9, 52.8, 80.1, 54.2, 89.7, 65.3, 116.6, 20.1, 94.3, 58.0, 112.1, 51.5, 86.0, 57.5, 84.4, 57.4, 73.7, 48.3, 78.8, 50.2, 82.0, 52.5, 85.2, 57.5, 83.3, 60.6, 83.5, 57.4, 78.7, 55.1, 75.5, 54.2, 71.4, 53.4, 72.0, 78.9, 71.8, 72.6, 71.8, 68.5, 71.4, 64.3, 70.8, 61.0, 77.9, 59.7, 79.5, 61.1, 81.0, 63.4, 82.0, 65.7, 91.4, 44.7, 122.9, 16.8, 80.2, 58.8, 81.9, 59.4, 77.2, 30.5, 84.6, 30.0, 94.4, 5.3, 104.5, 10.6, 85.4, 70.4, 129.7, 1.2, 122.5, 0.8, 116.0, 3.7, 104.9, 2.1, 127.7, 16.9, 88.8, 23.0, 118.3, 33.8, 103.6, 69.5, 100.0, 75.5, 128.3, 16.9, 110.7, 60.3, 81.9, 89.7, 92.1, 13.3, 84.3, 61.6, 123.5, 30.8, 70.4, 98.4, 85.6, 88.8, 92.1, 83.7, 86.9, 40.1, 77.6, 37.0, 95.8, 77.3, 88.9, 83.3, 72.7, 95.3, 106.1, 65.8, 78.7, 94.0, 123.6, 32.6, 74.9, 60.6, 76.0, 62.9, 77.3, 66.2, 77.8, 70.0, 79.5, 75.3, 82.4, 55.6, 83.9, 55.1, 85.6, 54.2, 93.8, 50.8, 117.1, 35.3, 81.0, 56.1, 112.4, 51.5, 81.4, 79.9, 73.0, 84.1, 94.2, 67.2, 93.4, 28.9, 88.3, 74.1, 107.4, 28.6, 98.1, 36.4, 109.2, 40.5, 73.5, 90.5, 96.7, 71.3, 89.8, 78.2, 99.5, 58.6, 118.6, 42.7, 105.1, 59.3, 118.0, 46.9, 100.3, 46.0, 130.9, 1.7, 126.2, 0.7]}, {"rect": [256, 443, 534, 721], "points": [0.3617, 0.01974, 0.07358, 0.0, -0.02693, 0.37256, -0.00749, 0.0, -0.08805, -0.02044, 0.35459, 0.0, -113.58986, -244.26263, -49.73887, 1.0, 67.9, 44.8, 70.7, 30.0, 67.6, 48.1, 67.1, 51.0, 66.5, 53.2, 65.6, 61.0, 65.6, 64.4, 65.3, 68.9, 64.8, 73.1, 64.2, 78.5, 37.9, 84.0, 34.8, 15.8, 60.3, 43.4, 60.1, 50.9, 51.9, 46.3, 46.0, 49.1, 53.7, 51.4, 48.4, 52.4, 35.2, 62.9, 12.1, 13.9, 31.2, 55.2, -14.1, 46.0, 38.2, 55.0, 40.0, 55.0, 60.2, 47.3, 52.8, 49.1, 47.3, 50.9, 39.1, 55.0, 41.9, 58.7, 40.9, 55.1, 49.2, 53.6, 54.4, 52.8, 60.2, 52.8, 55.0, 77.6, 56.9, 72.1, 57.5, 68.0, 58.4, 63.4, 59.2, 60.5, 48.7, 58.6, 47.3, 59.7, 45.5, 61.9, 44.0, 64.2, 40.9, 42.2, -23.2, 7.9, 45.0, 57.3, 43.3, 57.7, 62.9, 30.0, 51.9, 28.5, 41.2, 2.0, 29.6, 6.2, 39.9, 68.5, -7.8, -7.4, 4.7, -5.8, 14.0, -2.6, 27.8, -2.9, -6.9, 8.9, 47.2, 20.6, -20.0, 26.3, 7.5, 66.4, 4.4, 73.3, -17.4, 8.7, -2.5, 55.8, 36.0, 89.5, 43.9, 10.5, 40.5, 59.6, -5.8, 24.0, 46.5, 98.3, 25.9, 88.9, 16.3, 82.9, 59.5, 99.7, 70.1, 35.5, 48.1, 38.2, 61.5, 35.9, 17.1, 75.7, 26.0, 82.6, 47.6, 94.7, -5.7, 61.8, 61.0, 96.2, 35.6, 94.2, -15.5, 25.3, 53.4, 59.6, 52.3, 62.0, 50.9, 65.2, 49.6, 68.9, 46.7, 73.9, 43.8, 53.7, 42.4, 52.8, 41.4, 51.9, 35.2, 47.9, 5.7, 29.1, 45.0, 54.2, 3.7, 46.5, 41.6, 78.6, 62.4, 91.0, 63.3, 84.5, 52.2, 83.2, 27.9, 64.7, 40.3, 26.0, 33.8, 72.5, 23.6, 24.1, 33.4, 33.0, 16.8, 35.6, 49.4, 89.7, 21.0, 69.2, 29.2, 76.7, 23.6, 55.4, -4.4, 36.4, 13.6, 55.5, -11.3, 40.9, 27.7, 42.2, -17.8, -7.8, -23.7, -9.2, 83.1, 84.5, 99.6, 19.2, 74.5, 44.0, 73.0, 51.5, 80.5, 47.3, 83.7, 50.6, 77.2, 52.4, 80.4, 53.9, 89.9, 64.8, 116.8, 19.7, 94.5, 57.5, 112.4, 51.0, 86.0, 57.1, 84.6, 57.0, 74.0, 48.2, 79.0, 50.1, 82.2, 52.4, 85.4, 57.1, 83.6, 60.2, 83.7, 57.0, 78.7, 54.7, 75.8, 53.8, 71.7, 53.2, 72.1, 78.2, 72.2, 72.3, 72.2, 68.1, 71.7, 63.9, 71.1, 60.7, 78.2, 59.3, 79.6, 61.0, 81.3, 63.0, 82.3, 65.4, 91.4, 44.3, 123.1, 16.4, 80.5, 58.4, 82.2, 59.2, 77.4, 30.5, 84.8, 29.9, 94.3, 5.0, 104.4, 10.5, 85.5, 69.9, 129.6, 0.8, 122.4, 0.4, 116.1, 3.5, 104.8, 1.8, 127.7, 16.5, 89.0, 22.6, 118.5, 33.1, 104.0, 69.0, 100.3, 75.0, 128.2, 16.5, 111.0, 59.8, 82.3, 89.3, 92.3, 13.2, 84.6, 61.2, 123.4, 30.4, 71.0, 97.9, 86.0, 88.4, 92.5, 83.2, 87.1, 39.8, 77.8, 36.9, 96.2, 76.8, 89.2, 82.8, 73.1, 94.8, 106.4, 65.3, 79.1, 93.7, 123.6, 32.1, 75.2, 60.2, 76.3, 62.5, 77.6, 65.8, 78.1, 69.8, 79.8, 74.5, 82.6, 55.2, 84.1, 54.7, 85.6, 53.9, 94.0, 50.3, 117.3, 34.9, 81.0, 55.7, 112.7, 51.0, 81.7, 79.2, 73.4, 83.7, 94.3, 66.7, 93.6, 28.6, 88.6, 73.6, 107.6, 28.4, 98.3, 36.0, 109.4, 40.0, 73.9, 90.1, 97.1, 70.8, 90.1, 77.7, 99.7, 58.1, 118.8, 42.2, 105.4, 58.8, 118.0, 46.4, 100.6, 45.6, 130.9, 1.3, 126.0, 0.3]}, {"rect": [255, 442, 533, 720], "points": [0.36229, 0.01845, 0.07253, 0.0, -0.02488, 0.37227, -0.00723, 0.0, -0.08729, -0.02133, 0.35628, 0.0, -115.39197, -243.54101, -49.33661, 1.0, 67.9, 44.7, 70.1, 30.6, 67.7, 47.9, 67.3, 51.0, 66.5, 53.2, 65.6, 60.7, 65.7, 64.4, 65.6, 68.9, 65.1, 73.2, 64.0, 78.2, 37.7, 84.1, 34.3, 16.0, 60.4, 43.3, 60.1, 51.0, 51.9, 46.1, 45.9, 49.2, 53.7, 51.5, 48.6, 52.5, 35.1, 62.9, 11.4, 14.1, 31.1, 55.5, -14.2, 45.9, 38.2, 54.9, 40.0, 54.9, 60.4, 47.4, 52.8, 49.2, 47.2, 51.0, 39.1, 54.9, 41.8, 58.5, 40.8, 55.2, 49.2, 53.5, 54.6, 52.8, 60.1, 52.8, 55.1, 77.3, 56.9, 72.2, 57.7, 68.0, 58.6, 63.4, 59.2, 60.3, 48.7, 58.4, 47.3, 59.8, 45.4, 61.7, 44.0, 64.1, 40.7, 42.6, -23.3, 8.1, 45.0, 57.1, 43.6, 57.6, 62.6, 30.5, 51.5, 28.8, 40.5, 2.2, 28.9, 6.3, 39.8, 68.5, -8.5, -7.4, 3.9, -5.6, 13.2, -2.3, 27.0, -2.5, -7.6, 9.1, 46.8, 21.0, -20.2, 26.6, 7.2, 66.5, 4.3, 73.4, -18.1, 8.7, -2.6, 55.9, 35.8, 89.3, 43.2, 10.8, 40.4, 59.4, -6.5, 24.2, 46.4, 98.3, 25.9, 88.8, 16.3, 82.7, 59.7, 99.7, 69.6, 36.1, 47.8, 38.8, 61.2, 36.5, 16.9, 75.8, 26.0, 82.7, 47.4, 94.7, -5.8, 61.9, 61.1, 96.4, 35.7, 94.2, -15.9, 25.3, 53.6, 59.4, 52.3, 62.0, 50.9, 65.3, 49.6, 68.9, 46.7, 73.6, 43.7, 53.8, 42.3, 52.9, 41.3, 52.0, 34.8, 48.4, 5.0, 29.3, 45.0, 54.3, 3.1, 46.7, 41.6, 78.6, 62.2, 91.0, 63.1, 84.2, 52.0, 83.2, 27.8, 64.8, 39.9, 26.4, 33.8, 72.6, 22.9, 24.3, 33.0, 33.4, 16.3, 35.7, 49.3, 89.7, 20.9, 69.2, 29.1, 76.7, 23.3, 55.5, -4.8, 36.6, 13.2, 55.5, -11.7, 40.9, 27.0, 42.6, -18.6, -7.7, -23.9, -9.1, 83.0, 84.4, 99.1, 19.5, 74.7, 44.1, 73.0, 51.4, 80.4, 47.3, 83.6, 50.6, 77.2, 52.4, 80.4, 54.1, 89.5, 64.7, 116.5, 19.8, 94.1, 57.7, 112.7, 51.1, 86.0, 57.4, 84.6, 57.0, 73.9, 48.2, 79.0, 50.1, 82.2, 52.4, 85.1, 57.4, 83.3, 60.2, 83.7, 57.0, 78.6, 54.7, 75.8, 54.0, 71.6, 53.3, 71.9, 78.0, 72.5, 72.6, 72.5, 68.4, 72.0, 63.9, 71.1, 60.7, 78.1, 59.3, 79.5, 60.8, 81.3, 63.0, 82.3, 65.6, 90.9, 44.7, 123.3, 16.5, 80.4, 58.3, 81.9, 59.2, 76.7, 31.0, 84.1, 30.4, 93.9, 5.3, 104.0, 10.7, 85.2, 69.7, 129.7, 0.9, 122.0, 0.6, 115.3, 3.8, 104.4, 2.0, 127.8, 16.6, 88.2, 23.1, 118.7, 33.1, 104.1, 69.1, 100.4, 75.0, 128.3, 16.6, 111.3, 59.8, 82.4, 89.4, 91.7, 13.5, 84.6, 61.2, 123.4, 30.7, 71.0, 97.8, 86.1, 88.5, 92.6, 83.3, 86.4, 40.5, 77.1, 37.4, 96.2, 76.9, 89.3, 82.9, 73.2, 94.9, 106.7, 65.3, 79.3, 93.7, 123.8, 32.2, 75.0, 60.2, 76.3, 62.5, 77.6, 66.1, 78.2, 69.8, 79.4, 74.4, 82.4, 55.5, 84.1, 54.7, 85.5, 54.1, 93.6, 50.7, 117.0, 35.0, 80.9, 55.9, 112.8, 51.1, 81.6, 79.3, 73.2, 83.5, 94.1, 66.8, 93.1, 29.1, 88.4, 73.7, 107.3, 28.6, 97.8, 36.4, 109.2, 40.1, 73.8, 90.0, 97.1, 70.9, 89.9, 77.8, 99.5, 58.4, 118.8, 42.3, 105.4, 58.9, 118.3, 46.5, 100.1, 46.0, 131.0, 1.4, 126.3, 0.4]}, {"rect": [253, 441, 531, 719], "points": [0.36316, 0.01658, 0.07327, 0.0, -0.02299, 0.37137, -0.00718, 0.0, -0.08753, -0.0227, 0.35894, 0.0, -117.26032, -242.34844, -50.01163, 1.0, 67.9, 44.7, 70.4, 30.7, 67.6, 47.9, 67.1, 50.8, 66.6, 53.0, 65.8, 60.4, 65.8, 64.1, 65.8, 68.7, 65.3, 73.2, 64.4, 77.6, 37.8, 83.8, 33.9, 16.0, 60.3, 43.5, 60.2, 50.7, 52.0, 46.4, 46.0, 49.3, 53.8, 51.5, 48.7, 52.5, 34.8, 62.7, 10.9, 14.2, 30.7, 55.2, -14.8, 45.7, 38.6, 55.1, 40.1, 55.2, 60.2, 47.4, 52.9, 49.2, 47.4, 51.1, 39.2, 55.2, 42.0, 58.5, 41.0, 55.2, 49.3, 53.5, 54.7, 52.6, 60.2, 52.6, 55.3, 76.7, 56.8, 72.0, 57.7, 67.8, 58.5, 63.2, 59.4, 60.0, 48.8, 58.1, 47.4, 59.6, 45.6, 61.7, 44.0, 64.1, 40.3, 42.4, -23.9, 8.2, 45.1, 57.1, 43.7, 57.6, 62.6, 30.3, 51.3, 28.9, 40.2, 2.2, 28.4, 6.4, 39.7, 68.2, -9.3, -7.0, 4.4, -5.2, 13.9, -1.9, 27.7, -2.3, -8.3, 9.2, 46.6, 21.0, -20.8, 26.6, 6.8, 66.1, 4.0, 72.9, -18.6, 9.0, -2.9, 55.4, 36.0, 89.2, 42.9, 10.9, 40.6, 59.4, -7.0, 24.0, 46.7, 98.0, 25.7, 88.5, 16.0, 82.5, 60.2, 99.1, 69.9, 36.1, 47.6, 38.6, 61.2, 36.3, 16.8, 75.5, 26.0, 82.4, 47.9, 94.4, -6.1, 61.4, 61.6, 95.8, 35.7, 93.9, -16.3, 25.3, 53.8, 59.4, 52.5, 61.8, 50.8, 65.1, 49.8, 68.7, 46.6, 73.0, 44.1, 53.8, 42.7, 53.0, 41.4, 52.1, 34.4, 48.3, 4.5, 29.4, 45.1, 54.3, 2.7, 46.3, 41.6, 78.3, 63.0, 90.4, 63.5, 83.6, 52.5, 82.7, 27.4, 64.6, 39.7, 26.3, 33.5, 72.4, 22.4, 24.3, 32.5, 33.2, 15.9, 35.6, 49.7, 89.4, 20.5, 68.8, 28.9, 76.5, 22.9, 55.3, -5.2, 36.4, 12.8, 55.3, -12.1, 40.9, 26.6, 42.4, -19.3, -7.2, -24.8, -8.6, 83.6, 83.6, 99.4, 18.9, 74.5, 44.1, 73.1, 51.2, 80.5, 47.2, 83.7, 50.5, 77.3, 52.4, 80.5, 53.8, 90.1, 64.1, 116.8, 19.0, 94.6, 56.9, 113.2, 50.0, 86.1, 57.2, 84.7, 56.9, 74.0, 47.9, 79.1, 50.0, 82.3, 52.3, 85.2, 57.2, 83.7, 59.8, 83.8, 56.9, 78.7, 54.6, 75.9, 53.5, 71.8, 53.0, 72.3, 77.2, 72.7, 72.4, 72.6, 68.1, 72.1, 63.6, 71.0, 60.4, 78.3, 59.0, 79.7, 60.7, 81.4, 62.9, 82.4, 65.3, 91.4, 44.2, 123.5, 15.4, 80.6, 58.0, 82.0, 58.9, 77.2, 31.1, 84.6, 29.9, 94.0, 5.0, 104.1, 10.2, 85.6, 68.9, 129.8, 0.1, 122.2, 0.1, 115.7, 3.2, 104.4, 1.5, 128.0, 15.8, 88.7, 22.9, 119.1, 32.0, 104.8, 68.0, 101.1, 74.0, 128.5, 15.8, 111.8, 58.8, 83.1, 88.6, 92.0, 13.3, 84.7, 61.1, 123.8, 29.6, 71.7, 97.3, 86.8, 87.7, 93.3, 82.2, 86.9, 40.0, 77.4, 37.2, 96.9, 75.8, 90.0, 82.1, 73.9, 94.1, 107.2, 64.0, 80.3, 93.1, 124.2, 31.1, 75.1, 59.9, 76.5, 62.2, 77.8, 65.8, 78.6, 69.6, 80.0, 73.5, 82.5, 55.2, 84.2, 54.6, 85.6, 53.7, 93.9, 50.2, 117.4, 33.9, 81.0, 55.6, 113.2, 50.0, 82.2, 78.5, 73.6, 82.7, 94.7, 66.0, 93.4, 28.6, 88.8, 72.9, 107.6, 28.1, 98.3, 35.9, 109.5, 39.3, 74.4, 89.1, 97.8, 69.9, 90.5, 76.8, 100.2, 57.4, 119.2, 41.3, 106.1, 57.8, 118.7, 45.4, 100.7, 45.2, 131.1, 0.6, 126.2, -0.4]}, {"rect": [252, 440, 530, 718], "points": [0.36293, 0.01532, 0.07261, 0.0, -0.02151, 0.37127, -0.00689, 0.0, -0.08645, -0.02334, 0.35982, 0.0, -118.16978, -241.86979, -49.73894, 1.0, 67.0, 44.6, 70.0, 30.6, 66.9, 47.8, 66.5, 51.0, 66.0, 52.9, 65.4, 60.3, 65.4, 64.3, 65.4, 68.9, 65.0, 73.4, 64.2, 77.7, 37.5, 83.5, 33.6, 15.8, 59.6, 43.3, 59.6, 50.7, 51.6, 46.4, 45.6, 49.6, 53.4, 51.5, 48.3, 52.8, 34.4, 62.7, 10.7, 14.0, 30.6, 55.0, -14.9, 45.5, 38.5, 55.1, 40.3, 55.2, 59.6, 47.4, 52.5, 49.2, 47.0, 51.1, 39.4, 55.2, 42.1, 58.5, 40.9, 55.3, 49.2, 53.7, 54.3, 52.8, 59.9, 52.8, 55.0, 76.8, 56.7, 72.5, 57.6, 68.0, 58.1, 63.4, 59.0, 59.9, 48.7, 58.1, 47.3, 59.7, 45.5, 61.7, 44.1, 64.3, 39.8, 42.4, -23.8, 7.9, 45.0, 57.1, 43.6, 57.6, 62.2, 30.3, 51.1, 28.9, 40.0, 2.0, 28.1, 6.2, 39.4, 68.2, -9.5, -7.2, 4.0, -5.3, 13.2, -1.8, 27.3, -2.3, -8.6, 9.1, 46.1, 20.8, -20.9, 26.3, 6.7, 66.0, 4.0, 72.6, -18.8, 8.7, -3.1, 55.2, 35.7, 88.9, 42.5, 10.7, 40.7, 59.4, -7.2, 23.8, 46.7, 97.7, 25.6, 88.4, 16.0, 82.2, 60.0, 98.9, 69.5, 35.9, 47.2, 38.6, 60.8, 36.3, 16.5, 75.3, 25.7, 82.1, 47.6, 94.3, -6.1, 61.2, 61.4, 95.7, 35.6, 93.6, -16.4, 25.2, 53.4, 59.3, 52.1, 61.7, 50.7, 65.3, 49.7, 69.0, 46.3, 73.2, 44.0, 53.8, 42.6, 53.2, 41.3, 52.3, 34.2, 48.0, 4.3, 29.2, 45.0, 54.3, 2.5, 46.3, 41.2, 78.3, 62.7, 90.2, 63.2, 83.7, 52.2, 82.8, 27.1, 64.5, 39.3, 26.3, 33.4, 72.3, 22.2, 24.1, 32.3, 33.2, 15.5, 35.6, 49.4, 89.3, 20.2, 68.7, 28.8, 76.5, 22.8, 55.1, -5.3, 36.3, 12.7, 55.1, -12.2, 40.5, 26.4, 42.4, -19.4, -7.5, -24.7, -9.1, 83.4, 83.6, 98.9, 18.8, 73.8, 43.7, 72.4, 51.1, 79.8, 46.9, 83.3, 50.1, 76.9, 52.0, 80.1, 53.4, 89.8, 63.9, 116.4, 18.8, 94.1, 56.9, 113.2, 49.5, 86.0, 56.6, 84.6, 56.6, 73.4, 47.8, 78.4, 49.7, 81.6, 52.0, 85.1, 56.6, 83.3, 59.4, 83.7, 56.3, 78.3, 54.3, 75.5, 53.4, 71.4, 52.9, 72.0, 77.2, 72.3, 72.5, 72.3, 68.0, 71.5, 63.5, 70.9, 60.3, 78.2, 58.8, 79.6, 60.3, 81.0, 62.6, 82.3, 65.2, 90.8, 44.1, 123.6, 15.0, 80.5, 57.6, 81.9, 58.5, 76.9, 30.8, 84.2, 29.8, 93.8, 4.6, 103.9, 10.0, 85.2, 69.0, 129.6, -0.3, 121.5, -0.1, 114.8, 2.8, 103.7, 1.4, 127.8, 15.3, 88.3, 22.6, 119.1, 31.6, 104.5, 67.7, 101.1, 73.7, 128.6, 15.3, 111.7, 58.5, 82.9, 88.4, 91.5, 12.9, 84.6, 60.7, 123.7, 29.2, 71.5, 97.0, 86.6, 87.5, 93.3, 82.0, 86.5, 39.9, 77.0, 36.8, 96.7, 75.8, 89.8, 81.9, 73.7, 93.9, 107.2, 63.7, 80.1, 92.9, 124.2, 30.9, 75.0, 59.7, 76.3, 62.1, 77.4, 65.7, 78.2, 69.7, 79.7, 73.6, 82.3, 54.8, 83.8, 54.3, 85.2, 53.4, 93.5, 50.1, 117.2, 33.7, 80.7, 55.3, 113.1, 49.8, 82.0, 78.3, 73.3, 82.8, 94.4, 65.8, 93.0, 28.4, 88.5, 72.8, 107.2, 27.7, 98.0, 35.8, 109.4, 39.1, 74.2, 89.2, 97.5, 69.9, 90.3, 76.8, 99.8, 57.4, 119.1, 41.0, 105.8, 57.6, 118.7, 45.2, 100.3, 45.0, 131.0, 0.1, 126.3, -1.1]}, {"rect": [250, 439, 528, 717], "points": [0.36266, 0.01358, 0.07193, 0.0, -0.01906, 0.37087, -0.00719, 0.0, -0.08556, -0.02226, 0.35979, 0.0, -119.63053, -240.6279, -49.09302, 1.0, 67.3, 44.4, 70.1, 30.1, 67.2, 47.6, 66.7, 50.8, 66.3, 52.7, 65.5, 60.0, 65.8, 63.7, 65.7, 68.4, 65.4, 72.9, 64.8, 77.1, 38.2, 83.4, 33.7, 16.1, 59.9, 43.0, 59.9, 50.7, 51.6, 46.2, 45.7, 49.4, 53.5, 51.3, 48.4, 52.6, 35.3, 62.7, 10.8, 14.3, 31.2, 55.2, -14.2, 46.0, 38.4, 54.9, 40.2, 55.0, 59.9, 47.2, 52.6, 48.9, 47.0, 50.8, 39.3, 55.0, 42.1, 58.5, 41.0, 55.3, 49.3, 53.5, 54.4, 52.7, 59.9, 52.6, 55.6, 76.6, 57.0, 72.0, 57.9, 67.4, 58.5, 63.2, 59.4, 59.8, 48.8, 58.0, 47.5, 59.5, 45.7, 61.7, 44.3, 64.1, 40.2, 42.4, -23.4, 8.7, 45.1, 57.1, 43.8, 57.6, 62.3, 30.0, 51.2, 28.7, 39.8, 2.0, 27.9, 6.5, 40.0, 68.2, -9.5, -6.8, 3.5, -5.0, 12.8, -1.7, 26.6, -2.2, -8.5, 9.6, 46.2, 20.8, -20.2, 27.0, 7.4, 66.3, 4.9, 73.1, -18.7, 9.3, -2.6, 55.7, 36.4, 88.6, 42.5, 10.7, 40.7, 59.4, -6.9, 24.4, 47.4, 97.3, 26.5, 88.1, 16.9, 82.4, 60.6, 98.3, 69.6, 35.6, 47.5, 38.4, 60.9, 36.0, 17.4, 75.5, 26.6, 82.0, 48.3, 93.7, -5.2, 61.7, 62.0, 95.1, 36.3, 93.5, -16.1, 25.8, 53.6, 59.1, 52.5, 61.7, 51.1, 65.0, 50.1, 68.7, 46.9, 72.9, 43.9, 53.6, 42.5, 53.0, 41.2, 52.1, 34.6, 48.0, 4.7, 29.5, 44.9, 54.1, 3.2, 46.5, 41.9, 78.0, 63.4, 89.9, 63.9, 83.1, 52.8, 82.5, 28.0, 64.6, 39.6, 26.3, 34.0, 72.3, 22.2, 24.4, 32.4, 33.2, 15.8, 35.9, 50.1, 89.0, 21.1, 68.7, 29.4, 76.5, 23.4, 55.3, -4.9, 36.8, 13.3, 55.6, -11.5, 41.3, 26.8, 42.5, -19.5, -6.9, -24.3, -8.3, 83.7, 83.1, 98.9, 18.2, 74.1, 43.4, 72.7, 50.8, 80.0, 46.3, 83.4, 49.6, 77.0, 51.7, 80.2, 53.1, 90.1, 63.4, 116.4, 18.2, 94.4, 56.4, 113.5, 49.3, 86.1, 56.0, 84.5, 56.0, 73.6, 47.5, 78.7, 49.4, 81.9, 51.4, 85.2, 56.0, 83.4, 59.1, 83.8, 55.9, 78.6, 53.7, 75.6, 53.1, 71.4, 52.7, 72.6, 76.7, 72.6, 72.0, 72.4, 67.5, 71.8, 63.2, 70.9, 59.9, 78.3, 58.3, 79.7, 60.0, 81.1, 62.0, 82.4, 64.7, 91.1, 43.5, 123.7, 14.8, 80.6, 57.3, 82.0, 58.2, 76.9, 30.2, 84.3, 29.3, 93.6, 4.3, 103.7, 9.5, 85.6, 68.4, 129.4, -0.7, 121.2, -0.7, 114.7, 2.5, 103.6, 1.1, 127.6, 14.9, 88.3, 22.3, 119.2, 31.4, 104.8, 67.3, 101.3, 73.3, 128.5, 14.9, 111.9, 58.1, 83.3, 88.0, 91.3, 12.6, 84.7, 60.2, 123.8, 28.8, 72.1, 96.4, 87.0, 87.1, 93.5, 81.6, 86.6, 39.4, 77.3, 36.5, 97.0, 75.2, 90.2, 81.2, 74.1, 93.6, 107.6, 63.6, 80.4, 92.3, 124.3, 30.5, 75.1, 59.2, 76.5, 61.8, 77.7, 65.2, 78.3, 68.9, 80.1, 73.3, 82.4, 54.5, 83.9, 53.7, 85.2, 52.8, 93.8, 49.5, 117.3, 33.3, 81.0, 55.0, 113.2, 49.4, 82.4, 77.9, 73.7, 82.2, 94.7, 65.2, 93.0, 27.9, 88.8, 72.4, 107.2, 27.3, 98.0, 35.2, 109.5, 38.5, 74.6, 88.6, 97.7, 69.3, 90.7, 76.2, 99.9, 56.8, 119.2, 40.6, 105.9, 57.2, 119.1, 44.8, 100.4, 44.4, 130.8, -0.3, 126.1, -1.2]}, {"rect": [249, 438, 527, 716], "points": [0.36144, 0.01224, 0.07135, 0.0, -0.01767, 0.37011, -0.00695, 0.0, -0.08487, -0.02176, 0.35881, 0.0, -120.00765, -239.26354, -48.76484, 1.0, 66.9, 44.7, 69.9, 30.0, 66.5, 47.6, 66.1, 50.8, 65.7, 52.9, 65.1, 60.1, 65.2, 63.8, 65.2, 68.5, 65.1, 73.0, 64.6, 77.3, 38.2, 83.3, 33.6, 16.2, 59.5, 43.3, 59.5, 50.7, 51.3, 46.5, 45.6, 49.4, 53.1, 51.5, 48.0, 52.6, 35.1, 63.0, 10.9, 14.7, 31.3, 55.3, -13.9, 46.4, 38.3, 55.0, 40.1, 55.2, 59.5, 47.4, 52.2, 49.0, 46.7, 51.1, 39.2, 55.2, 42.0, 58.5, 40.7, 55.3, 48.9, 53.5, 54.0, 52.9, 59.6, 52.5, 55.4, 76.8, 56.8, 72.1, 57.4, 67.6, 58.2, 63.3, 59.1, 59.8, 48.5, 58.0, 47.1, 59.7, 45.6, 61.7, 44.2, 64.3, 40.4, 42.4, -23.2, 9.2, 44.8, 57.1, 43.4, 57.6, 62.1, 30.0, 51.1, 28.6, 39.7, 2.3, 28.0, 6.8, 40.1, 68.1, -9.4, -6.4, 3.4, -4.6, 12.6, -1.3, 26.4, -1.8, -8.3, 10.1, 46.1, 21.1, -20.0, 27.2, 7.7, 66.6, 5.0, 73.2, -18.5, 9.7, -2.4, 56.1, 36.4, 88.8, 42.4, 11.0, 40.6, 59.4, -6.9, 24.8, 47.4, 97.2, 26.6, 88.3, 17.0, 82.4, 60.4, 98.4, 69.2, 35.5, 47.5, 38.6, 60.8, 36.0, 17.5, 75.5, 26.7, 82.0, 48.3, 93.8, -5.1, 62.0, 61.8, 94.9, 36.4, 93.5, -16.1, 26.2, 53.5, 59.2, 52.2, 61.6, 50.8, 65.2, 49.8, 68.9, 46.9, 73.1, 43.8, 53.9, 42.4, 53.1, 41.1, 52.1, 34.9, 48.3, 4.9, 29.9, 44.7, 54.3, 3.2, 46.9, 41.9, 78.2, 63.2, 89.8, 63.6, 83.3, 52.6, 82.4, 28.0, 64.8, 39.5, 26.3, 34.0, 72.3, 22.1, 24.5, 32.6, 33.2, 16.0, 36.0, 49.8, 88.9, 21.2, 69.0, 29.5, 76.5, 23.5, 55.6, -4.7, 37.2, 13.4, 55.7, -11.5, 41.5, 27.0, 42.8, -19.1, -6.4, -24.1, -7.8, 83.5, 82.9, 98.3, 18.4, 73.4, 43.4, 72.1, 51.1, 79.4, 46.3, 83.1, 49.8, 76.6, 51.7, 79.8, 53.0, 89.5, 63.5, 115.8, 18.3, 94.0, 56.2, 113.0, 49.2, 85.8, 55.9, 84.3, 55.9, 73.0, 47.5, 78.1, 49.4, 81.3, 51.3, 84.9, 55.9, 83.1, 59.0, 83.5, 55.9, 78.1, 53.9, 75.2, 53.1, 71.1, 52.9, 72.4, 76.8, 72.1, 72.1, 72.0, 67.6, 71.5, 63.3, 70.6, 59.8, 78.0, 58.4, 79.4, 59.9, 80.8, 62.1, 82.1, 64.5, 90.8, 43.4, 123.1, 14.7, 80.3, 57.2, 81.7, 58.1, 76.6, 30.3, 83.9, 29.4, 93.1, 4.2, 103.3, 9.6, 85.3, 68.5, 128.7, -0.8, 120.7, -0.8, 114.2, 2.4, 103.2, 1.0, 127.1, 14.7, 87.7, 22.2, 118.9, 31.3, 104.3, 67.1, 101.0, 73.2, 128.0, 14.8, 111.6, 58.0, 83.0, 87.9, 90.9, 12.5, 84.4, 60.3, 123.1, 28.9, 71.9, 96.3, 86.7, 86.9, 93.1, 81.4, 86.2, 39.2, 77.0, 36.4, 96.5, 75.0, 89.9, 81.0, 73.8, 93.4, 107.0, 63.4, 79.9, 92.1, 123.9, 30.4, 74.8, 59.3, 76.1, 61.7, 77.2, 65.2, 78.0, 69.0, 79.8, 73.2, 82.1, 54.4, 83.5, 53.6, 84.9, 52.7, 93.2, 49.3, 116.7, 33.1, 80.7, 54.9, 112.6, 49.2, 82.1, 77.8, 73.7, 82.3, 94.2, 65.3, 92.7, 27.8, 88.5, 72.3, 106.6, 27.2, 97.4, 35.1, 108.9, 38.6, 74.3, 88.4, 97.3, 69.1, 90.4, 76.0, 99.6, 56.7, 118.9, 40.5, 105.6, 57.1, 118.5, 44.6, 100.0, 44.3, 130.1, -0.4, 125.5, -1.3]}, {"rect": [247, 436, 525, 714], "points": [0.36062, 0.01087, 0.0709, 0.0, -0.01632, 0.36891, -0.00708, 0.0, -0.08427, -0.02117, 0.35847, 0.0, -120.35829, -237.37613, -48.41688, 1.0, 67.3, 45.2, 70.1, 30.2, 66.9, 48.3, 66.7, 51.5, 66.3, 53.4, 65.5, 60.2, 65.9, 63.9, 65.6, 68.8, 65.5, 73.0, 65.0, 77.6, 38.8, 83.8, 33.8, 16.8, 59.9, 43.8, 59.9, 51.2, 51.7, 47.0, 46.0, 50.1, 53.5, 52.1, 48.4, 53.3, 35.6, 63.5, 11.2, 15.3, 31.6, 55.8, -13.3, 47.1, 38.7, 55.7, 40.4, 55.8, 59.9, 47.9, 52.6, 49.7, 47.1, 51.6, 39.6, 55.8, 42.4, 58.9, 41.0, 55.8, 49.3, 54.3, 54.4, 53.4, 60.0, 53.0, 55.8, 77.1, 57.2, 72.4, 58.1, 67.9, 58.6, 63.5, 59.5, 59.9, 48.9, 58.5, 47.5, 59.9, 46.0, 62.1, 44.7, 64.5, 40.6, 42.9, -22.9, 10.2, 45.2, 57.5, 43.8, 58.0, 62.3, 30.2, 51.6, 29.2, 40.0, 2.9, 28.2, 7.4, 40.6, 68.6, -9.1, -5.4, 3.7, -4.0, 12.9, -0.4, 26.7, -0.9, -7.7, 10.7, 46.5, 21.4, -19.6, 28.2, 8.3, 66.9, 5.6, 73.7, -17.9, 10.6, -1.8, 56.7, 36.9, 89.0, 42.8, 11.6, 41.0, 59.9, -6.3, 25.5, 47.9, 97.6, 26.9, 88.5, 17.6, 82.9, 60.8, 98.6, 69.6, 35.7, 47.9, 38.9, 61.2, 36.5, 18.0, 76.0, 27.2, 82.5, 48.8, 94.0, -4.5, 62.6, 62.3, 95.3, 36.9, 93.9, -15.5, 26.8, 53.9, 59.4, 52.6, 61.7, 51.2, 65.3, 50.3, 69.3, 47.2, 73.5, 44.2, 54.4, 42.8, 53.8, 41.5, 52.9, 35.1, 48.9, 5.2, 30.5, 45.1, 54.8, 3.8, 47.5, 42.4, 78.7, 63.6, 90.1, 64.1, 83.6, 53.1, 82.8, 28.3, 65.3, 39.7, 26.9, 34.3, 72.7, 22.6, 25.3, 32.8, 33.8, 16.3, 36.5, 50.3, 89.3, 21.7, 69.5, 30.0, 76.9, 24.0, 56.2, -4.1, 37.8, 13.9, 56.2, -10.9, 42.3, 27.3, 43.3, -18.8, -5.5, -23.8, -6.8, 83.9, 83.3, 98.6, 18.6, 73.8, 44.0, 72.4, 51.6, 79.8, 47.0, 83.4, 50.2, 77.0, 52.1, 80.2, 53.5, 89.9, 63.9, 116.1, 18.6, 94.4, 56.6, 113.3, 49.3, 86.2, 56.6, 84.7, 56.6, 73.3, 48.0, 78.4, 49.8, 81.7, 52.0, 85.3, 56.6, 83.5, 59.4, 83.9, 56.6, 78.4, 54.4, 75.6, 53.8, 71.5, 53.4, 72.8, 77.2, 72.5, 72.4, 72.4, 67.9, 71.9, 63.5, 71.0, 60.2, 78.4, 58.5, 79.8, 60.3, 81.2, 62.5, 82.6, 64.9, 90.9, 43.8, 123.4, 14.8, 80.7, 57.6, 82.1, 58.5, 76.9, 30.6, 84.2, 29.6, 93.4, 4.7, 103.5, 9.8, 85.7, 68.9, 128.9, -0.4, 120.7, -0.4, 114.2, 2.8, 103.2, 1.5, 127.2, 14.9, 88.0, 22.7, 119.2, 31.7, 104.6, 67.3, 101.3, 73.3, 128.1, 15.2, 111.9, 58.1, 83.4, 88.0, 91.1, 13.0, 84.9, 60.7, 123.4, 29.1, 72.4, 96.7, 87.1, 87.0, 93.5, 81.5, 86.5, 39.7, 77.3, 36.6, 97.1, 75.2, 90.3, 81.2, 74.2, 93.5, 107.3, 63.6, 80.5, 92.2, 123.9, 30.5, 75.2, 59.4, 76.5, 62.0, 77.9, 65.4, 78.4, 69.4, 80.1, 73.5, 82.5, 54.9, 83.9, 54.3, 85.3, 53.3, 93.5, 49.8, 117.0, 33.3, 81.1, 55.3, 112.9, 49.4, 82.4, 78.2, 74.1, 82.7, 94.5, 65.4, 92.9, 28.2, 88.9, 72.6, 106.9, 27.6, 97.7, 35.5, 109.2, 38.8, 75.0, 88.8, 97.7, 69.5, 90.8, 76.4, 99.9, 57.1, 119.2, 40.6, 105.9, 57.2, 118.8, 44.8, 100.4, 44.7, 130.3, 0.0, 125.7, -0.9]}, {"rect": [246, 435, 524, 713], "points": [0.35952, 0.00972, 0.07047, 0.0, -0.01488, 0.36744, -0.00739, 0.0, -0.0838, -0.02097, 0.35706, 0.0, -120.79741, -235.54683, -47.9519, 1.0, 67.5, 45.5, 69.9, 30.7, 67.1, 48.4, 66.7, 51.5, 66.2, 53.4, 65.7, 59.9, 66.1, 63.5, 66.1, 67.9, 65.7, 72.4, 65.2, 77.2, 39.0, 83.7, 33.9, 17.4, 59.8, 44.2, 60.1, 51.5, 51.9, 47.3, 46.0, 50.2, 53.7, 52.3, 48.4, 53.4, 36.1, 63.4, 11.4, 16.0, 32.0, 56.1, -12.9, 47.6, 38.6, 56.0, 40.1, 56.0, 59.8, 48.3, 52.8, 49.8, 47.3, 51.9, 39.5, 56.0, 42.3, 58.9, 41.0, 56.0, 49.3, 54.3, 54.3, 53.7, 60.1, 53.3, 56.1, 76.8, 57.4, 71.5, 58.3, 67.3, 58.8, 63.1, 59.7, 59.8, 48.8, 58.4, 47.7, 59.8, 46.0, 62.0, 44.6, 64.4, 40.9, 43.2, -22.8, 10.9, 45.1, 57.5, 43.7, 58.0, 62.4, 30.7, 51.5, 29.5, 40.0, 3.5, 28.1, 7.8, 40.9, 68.5, -9.1, -4.7, 3.7, -3.3, 12.9, 0.3, 26.7, -0.5, -7.4, 11.4, 46.5, 22.0, -19.3, 28.8, 8.7, 67.2, 6.0, 74.0, -17.8, 11.3, -1.5, 57.0, 37.2, 89.1, 42.8, 11.9, 40.9, 60.1, -6.0, 26.1, 48.2, 97.5, 27.2, 88.7, 17.9, 83.1, 61.0, 98.4, 69.5, 36.2, 48.1, 39.4, 61.1, 36.8, 18.4, 76.2, 27.5, 82.7, 49.1, 94.1, -4.2, 63.0, 62.5, 95.1, 37.2, 93.8, -15.2, 27.5, 53.8, 59.3, 52.8, 61.6, 51.4, 65.0, 50.5, 68.7, 47.7, 73.2, 44.1, 54.7, 42.7, 53.8, 41.4, 52.9, 35.4, 49.2, 5.5, 31.1, 45.1, 55.1, 4.1, 47.8, 42.7, 78.6, 63.8, 89.8, 64.3, 83.3, 53.3, 82.7, 28.8, 65.3, 39.9, 27.5, 34.8, 72.7, 22.6, 25.7, 33.0, 34.4, 16.5, 37.1, 50.5, 89.1, 22.0, 69.8, 30.3, 77.1, 24.2, 56.5, -4.0, 38.2, 14.2, 56.5, -10.6, 42.7, 27.5, 43.6, -18.7, -4.8, -23.8, -6.1, 84.0, 83.2, 98.4, 18.8, 74.0, 44.5, 72.6, 51.6, 80.0, 47.3, 83.6, 50.5, 77.2, 52.4, 80.1, 53.7, 90.0, 63.5, 115.9, 18.8, 94.3, 56.6, 113.2, 49.5, 86.4, 56.9, 84.7, 56.6, 73.5, 48.3, 78.6, 50.1, 81.9, 52.0, 85.5, 56.6, 83.7, 59.4, 83.8, 56.6, 78.6, 54.6, 75.8, 53.8, 71.7, 53.4, 73.0, 76.8, 73.0, 71.5, 72.6, 67.3, 72.1, 63.1, 71.2, 59.8, 78.6, 58.5, 79.9, 60.2, 81.4, 62.2, 82.8, 64.8, 91.0, 44.0, 123.0, 15.0, 80.9, 57.8, 82.3, 58.4, 76.7, 30.8, 83.8, 29.9, 93.0, 5.0, 103.1, 10.1, 85.6, 68.6, 128.5, -0.2, 120.3, -0.1, 113.8, 3.1, 102.7, 1.8, 127.0, 15.1, 87.8, 22.9, 118.8, 31.7, 104.7, 67.1, 101.2, 73.4, 127.6, 15.4, 111.8, 58.3, 83.5, 87.9, 90.7, 13.3, 85.1, 60.7, 123.3, 29.3, 72.5, 96.6, 87.2, 86.9, 93.4, 81.4, 86.4, 39.9, 77.2, 36.8, 97.0, 75.3, 90.2, 81.3, 74.4, 93.4, 107.2, 63.5, 80.5, 92.3, 123.5, 30.7, 75.3, 59.3, 76.7, 61.7, 78.1, 65.0, 78.6, 69.0, 80.0, 73.2, 82.7, 55.1, 84.1, 54.3, 85.5, 53.4, 93.4, 49.7, 116.8, 33.5, 81.0, 55.6, 112.8, 49.5, 82.3, 78.1, 74.0, 82.3, 94.6, 65.3, 92.6, 28.5, 89.1, 72.3, 106.8, 27.6, 97.6, 35.5, 109.0, 39.0, 74.9, 88.7, 97.8, 69.4, 90.9, 76.3, 99.8, 57.0, 118.8, 40.8, 105.8, 57.4, 118.4, 44.9, 100.2, 45.0, 129.9, 0.3, 125.4, -0.7]}, {"rect": [245, 434, 523, 712], "points": [0.35852, 0.00857, 0.06995, 0.0, -0.01411, 0.36575, -0.0067, 0.0, -0.08294, -0.02147, 0.35599, 0.0, -120.79636, -233.79204, -48.11704, 1.0, 67.0, 45.6, 69.8, 30.8, 66.9, 48.7, 66.4, 51.6, 66.0, 53.5, 65.7, 59.5, 65.9, 63.2, 65.9, 67.7, 65.4, 71.9, 64.9, 76.7, 39.1, 83.4, 33.7, 17.5, 59.8, 44.6, 59.9, 51.5, 51.6, 47.4, 45.7, 50.5, 53.5, 52.2, 48.3, 53.4, 35.9, 63.2, 11.2, 16.1, 32.0, 56.1, -12.8, 47.5, 38.6, 56.0, 40.0, 56.1, 59.5, 48.3, 52.5, 50.1, 47.0, 52.0, 39.5, 56.1, 42.3, 58.9, 40.9, 56.1, 49.2, 54.3, 54.3, 53.5, 59.9, 53.1, 56.0, 76.2, 57.5, 71.3, 58.1, 66.8, 58.8, 62.7, 59.4, 59.5, 48.8, 58.4, 47.5, 59.8, 46.0, 61.7, 44.6, 64.4, 40.9, 43.3, -22.5, 11.1, 45.0, 57.5, 43.7, 57.9, 62.1, 30.8, 51.5, 29.8, 39.7, 3.7, 28.1, 8.2, 40.9, 68.2, -9.1, -4.2, 3.7, -2.8, 12.9, 0.5, 26.6, -0.0, -7.4, 11.9, 46.5, 22.1, -19.0, 29.0, 8.8, 67.2, 6.1, 73.8, -17.5, 11.5, -1.4, 57.1, 37.3, 88.8, 42.7, 12.1, 40.9, 59.9, -5.9, 26.3, 47.9, 97.2, 27.2, 88.5, 18.0, 82.9, 60.7, 98.1, 69.3, 36.4, 47.9, 39.5, 60.8, 36.8, 18.4, 76.0, 27.3, 82.4, 48.9, 93.6, -4.1, 63.0, 62.4, 94.6, 37.3, 93.5, -14.8, 27.6, 53.8, 59.0, 52.5, 61.3, 51.2, 64.8, 50.2, 68.6, 47.7, 72.9, 43.8, 54.7, 42.5, 53.9, 41.4, 52.9, 35.4, 49.2, 5.5, 31.3, 45.0, 55.2, 4.1, 47.9, 42.7, 78.3, 63.5, 89.5, 64.3, 83.0, 53.2, 82.1, 28.6, 65.3, 39.7, 27.6, 34.9, 72.7, 22.6, 25.8, 33.0, 34.5, 16.5, 37.3, 50.5, 88.6, 22.0, 69.6, 30.3, 76.9, 24.0, 56.5, -3.7, 38.3, 14.2, 56.6, -10.2, 42.9, 27.6, 43.7, -18.4, -4.5, -23.5, -5.6, 83.7, 82.6, 98.0, 18.9, 73.8, 44.7, 72.3, 51.7, 79.7, 47.4, 83.3, 50.3, 76.9, 52.5, 80.1, 53.6, 89.7, 63.2, 115.5, 18.6, 94.2, 56.3, 113.1, 48.7, 86.4, 56.7, 84.6, 56.6, 73.3, 48.4, 78.3, 50.2, 81.9, 52.1, 85.5, 56.7, 83.7, 59.4, 83.8, 56.6, 78.6, 54.5, 75.6, 53.9, 71.4, 53.5, 72.7, 76.2, 72.8, 71.3, 72.7, 66.9, 71.9, 62.7, 71.0, 59.5, 78.3, 58.4, 79.7, 59.9, 81.4, 62.1, 82.8, 64.5, 90.6, 43.8, 122.8, 14.6, 80.6, 57.6, 82.3, 58.4, 76.4, 30.9, 83.7, 30.0, 92.6, 5.1, 102.7, 10.2, 85.5, 68.2, 128.3, -0.3, 120.1, -0.3, 113.6, 3.0, 102.5, 1.9, 126.6, 14.9, 87.4, 23.0, 118.6, 31.2, 104.4, 66.6, 101.1, 72.7, 127.5, 15.0, 111.7, 57.8, 83.2, 87.5, 90.6, 13.4, 85.0, 60.4, 122.9, 28.8, 72.2, 96.2, 86.9, 86.3, 93.3, 80.8, 86.0, 39.7, 76.8, 36.9, 96.9, 74.8, 90.1, 80.8, 74.1, 93.0, 107.1, 62.9, 80.4, 91.7, 123.3, 30.2, 75.1, 59.0, 76.5, 61.3, 77.8, 64.9, 78.6, 68.6, 79.9, 72.8, 82.5, 54.9, 84.1, 54.4, 85.5, 53.4, 93.3, 49.7, 116.5, 33.3, 81.0, 55.4, 112.6, 49.1, 82.2, 77.5, 73.7, 81.8, 94.3, 65.1, 92.4, 28.5, 88.7, 72.0, 106.6, 27.7, 97.4, 35.5, 108.7, 38.8, 74.9, 88.1, 97.5, 68.8, 90.6, 75.7, 99.7, 56.8, 118.6, 40.3, 105.7, 56.9, 118.2, 44.5, 99.9, 44.8, 129.7, -0.1, 125.4, -1.1]}, {"rect": [244, 433, 522, 711], "points": [0.35719, 0.00792, 0.06967, 0.0, -0.01342, 0.36412, -0.00636, 0.0, -0.08229, -0.02145, 0.35422, 0.0, -120.64528, -232.19406, -48.11472, 1.0, 67.2, 46.0, 69.3, 31.0, 66.9, 48.8, 66.4, 51.7, 66.0, 53.5, 65.6, 59.2, 65.9, 62.9, 65.9, 67.4, 65.4, 71.5, 64.6, 76.5, 39.1, 83.4, 33.6, 17.9, 59.6, 44.7, 59.9, 51.6, 51.6, 47.5, 45.6, 50.4, 53.4, 52.5, 48.3, 53.5, 35.8, 63.1, 11.4, 16.5, 31.7, 55.9, -12.3, 47.8, 38.3, 55.8, 39.7, 55.8, 59.5, 48.4, 52.5, 50.2, 47.0, 52.1, 39.2, 55.8, 42.0, 58.6, 40.6, 55.8, 49.0, 54.4, 54.1, 53.5, 59.9, 53.4, 55.8, 76.1, 57.3, 70.7, 58.0, 66.5, 58.6, 62.3, 59.4, 59.2, 48.8, 58.1, 47.5, 59.5, 45.7, 61.5, 44.3, 64.0, 40.6, 43.4, -22.0, 11.4, 44.8, 57.2, 43.4, 57.7, 61.8, 31.0, 51.2, 29.9, 39.6, 4.1, 28.1, 8.4, 40.9, 68.2, -8.6, -3.8, 3.7, -2.4, 12.9, 0.9, 26.4, 0.4, -7.1, 12.0, 46.4, 22.2, -18.7, 29.4, 9.0, 67.2, 6.6, 73.8, -17.2, 11.9, -1.1, 57.1, 37.3, 88.6, 42.4, 12.5, 40.6, 59.9, -5.7, 26.6, 47.9, 96.9, 27.5, 88.4, 18.2, 82.6, 60.5, 97.8, 68.8, 36.5, 47.8, 39.6, 60.5, 37.0, 18.7, 76.0, 27.6, 82.2, 48.8, 93.6, -3.6, 63.1, 61.9, 94.5, 37.3, 93.2, -14.6, 28.0, 53.6, 58.7, 52.5, 61.0, 51.1, 64.3, 50.2, 68.2, 47.4, 72.8, 43.8, 54.5, 42.4, 53.9, 41.1, 53.0, 35.3, 49.3, 5.8, 31.4, 44.8, 55.0, 4.4, 48.3, 42.7, 78.0, 63.2, 89.4, 64.0, 82.7, 53.0, 82.1, 28.8, 65.1, 39.6, 27.7, 34.9, 72.5, 22.5, 26.2, 32.8, 34.6, 16.5, 37.4, 50.3, 88.5, 22.0, 69.6, 30.4, 76.6, 24.2, 56.3, -3.5, 38.6, 14.2, 56.7, -9.9, 43.2, 27.5, 43.8, -18.1, -3.8, -23.2, -5.1, 83.4, 82.5, 97.7, 19.0, 73.8, 45.1, 72.3, 52.0, 79.8, 47.5, 83.1, 50.6, 76.6, 52.6, 79.8, 53.8, 89.1, 63.2, 115.1, 18.9, 93.7, 56.3, 112.5, 48.9, 86.2, 56.8, 84.4, 56.7, 73.3, 48.8, 78.3, 50.3, 81.7, 52.4, 85.3, 56.7, 83.5, 59.4, 83.8, 56.7, 78.4, 54.8, 75.5, 54.0, 71.4, 53.5, 72.4, 76.1, 72.8, 70.7, 72.5, 66.6, 71.9, 62.3, 70.9, 59.2, 78.3, 58.2, 79.7, 59.6, 81.2, 61.9, 82.5, 64.2, 90.0, 43.9, 122.1, 14.9, 80.6, 57.6, 82.0, 58.2, 75.8, 31.0, 83.1, 30.1, 92.2, 5.2, 102.3, 10.3, 84.9, 67.9, 127.6, -0.2, 119.7, 0.1, 112.9, 3.3, 101.9, 2.0, 126.2, 15.2, 86.8, 23.1, 118.1, 31.5, 103.8, 66.8, 100.6, 72.8, 127.1, 15.3, 111.1, 57.7, 82.7, 87.2, 90.0, 13.5, 84.8, 60.4, 122.5, 29.1, 71.9, 95.9, 86.4, 86.2, 92.7, 80.7, 85.4, 39.8, 76.2, 37.0, 96.4, 74.8, 89.5, 80.7, 73.8, 92.7, 106.5, 63.1, 79.9, 91.4, 122.9, 30.5, 75.1, 58.7, 76.5, 61.0, 77.8, 64.6, 78.4, 68.3, 79.4, 72.5, 82.5, 55.2, 83.9, 54.4, 85.3, 53.5, 92.8, 49.8, 116.1, 33.6, 80.7, 55.7, 112.1, 49.3, 81.7, 77.4, 73.4, 81.7, 94.0, 65.1, 91.8, 28.6, 88.2, 71.9, 106.1, 27.7, 96.9, 35.6, 108.3, 38.8, 74.4, 88.0, 96.9, 68.8, 90.0, 75.7, 99.2, 56.8, 118.1, 40.6, 105.1, 57.1, 117.6, 44.7, 99.5, 44.8, 129.3, 0.2, 124.8, -0.8]}, {"rect": [243, 432, 521, 710], "points": [0.35638, 0.00761, 0.06974, 0.0, -0.01284, 0.3627, -0.00709, 0.0, -0.08249, -0.02201, 0.35325, 0.0, -120.79334, -230.9853, -47.73984, 1.0, 67.2, 46.1, 69.2, 31.4, 67.1, 48.9, 66.7, 52.0, 66.2, 53.8, 65.8, 59.5, 65.9, 63.1, 65.9, 67.3, 65.4, 71.4, 64.5, 76.5, 38.9, 83.4, 33.6, 18.1, 59.8, 45.1, 59.9, 51.7, 51.6, 47.9, 45.6, 50.7, 53.4, 52.6, 48.3, 53.6, 35.5, 63.1, 11.4, 16.7, 31.4, 56.1, -12.5, 48.0, 38.3, 55.9, 39.7, 55.9, 59.8, 48.8, 52.5, 50.3, 47.0, 52.2, 38.9, 55.9, 42.0, 58.6, 40.6, 55.9, 49.2, 54.5, 54.3, 53.8, 59.9, 53.5, 55.8, 76.3, 57.5, 70.5, 58.0, 66.4, 58.8, 62.3, 59.4, 59.4, 48.8, 58.1, 47.4, 59.5, 45.6, 61.7, 44.3, 63.8, 40.5, 43.8, -22.2, 11.6, 44.8, 57.2, 43.4, 57.7, 61.7, 31.4, 51.1, 30.1, 39.6, 4.3, 28.0, 8.8, 40.6, 68.2, -8.8, -3.6, 3.7, -1.9, 12.8, 1.3, 26.3, 0.6, -7.4, 12.4, 46.1, 22.6, -18.9, 29.5, 8.8, 67.3, 6.4, 74.1, -17.2, 12.1, -1.3, 57.2, 37.3, 88.6, 42.4, 12.9, 40.6, 59.9, -5.7, 26.8, 47.9, 96.9, 27.6, 88.5, 18.0, 82.9, 60.5, 97.8, 68.7, 36.9, 47.5, 39.7, 60.4, 37.4, 18.5, 76.0, 27.6, 82.4, 48.8, 93.6, -3.8, 63.1, 61.9, 94.5, 37.3, 93.2, -14.8, 28.2, 53.8, 58.9, 52.5, 60.9, 51.1, 64.5, 50.2, 67.9, 47.2, 72.8, 43.8, 54.8, 42.4, 54.0, 41.1, 53.1, 35.0, 49.3, 5.5, 31.7, 44.8, 55.3, 4.1, 48.4, 42.5, 78.3, 63.2, 89.4, 63.8, 82.8, 52.7, 82.0, 28.6, 65.3, 39.6, 28.1, 34.6, 72.7, 22.5, 26.4, 32.7, 35.0, 16.4, 37.7, 50.3, 88.5, 22.0, 69.6, 30.4, 76.9, 24.0, 56.3, -3.8, 38.7, 14.2, 56.7, -10.2, 43.3, 27.2, 43.8, -18.1, -3.6, -23.2, -4.9, 83.1, 82.5, 97.4, 19.4, 74.0, 45.2, 72.3, 52.1, 80.0, 47.8, 83.3, 50.8, 76.9, 52.9, 80.1, 53.9, 89.1, 63.4, 114.8, 19.3, 93.6, 56.6, 112.2, 49.2, 86.2, 57.0, 84.4, 56.7, 73.5, 48.9, 78.3, 50.6, 81.9, 52.6, 85.2, 57.0, 83.5, 59.4, 83.8, 56.7, 78.3, 54.9, 75.5, 54.3, 71.4, 53.8, 72.1, 76.3, 72.8, 70.6, 72.7, 66.7, 71.9, 62.3, 70.9, 59.4, 78.3, 58.4, 79.7, 59.8, 81.4, 62.1, 82.6, 64.4, 90.0, 44.2, 121.7, 15.5, 80.6, 57.6, 82.0, 58.4, 75.7, 31.5, 83.1, 30.4, 92.1, 5.9, 102.0, 10.6, 84.9, 68.1, 127.2, 0.3, 119.3, 0.4, 112.8, 3.7, 101.8, 2.3, 125.8, 15.5, 86.8, 23.5, 118.0, 32.0, 103.7, 67.0, 100.5, 73.0, 126.7, 15.6, 110.8, 57.9, 82.6, 87.5, 89.9, 13.9, 84.8, 60.4, 122.2, 29.4, 71.7, 95.9, 86.3, 86.5, 92.7, 80.9, 85.4, 40.1, 76.2, 37.4, 96.1, 75.0, 89.5, 80.9, 73.8, 92.7, 106.5, 63.4, 79.9, 91.6, 122.6, 30.7, 75.1, 58.9, 76.5, 61.2, 77.8, 64.5, 78.7, 68.2, 79.4, 72.7, 82.5, 55.3, 83.9, 54.7, 85.3, 53.8, 92.7, 49.8, 115.8, 34.0, 80.7, 55.7, 112.0, 49.6, 81.7, 77.4, 73.4, 81.9, 93.7, 65.3, 91.7, 29.0, 88.1, 72.2, 106.0, 28.0, 96.8, 35.9, 108.3, 39.1, 74.3, 88.0, 96.9, 69.0, 90.0, 75.9, 99.1, 57.0, 118.0, 40.9, 104.8, 57.4, 117.5, 45.0, 99.2, 45.0, 128.7, 0.7, 124.4, -0.5]}, {"rect": [242, 432, 520, 710], "points": [0.35621, 0.00701, 0.07016, 0.0, -0.01217, 0.36134, -0.00712, 0.0, -0.08276, -0.02294, 0.35278, 0.0, -121.29876, -229.90622, -48.11798, 1.0, 67.2, 46.0, 69.4, 31.4, 67.1, 48.8, 66.7, 51.7, 66.2, 53.5, 65.8, 59.3, 65.8, 62.6, 65.8, 66.8, 65.7, 71.0, 64.5, 76.0, 39.1, 83.0, 33.5, 18.0, 59.8, 44.8, 59.9, 51.6, 51.6, 47.8, 45.6, 50.6, 53.4, 52.4, 48.4, 53.5, 35.4, 62.7, 11.1, 16.6, 31.3, 55.8, -12.8, 47.9, 38.3, 55.7, 40.0, 55.7, 59.8, 48.4, 52.5, 50.2, 47.0, 52.1, 39.1, 55.7, 42.0, 58.5, 40.9, 55.7, 49.3, 54.3, 54.3, 53.5, 59.9, 53.4, 55.8, 75.9, 57.4, 70.1, 58.0, 66.0, 58.8, 61.8, 59.4, 59.0, 48.8, 57.7, 47.4, 59.1, 45.6, 61.3, 44.3, 63.6, 40.3, 43.7, -22.5, 11.6, 45.1, 57.1, 43.6, 57.5, 61.6, 31.4, 51.0, 30.0, 39.6, 4.5, 28.0, 8.8, 40.5, 68.1, -8.8, -3.6, 3.7, -2.2, 12.6, 1.1, 26.4, 0.5, -7.4, 12.4, 46.0, 22.6, -19.2, 29.4, 8.7, 66.9, 6.1, 73.7, -17.4, 12.0, -1.4, 57.1, 37.3, 88.4, 42.3, 12.9, 40.6, 59.5, -6.0, 26.7, 48.0, 96.7, 27.6, 88.1, 18.0, 82.5, 60.8, 97.6, 68.7, 36.9, 47.4, 39.7, 60.3, 37.3, 18.5, 75.7, 27.6, 82.0, 48.9, 93.1, -4.0, 62.8, 62.2, 94.0, 37.4, 93.0, -15.1, 28.1, 53.8, 58.5, 52.5, 60.8, 51.1, 64.0, 50.1, 67.7, 47.3, 72.6, 43.8, 54.5, 42.4, 53.9, 41.3, 53.0, 34.9, 49.0, 5.5, 31.4, 45.0, 54.9, 3.8, 48.0, 42.5, 77.8, 63.2, 88.9, 64.0, 82.4, 53.0, 81.6, 28.5, 65.0, 39.5, 28.0, 34.6, 72.3, 22.5, 26.3, 32.6, 34.7, 16.1, 37.4, 50.6, 88.0, 21.7, 69.2, 30.4, 76.5, 23.9, 56.2, -4.1, 38.7, 13.9, 56.6, -10.5, 43.0, 27.1, 43.7, -18.4, -3.6, -23.4, -4.7, 83.4, 82.1, 97.5, 19.3, 74.0, 45.1, 72.3, 52.0, 80.0, 47.5, 83.3, 50.6, 76.9, 52.6, 80.1, 53.8, 89.3, 62.8, 114.7, 18.9, 93.5, 56.2, 112.4, 48.8, 86.2, 56.6, 84.7, 56.6, 73.5, 48.8, 78.3, 50.3, 81.9, 52.4, 85.3, 56.6, 83.7, 59.0, 83.9, 56.6, 78.4, 54.7, 75.5, 53.9, 71.4, 53.5, 72.3, 75.6, 72.7, 70.3, 72.7, 66.3, 72.1, 62.1, 70.9, 59.0, 78.3, 58.0, 79.7, 59.4, 81.5, 61.7, 82.8, 64.0, 90.2, 44.1, 121.6, 15.1, 80.6, 57.4, 82.0, 58.0, 75.9, 31.7, 83.3, 30.4, 92.0, 5.6, 102.1, 10.6, 85.1, 67.7, 127.1, 0.0, 119.2, 0.3, 112.4, 3.5, 101.7, 2.3, 125.7, 15.2, 87.0, 23.4, 118.0, 31.4, 103.8, 66.4, 100.5, 72.4, 126.6, 15.2, 111.0, 57.5, 82.9, 87.0, 89.8, 13.8, 84.8, 60.2, 122.1, 29.0, 71.9, 95.4, 86.6, 85.8, 92.7, 80.3, 85.6, 40.0, 76.4, 37.3, 96.3, 74.6, 89.5, 80.3, 74.1, 92.5, 106.5, 62.7, 80.1, 91.2, 122.6, 30.4, 75.1, 58.5, 76.8, 60.8, 77.8, 64.1, 78.7, 67.7, 79.6, 72.3, 82.5, 55.2, 84.2, 54.3, 85.5, 53.5, 93.0, 49.7, 116.0, 33.6, 80.9, 55.4, 112.0, 48.9, 81.9, 76.9, 73.6, 81.5, 93.9, 64.9, 91.7, 28.7, 88.4, 71.5, 105.9, 27.7, 97.0, 35.5, 108.3, 38.7, 74.6, 87.6, 97.1, 68.6, 90.2, 75.5, 99.1, 56.6, 118.0, 40.5, 105.0, 56.7, 117.5, 44.3, 99.5, 44.6, 128.6, 0.4, 124.3, -0.6]}, {"rect": [241, 431, 519, 709], "points": [0.35595, 0.00637, 0.06976, 0.0, -0.01152, 0.36036, -0.00765, 0.0, -0.08231, -0.02371, 0.35239, 0.0, -121.61367, -228.86751, -47.50953, 1.0, 67.2, 46.4, 69.2, 31.9, 67.1, 49.2, 66.7, 52.0, 66.3, 53.9, 65.8, 59.4, 65.9, 62.7, 65.9, 66.9, 65.5, 71.0, 64.6, 76.1, 39.2, 83.4, 33.3, 18.5, 59.9, 45.2, 59.9, 52.0, 51.6, 48.0, 45.7, 51.0, 53.5, 52.6, 48.4, 53.8, 35.2, 62.8, 11.1, 17.1, 31.0, 55.9, -12.8, 48.1, 38.4, 55.8, 40.1, 55.8, 59.9, 48.8, 52.5, 50.6, 47.0, 52.5, 39.2, 55.8, 42.0, 58.6, 40.7, 55.9, 49.3, 54.5, 54.3, 53.9, 59.9, 53.5, 55.8, 75.7, 57.2, 70.1, 58.0, 66.3, 58.6, 62.1, 59.4, 59.1, 48.9, 58.0, 47.5, 59.4, 45.7, 61.4, 44.3, 63.7, 39.8, 43.9, -22.5, 12.1, 45.1, 57.2, 43.5, 57.7, 61.4, 31.8, 50.7, 30.4, 39.6, 4.7, 27.8, 9.2, 40.3, 68.2, -9.0, -3.1, 3.8, -1.7, 12.9, 1.5, 26.7, 1.0, -7.6, 12.6, 45.7, 23.0, -19.2, 29.6, 8.5, 67.3, 6.2, 73.8, -17.5, 12.5, -1.4, 57.2, 37.4, 88.5, 42.0, 13.1, 40.7, 59.5, -6.2, 26.9, 48.1, 96.8, 27.7, 88.4, 18.1, 82.6, 60.9, 97.7, 68.7, 37.3, 47.1, 40.1, 60.3, 37.8, 18.5, 76.0, 27.7, 82.2, 49.0, 93.5, -4.0, 63.2, 62.3, 94.4, 37.4, 93.1, -15.1, 28.6, 53.6, 58.6, 52.5, 60.9, 51.1, 64.1, 49.9, 67.8, 47.1, 72.5, 43.9, 54.8, 42.5, 54.0, 41.2, 53.4, 34.4, 49.3, 5.2, 31.8, 44.9, 55.3, 3.8, 48.4, 42.5, 77.9, 63.3, 89.0, 64.1, 82.5, 53.0, 81.9, 28.3, 65.1, 39.3, 28.2, 34.6, 72.4, 22.2, 26.7, 32.4, 35.1, 15.9, 37.8, 50.7, 88.4, 21.8, 69.6, 30.2, 76.6, 23.6, 56.3, -4.1, 38.9, 13.9, 56.8, -10.4, 43.4, 26.9, 43.9, -18.4, -3.1, -23.4, -4.5, 83.5, 82.4, 97.3, 19.7, 74.1, 45.5, 72.3, 52.1, 80.1, 47.9, 83.3, 51.0, 76.9, 52.9, 80.1, 54.0, 89.4, 63.1, 114.7, 19.3, 93.6, 56.3, 112.5, 48.9, 86.4, 56.8, 85.0, 56.7, 73.3, 49.2, 78.6, 50.6, 81.9, 52.6, 85.5, 56.7, 83.8, 59.1, 84.1, 56.7, 78.6, 54.9, 75.5, 54.3, 71.4, 53.9, 72.3, 75.7, 72.8, 70.2, 72.7, 66.3, 71.9, 62.2, 70.9, 59.1, 78.3, 58.1, 80.0, 59.5, 81.5, 61.7, 82.9, 64.0, 90.3, 44.3, 121.7, 15.2, 80.9, 57.3, 82.3, 58.1, 76.0, 32.2, 83.4, 30.8, 91.7, 6.0, 101.8, 11.0, 85.2, 67.7, 127.1, 0.4, 119.0, 0.5, 112.2, 3.7, 101.5, 2.7, 125.7, 15.3, 87.0, 23.6, 118.1, 31.7, 104.2, 66.5, 100.7, 72.5, 126.4, 15.6, 111.2, 57.6, 83.0, 87.2, 89.8, 14.2, 85.1, 60.1, 122.2, 29.1, 72.3, 95.7, 86.8, 86.2, 93.1, 80.6, 85.7, 40.5, 76.4, 37.8, 96.5, 74.7, 89.9, 80.6, 74.2, 92.6, 106.7, 62.8, 80.3, 91.6, 122.6, 30.5, 75.4, 58.6, 76.8, 60.9, 77.8, 64.1, 78.7, 67.8, 79.7, 72.3, 82.7, 55.3, 84.2, 54.5, 85.6, 53.8, 93.0, 49.8, 116.1, 33.7, 81.0, 55.7, 112.1, 49.3, 82.0, 77.0, 73.7, 81.5, 94.0, 65.0, 91.7, 29.0, 88.5, 71.8, 106.0, 28.1, 96.8, 35.9, 108.3, 39.1, 74.7, 87.9, 97.3, 68.7, 90.4, 75.6, 99.1, 56.7, 118.1, 40.6, 105.1, 56.8, 117.6, 44.7, 99.5, 44.7, 128.5, 0.5, 124.0, -0.4]}, {"rect": [241, 431, 519, 709], "points": [0.35583, 0.00556, 0.06983, 0.0, -0.01079, 0.3597, -0.00844, 0.0, -0.08178, -0.02439, 0.35207, 0.0, -122.14739, -228.08509, -47.13102, 1.0, 66.8, 46.1, 69.0, 32.1, 66.5, 48.9, 66.1, 52.0, 65.6, 53.8, 65.5, 59.1, 65.5, 62.6, 65.5, 66.7, 65.0, 70.9, 64.5, 76.0, 39.1, 83.3, 32.9, 18.5, 59.5, 45.1, 59.5, 52.0, 51.2, 47.9, 45.3, 50.7, 53.1, 52.5, 48.0, 53.8, 34.8, 62.8, 10.7, 17.1, 30.6, 55.8, -13.3, 48.1, 38.3, 55.8, 40.0, 55.8, 59.5, 48.8, 52.1, 50.6, 46.7, 52.4, 39.1, 55.8, 42.0, 58.5, 40.6, 56.1, 49.0, 54.6, 54.0, 53.9, 59.5, 53.5, 55.7, 75.6, 56.9, 70.0, 57.7, 65.9, 58.2, 61.8, 59.0, 58.9, 48.5, 57.7, 47.2, 59.1, 45.6, 61.3, 44.2, 63.6, 39.4, 43.8, -23.0, 12.1, 44.8, 57.1, 43.4, 57.6, 61.2, 32.1, 50.3, 30.4, 39.2, 4.7, 27.3, 9.3, 40.1, 67.8, -9.5, -3.1, 3.5, -1.4, 12.7, 1.8, 26.4, 1.0, -8.0, 12.6, 45.3, 23.1, -19.7, 29.7, 8.1, 67.3, 5.8, 73.8, -18.0, 12.6, -1.9, 57.2, 37.3, 88.4, 41.6, 13.3, 40.6, 59.5, -6.6, 26.9, 48.2, 96.7, 27.4, 88.4, 17.8, 82.8, 61.1, 97.6, 68.5, 37.3, 46.7, 40.1, 59.9, 37.8, 18.2, 76.0, 27.4, 82.3, 49.1, 93.4, -4.3, 63.1, 62.5, 94.0, 37.4, 93.1, -15.7, 28.6, 53.5, 58.5, 52.1, 60.8, 50.8, 64.0, 49.8, 67.6, 47.0, 72.4, 43.7, 54.8, 42.4, 54.2, 41.1, 53.4, 33.9, 49.3, 4.8, 31.8, 44.8, 55.3, 3.4, 48.4, 42.4, 77.9, 63.4, 88.9, 63.9, 82.1, 52.9, 81.6, 27.9, 65.0, 38.8, 28.2, 34.3, 72.3, 21.8, 26.7, 31.9, 35.1, 15.5, 37.8, 50.6, 88.0, 21.4, 69.5, 30.1, 76.5, 23.2, 56.3, -4.7, 38.9, 13.5, 56.7, -10.8, 43.3, 26.4, 43.8, -19.0, -3.1, -23.9, -4.4, 83.7, 82.1, 97.1, 19.5, 73.4, 45.2, 71.9, 52.0, 79.4, 47.8, 82.9, 50.7, 76.5, 52.9, 79.4, 53.9, 89.3, 62.7, 114.3, 19.0, 93.5, 56.0, 112.3, 48.6, 85.9, 56.7, 84.4, 56.3, 72.9, 48.9, 78.0, 50.6, 81.3, 52.5, 84.9, 56.6, 83.4, 59.0, 83.5, 56.3, 78.0, 54.8, 75.1, 54.0, 71.0, 53.8, 72.2, 75.5, 72.4, 70.1, 72.4, 66.0, 71.5, 61.8, 70.5, 58.9, 77.9, 58.1, 79.4, 59.4, 81.1, 61.4, 82.5, 63.7, 90.1, 44.2, 121.2, 14.9, 80.3, 57.2, 81.7, 58.1, 75.8, 32.2, 83.2, 30.8, 91.3, 6.0, 101.4, 10.7, 85.1, 67.4, 126.5, 0.1, 118.6, 0.2, 112.0, 3.4, 101.4, 2.4, 125.1, 15.0, 86.9, 23.6, 117.8, 31.4, 104.2, 66.4, 101.0, 72.4, 126.1, 15.3, 111.2, 57.3, 83.2, 87.1, 89.4, 14.0, 84.5, 60.0, 122.1, 28.8, 72.3, 95.4, 87.0, 86.1, 93.1, 80.3, 85.5, 40.2, 76.0, 37.8, 96.7, 74.4, 89.9, 80.3, 74.2, 92.6, 106.9, 62.7, 80.5, 91.3, 122.4, 30.2, 74.7, 58.5, 76.1, 60.8, 77.4, 64.0, 78.3, 67.7, 79.6, 72.0, 82.2, 55.2, 83.6, 54.4, 85.0, 53.5, 92.9, 49.5, 115.8, 33.3, 80.4, 55.7, 112.0, 48.9, 81.9, 76.9, 73.6, 81.2, 93.9, 64.6, 91.6, 29.0, 88.4, 71.5, 105.6, 27.8, 96.7, 35.6, 108.2, 38.8, 74.6, 87.6, 97.2, 68.4, 90.3, 75.3, 99.0, 56.4, 118.0, 40.2, 105.1, 56.7, 117.6, 44.3, 99.4, 44.4, 128.0, 0.2, 123.5, -0.7]}, {"rect": [241, 431, 519, 709], "points": [0.3559, 0.00471, 0.06788, 0.0, -0.01026, 0.35938, -0.00896, 0.0, -0.07927, -0.02419, 0.35183, 0.0, -122.20416, -227.34813, -45.46689, 1.0, 66.5, 46.1, 68.4, 32.3, 66.2, 48.8, 66.0, 51.7, 65.5, 53.6, 65.1, 59.0, 65.2, 62.3, 65.2, 66.4, 64.7, 70.6, 64.2, 75.7, 38.9, 83.3, 32.6, 18.7, 59.2, 45.1, 59.2, 51.7, 50.9, 47.9, 45.3, 50.7, 53.1, 52.5, 48.0, 53.5, 34.8, 63.0, 10.4, 17.3, 30.3, 56.1, -13.1, 48.6, 38.3, 55.7, 39.8, 56.0, 59.1, 48.5, 51.8, 50.3, 46.7, 52.1, 38.9, 55.7, 41.9, 58.5, 40.7, 56.1, 48.9, 54.4, 53.7, 53.9, 59.2, 53.4, 55.4, 75.2, 56.8, 70.0, 57.4, 65.9, 58.2, 61.7, 58.7, 58.9, 48.5, 57.9, 47.1, 59.3, 45.3, 61.2, 44.0, 63.5, 39.1, 44.0, -22.7, 12.6, 44.8, 57.1, 43.4, 57.6, 60.6, 32.0, 49.7, 30.7, 38.6, 4.9, 27.0, 9.5, 39.9, 67.7, -9.7, -2.6, 3.8, -1.1, 12.9, 2.0, 26.3, 1.2, -8.0, 13.1, 44.9, 23.3, -19.2, 30.1, 8.1, 67.5, 6.1, 74.0, -18.0, 13.1, -1.9, 57.4, 37.0, 88.4, 41.2, 13.5, 40.3, 59.4, -6.6, 27.4, 48.0, 96.7, 27.6, 88.4, 18.0, 82.8, 60.9, 97.6, 67.9, 37.5, 46.4, 40.2, 59.3, 37.9, 18.2, 75.9, 27.3, 82.3, 48.9, 93.1, -4.0, 63.4, 62.2, 94.0, 37.3, 93.3, -15.4, 28.8, 53.2, 58.4, 51.8, 60.7, 50.5, 63.6, 49.5, 67.3, 46.7, 72.3, 43.5, 54.8, 42.1, 53.9, 40.8, 53.4, 33.9, 49.5, 4.6, 32.1, 44.8, 55.2, 3.2, 48.6, 42.4, 77.8, 63.2, 88.9, 63.7, 82.0, 52.7, 81.5, 27.9, 65.2, 38.5, 28.4, 34.2, 72.3, 21.5, 27.0, 31.6, 35.3, 15.4, 38.0, 50.4, 88.0, 21.4, 69.5, 30.0, 76.7, 23.0, 56.5, -4.7, 39.3, 13.3, 56.9, -10.7, 43.6, 26.1, 44.0, -19.0, -2.6, -23.7, -3.9, 83.4, 82.0, 96.8, 19.6, 73.1, 45.2, 71.6, 51.8, 79.3, 47.6, 82.6, 50.7, 76.2, 52.6, 79.3, 53.9, 89.0, 62.6, 114.3, 18.9, 93.2, 56.1, 113.1, 48.7, 85.8, 56.6, 84.4, 56.3, 72.6, 48.8, 77.9, 50.3, 81.2, 52.2, 84.9, 56.4, 83.1, 58.9, 83.5, 56.3, 78.0, 54.5, 74.8, 53.9, 70.7, 53.6, 71.7, 75.2, 72.1, 70.0, 72.0, 65.9, 71.2, 61.8, 70.3, 58.9, 77.6, 58.0, 79.3, 59.4, 80.8, 61.3, 82.2, 63.6, 89.6, 44.2, 121.9, 14.9, 80.2, 57.1, 81.6, 58.0, 75.3, 32.4, 82.6, 30.8, 91.0, 5.9, 101.1, 10.9, 84.6, 67.3, 126.7, 0.0, 118.7, 0.1, 112.1, 3.3, 101.2, 2.3, 125.3, 15.1, 86.4, 23.8, 118.6, 31.4, 104.5, 66.3, 101.5, 72.3, 126.6, 15.2, 111.7, 57.5, 83.0, 87.0, 89.1, 14.1, 84.4, 59.9, 122.4, 28.9, 72.3, 95.4, 87.0, 86.1, 93.4, 80.5, 84.9, 40.4, 75.4, 37.9, 97.0, 74.5, 90.1, 80.5, 74.2, 92.5, 107.5, 62.6, 80.6, 91.2, 122.9, 30.3, 74.4, 58.4, 75.8, 60.7, 77.1, 63.7, 78.0, 67.4, 79.0, 71.9, 82.1, 54.9, 83.5, 54.3, 84.9, 53.5, 92.4, 49.6, 116.0, 33.5, 80.3, 55.4, 112.3, 48.8, 81.6, 76.9, 73.3, 81.1, 93.7, 64.5, 91.3, 28.9, 88.1, 71.4, 105.5, 27.9, 96.4, 35.8, 108.2, 38.7, 74.3, 87.5, 97.2, 68.6, 90.3, 75.5, 99.0, 56.6, 118.3, 40.1, 105.3, 56.6, 118.2, 44.3, 99.1, 44.6, 128.4, 0.4, 123.9, -0.8]}, {"rect": [241, 430, 519, 708], "points": [0.35541, 0.00447, 0.06677, 0.0, -0.00978, 0.35938, -0.009, 0.0, -0.07806, -0.02322, 0.35157, 0.0, -122.04538, -226.90111, -44.63833, 1.0, 66.5, 46.5, 68.3, 32.3, 66.4, 49.3, 66.0, 52.4, 65.6, 54.2, 65.1, 59.3, 65.4, 62.7, 65.4, 66.8, 65.0, 71.0, 64.4, 76.3, 39.1, 83.5, 33.0, 18.9, 59.2, 45.5, 59.5, 52.4, 51.2, 48.3, 45.6, 51.1, 53.1, 52.9, 48.0, 54.0, 35.2, 63.4, 10.9, 17.6, 31.1, 56.5, -12.2, 48.8, 38.6, 56.2, 40.1, 56.2, 59.2, 49.2, 52.1, 50.7, 46.9, 52.6, 39.2, 56.2, 42.0, 58.9, 40.9, 56.3, 49.0, 54.8, 53.9, 54.3, 59.5, 53.9, 55.7, 75.9, 57.1, 70.4, 57.6, 66.3, 58.5, 62.1, 59.0, 59.0, 48.8, 58.1, 47.4, 59.5, 45.6, 61.6, 44.2, 63.9, 39.8, 44.3, -21.9, 12.9, 45.1, 57.5, 43.7, 58.0, 60.8, 31.9, 50.2, 30.9, 39.0, 5.1, 27.5, 9.7, 40.3, 68.2, -9.0, -2.3, 4.1, -0.9, 13.0, 2.3, 26.4, 1.4, -7.5, 13.4, 45.1, 23.5, -18.6, 30.4, 8.9, 67.7, 6.7, 74.2, -17.3, 13.4, -1.2, 57.6, 37.3, 88.9, 41.5, 13.5, 40.8, 59.9, -6.1, 27.7, 48.0, 96.9, 27.7, 88.6, 18.4, 83.0, 60.9, 97.8, 67.9, 37.4, 46.8, 40.2, 59.5, 37.9, 18.7, 76.2, 27.6, 82.5, 48.9, 93.5, -3.4, 63.6, 62.3, 94.4, 37.4, 93.6, -14.6, 29.1, 53.5, 58.6, 52.1, 60.9, 51.0, 64.0, 49.8, 67.7, 47.0, 72.7, 43.8, 55.2, 42.4, 54.4, 41.4, 53.8, 34.3, 49.8, 5.3, 32.3, 45.1, 55.7, 3.9, 48.9, 42.4, 78.2, 63.2, 89.3, 63.7, 82.4, 53.0, 82.0, 28.3, 65.4, 38.7, 28.6, 34.5, 72.7, 21.9, 27.2, 32.1, 35.5, 15.9, 38.3, 50.6, 88.4, 21.9, 69.7, 30.3, 76.9, 23.7, 56.7, -3.9, 39.6, 14.0, 57.1, -9.9, 43.8, 26.6, 44.3, -18.5, -2.3, -22.9, -3.6, 83.5, 82.4, 96.8, 19.8, 73.3, 45.6, 71.9, 52.4, 79.3, 48.2, 82.6, 51.1, 76.2, 53.0, 79.4, 54.3, 89.0, 63.1, 114.3, 19.3, 93.5, 56.6, 113.3, 49.2, 85.8, 57.1, 84.3, 56.9, 72.8, 49.3, 77.9, 50.7, 81.2, 52.9, 84.9, 57.0, 83.1, 59.4, 83.5, 56.9, 78.0, 55.2, 74.8, 54.3, 70.9, 54.2, 71.9, 75.8, 72.3, 70.4, 72.0, 66.3, 71.4, 62.2, 70.5, 59.0, 77.8, 58.4, 79.4, 59.8, 80.8, 61.7, 82.2, 64.0, 89.8, 44.6, 122.3, 15.5, 80.2, 57.5, 81.7, 58.4, 75.2, 32.4, 82.6, 30.9, 91.2, 6.1, 101.3, 11.1, 84.8, 68.0, 126.7, 0.4, 118.5, 0.7, 111.7, 3.7, 101.0, 2.7, 125.4, 15.5, 86.3, 24.0, 118.7, 31.8, 104.6, 66.7, 101.5, 72.8, 126.7, 15.6, 111.6, 57.9, 83.0, 87.4, 89.3, 14.3, 84.4, 60.6, 122.2, 29.4, 72.4, 95.8, 87.1, 86.5, 93.5, 81.0, 84.9, 40.5, 75.6, 37.9, 96.9, 75.0, 90.0, 81.0, 74.2, 92.7, 107.4, 63.0, 80.6, 91.6, 123.0, 30.8, 74.7, 58.8, 76.0, 61.1, 77.4, 64.3, 78.0, 68.0, 79.3, 72.3, 82.1, 55.6, 83.5, 54.8, 84.9, 54.1, 92.6, 50.1, 115.8, 33.6, 80.6, 56.0, 112.4, 49.2, 81.6, 77.3, 73.3, 81.5, 94.0, 64.9, 91.3, 29.1, 88.1, 71.8, 105.5, 28.1, 96.4, 35.9, 108.0, 39.1, 74.6, 87.9, 97.2, 69.0, 90.3, 75.9, 99.1, 57.0, 118.4, 40.5, 105.2, 57.1, 118.3, 44.7, 99.1, 45.1, 128.5, 0.8, 124.3, -0.2]}, {"rect": [241, 430, 519, 708], "points": [0.35549, 0.0039, 0.06647, 0.0, -0.00935, 0.35949, -0.00922, 0.0, -0.07776, -0.02264, 0.35208, 0.0, -122.2702, -226.58175, -44.35107, 1.0, 66.9, 46.5, 68.4, 31.9, 66.6, 49.2, 66.4, 52.4, 66.0, 53.9, 65.5, 59.1, 65.6, 62.6, 65.6, 66.8, 65.2, 71.0, 64.3, 76.1, 39.0, 83.5, 32.9, 18.9, 59.6, 45.5, 59.6, 52.4, 51.3, 48.3, 45.8, 51.1, 53.5, 52.9, 48.4, 54.2, 35.2, 63.2, 10.8, 17.6, 31.0, 56.3, -12.1, 48.9, 38.8, 56.2, 40.3, 56.2, 59.5, 49.2, 52.3, 50.7, 47.1, 52.8, 39.4, 56.2, 42.2, 58.9, 41.1, 56.2, 49.3, 54.8, 54.1, 54.3, 59.6, 53.9, 55.6, 75.9, 57.3, 70.4, 57.8, 66.3, 58.6, 61.9, 59.2, 59.0, 48.9, 58.0, 47.6, 59.4, 45.8, 61.4, 44.4, 63.7, 39.8, 44.2, -21.7, 13.0, 45.2, 57.2, 43.9, 58.0, 60.9, 31.9, 50.3, 30.8, 38.9, 5.1, 27.4, 9.7, 40.3, 68.2, -9.1, -2.2, 4.2, -0.8, 13.4, 2.1, 26.7, 1.4, -7.4, 13.4, 45.3, 23.2, -18.4, 30.5, 8.9, 67.7, 6.6, 74.3, -17.1, 13.4, -1.0, 57.7, 37.4, 88.9, 41.6, 13.4, 40.8, 59.9, -5.9, 27.7, 48.2, 97.1, 27.8, 88.8, 18.5, 83.0, 61.1, 98.0, 68.0, 37.3, 46.8, 40.1, 59.6, 37.8, 18.6, 76.4, 27.7, 82.6, 49.0, 93.5, -3.3, 63.7, 62.4, 94.4, 37.5, 93.6, -14.7, 29.1, 53.6, 58.5, 52.3, 60.8, 51.2, 64.0, 50.0, 67.7, 47.1, 72.7, 44.0, 55.2, 42.6, 54.3, 41.5, 53.8, 34.3, 49.8, 5.2, 32.3, 45.2, 55.7, 4.1, 48.8, 42.5, 77.9, 63.3, 89.3, 63.8, 82.4, 53.1, 82.0, 28.3, 65.4, 38.8, 28.6, 34.7, 72.8, 21.8, 26.9, 32.0, 35.5, 15.8, 38.3, 50.5, 88.4, 21.8, 69.9, 30.2, 76.9, 23.6, 56.7, -3.8, 39.6, 13.9, 57.1, -9.8, 43.9, 26.8, 44.2, -18.4, -2.2, -22.7, -3.5, 83.6, 82.4, 97.0, 19.7, 73.4, 45.5, 72.0, 52.4, 79.5, 47.9, 83.0, 51.1, 76.5, 52.9, 79.7, 54.3, 89.1, 63.0, 114.4, 19.2, 93.6, 56.5, 113.7, 49.1, 86.2, 57.0, 84.4, 56.7, 73.0, 49.2, 78.0, 50.7, 81.6, 52.8, 85.3, 57.0, 83.4, 59.3, 83.8, 56.7, 78.4, 55.1, 75.1, 54.3, 71.1, 53.9, 72.0, 75.6, 72.5, 70.4, 72.4, 66.3, 71.6, 62.1, 70.7, 59.0, 78.0, 58.1, 79.7, 59.5, 81.1, 61.7, 82.5, 64.0, 89.9, 44.3, 122.5, 15.4, 80.3, 57.5, 82.0, 58.4, 75.3, 32.3, 82.7, 30.9, 91.4, 6.0, 101.5, 11.0, 85.0, 67.7, 127.1, 0.3, 118.6, 0.4, 111.7, 3.6, 101.1, 2.7, 125.7, 15.5, 86.7, 23.9, 118.9, 31.9, 104.7, 66.7, 101.9, 72.9, 127.1, 15.5, 112.0, 57.8, 83.2, 87.4, 89.5, 14.2, 84.8, 60.4, 122.6, 29.3, 72.6, 95.8, 87.3, 86.5, 93.7, 80.9, 85.0, 40.5, 75.7, 37.8, 97.3, 74.9, 90.4, 80.9, 74.4, 92.9, 107.9, 63.0, 80.8, 91.6, 123.4, 30.7, 74.8, 58.6, 76.2, 60.9, 77.5, 64.1, 78.4, 67.7, 79.4, 72.2, 82.2, 55.3, 83.9, 54.7, 85.3, 53.9, 92.7, 49.8, 116.1, 33.5, 80.7, 55.8, 112.6, 49.2, 81.8, 77.3, 73.5, 81.4, 94.1, 64.9, 91.4, 29.0, 88.5, 71.8, 105.7, 28.0, 96.5, 35.8, 108.3, 39.0, 74.8, 87.9, 97.4, 69.0, 90.5, 75.9, 99.3, 57.0, 118.6, 40.7, 105.6, 57.0, 118.5, 44.8, 99.3, 45.0, 128.9, 0.7, 124.7, -0.2]}, {"rect": [242, 430, 520, 708], "points": [0.35595, 0.00282, 0.06696, 0.0, -0.00874, 0.3597, -0.00869, 0.0, -0.07857, -0.02239, 0.35282, 0.0, -123.04617, -226.19207, -45.06788, 1.0, 67.0, 46.5, 68.7, 31.9, 66.8, 49.2, 66.5, 52.1, 66.0, 53.9, 65.6, 59.3, 65.9, 62.6, 65.6, 66.8, 65.4, 71.2, 64.5, 76.1, 39.2, 83.8, 33.1, 18.9, 59.9, 45.3, 59.9, 52.1, 51.6, 48.3, 46.0, 51.1, 53.5, 52.9, 48.4, 54.0, 35.1, 63.2, 10.7, 17.8, 30.9, 56.3, -12.4, 49.2, 38.8, 56.2, 40.5, 56.2, 59.6, 48.9, 52.5, 50.6, 47.1, 52.6, 39.6, 56.2, 42.4, 58.7, 41.1, 56.2, 49.3, 54.8, 54.3, 54.3, 59.9, 53.9, 55.8, 75.7, 57.3, 70.5, 58.0, 66.3, 58.7, 62.1, 59.4, 58.9, 48.9, 58.0, 47.5, 59.4, 46.0, 61.3, 44.4, 63.7, 39.7, 44.2, -22.1, 13.3, 45.2, 57.1, 43.8, 58.0, 60.9, 31.8, 50.3, 30.8, 39.1, 5.1, 27.6, 9.7, 40.2, 68.2, -9.2, -2.0, 4.1, -0.6, 13.3, 2.3, 26.7, 1.4, -7.7, 13.7, 45.2, 23.4, -18.5, 30.8, 8.8, 67.8, 6.5, 74.6, -17.4, 13.7, -1.3, 58.0, 37.4, 88.9, 41.5, 13.4, 41.0, 59.9, -6.0, 28.0, 48.4, 97.2, 27.7, 88.9, 18.5, 83.3, 61.3, 98.1, 68.2, 37.3, 47.0, 40.1, 59.9, 37.8, 18.5, 76.5, 27.7, 82.8, 49.0, 93.5, -3.6, 64.0, 62.4, 94.4, 37.4, 93.9, -14.8, 29.4, 53.9, 58.5, 52.5, 60.8, 51.2, 64.0, 50.2, 67.7, 47.1, 72.8, 44.2, 55.0, 42.8, 54.3, 41.5, 53.6, 34.3, 49.7, 5.1, 32.6, 45.2, 55.4, 3.8, 48.9, 42.5, 78.0, 63.3, 89.3, 64.1, 82.4, 53.1, 82.0, 28.2, 65.4, 38.8, 28.6, 34.6, 72.8, 21.8, 27.1, 31.9, 35.5, 15.8, 38.3, 50.7, 88.4, 21.8, 70.0, 30.1, 77.0, 23.6, 56.7, -4.0, 39.7, 13.9, 57.1, -10.1, 44.2, 26.8, 44.3, -18.5, -2.0, -23.0, -3.0, 83.9, 82.1, 97.2, 19.4, 73.7, 45.5, 72.0, 52.1, 79.7, 47.9, 83.0, 51.0, 76.5, 52.9, 79.8, 54.2, 89.4, 62.8, 114.6, 18.9, 93.6, 56.3, 113.7, 48.6, 86.2, 56.7, 84.4, 56.6, 73.2, 49.2, 78.1, 50.6, 81.6, 52.6, 85.3, 56.7, 83.4, 59.0, 83.6, 56.6, 78.4, 54.9, 75.2, 54.3, 71.1, 53.9, 72.0, 75.6, 72.8, 70.4, 72.5, 66.3, 71.9, 62.1, 71.0, 58.9, 78.0, 58.0, 79.8, 59.4, 81.1, 61.7, 82.5, 64.0, 89.9, 44.2, 122.4, 14.9, 80.4, 57.2, 82.1, 58.1, 75.6, 32.2, 82.9, 30.8, 91.6, 5.9, 101.7, 10.7, 85.2, 67.7, 127.1, -0.0, 118.8, 0.1, 111.9, 3.3, 101.0, 2.4, 125.7, 14.9, 86.7, 23.6, 119.1, 31.4, 105.0, 66.4, 102.1, 72.4, 127.1, 15.2, 112.3, 57.3, 83.4, 87.2, 89.4, 13.9, 84.8, 60.3, 122.5, 28.7, 72.8, 95.8, 87.5, 86.2, 94.0, 80.7, 85.2, 40.2, 75.7, 37.8, 97.5, 74.7, 90.6, 80.7, 74.6, 92.7, 108.1, 62.7, 81.0, 91.6, 123.4, 30.2, 75.1, 58.5, 76.5, 60.8, 77.6, 64.0, 78.4, 67.7, 79.4, 72.0, 82.2, 55.3, 83.9, 54.7, 85.3, 53.8, 92.7, 49.8, 116.1, 33.2, 80.7, 55.7, 112.8, 48.9, 82.0, 77.0, 73.7, 81.2, 94.4, 64.6, 91.7, 29.0, 88.5, 71.6, 105.9, 27.7, 96.7, 35.6, 108.4, 38.8, 74.8, 87.7, 97.7, 68.7, 90.8, 75.6, 99.5, 56.7, 118.8, 40.2, 105.8, 56.7, 118.7, 44.3, 99.5, 44.7, 128.9, 0.1, 124.6, -0.8]}, {"rect": [244, 430, 522, 708], "points": [0.35638, 0.00214, 0.06821, 0.0, -0.00792, 0.36048, -0.00918, 0.0, -0.08025, -0.0219, 0.35357, 0.0, -124.30153, -226.39339, -45.63138, 1.0, 66.9, 46.2, 68.3, 31.8, 66.6, 49.0, 66.4, 52.1, 65.9, 53.9, 65.5, 59.0, 65.6, 62.6, 65.5, 66.8, 65.1, 71.0, 64.2, 76.4, 38.8, 83.8, 32.4, 18.9, 59.5, 45.3, 59.6, 52.1, 51.3, 48.3, 45.7, 51.1, 53.1, 52.9, 48.1, 54.0, 34.8, 63.5, 10.2, 17.6, 30.5, 56.3, -12.9, 49.0, 38.3, 56.2, 40.1, 56.2, 59.5, 48.9, 52.2, 50.7, 46.7, 52.6, 39.2, 56.2, 42.0, 58.9, 40.7, 56.2, 49.0, 54.8, 54.0, 54.1, 59.6, 53.9, 55.4, 76.0, 57.2, 70.5, 57.7, 66.3, 58.6, 62.1, 59.1, 58.9, 48.6, 58.0, 47.2, 59.5, 45.7, 61.6, 44.3, 63.9, 39.4, 44.2, -22.6, 13.3, 44.8, 57.2, 43.5, 58.0, 60.6, 31.8, 49.9, 30.6, 38.4, 5.1, 26.9, 9.7, 39.8, 68.5, -10.0, -2.2, 3.4, -0.8, 12.6, 2.3, 26.0, 1.4, -8.2, 13.5, 44.9, 23.1, -19.3, 30.9, 8.3, 67.9, 6.0, 74.7, -18.0, 13.5, -1.8, 58.1, 37.0, 89.0, 41.1, 13.4, 40.7, 59.9, -6.5, 27.8, 48.0, 97.2, 27.3, 89.0, 18.0, 83.4, 61.0, 98.2, 67.9, 37.0, 46.6, 40.1, 59.6, 37.7, 18.1, 76.6, 27.3, 82.9, 48.9, 93.6, -4.1, 64.1, 62.3, 94.5, 37.0, 94.0, -15.5, 29.5, 53.5, 58.5, 52.2, 60.8, 50.9, 64.1, 49.9, 67.7, 46.7, 72.8, 43.8, 55.2, 42.5, 54.4, 41.1, 53.8, 34.1, 49.7, 4.6, 32.4, 44.8, 55.7, 3.3, 48.9, 42.1, 78.2, 63.2, 89.3, 63.8, 82.5, 52.7, 82.1, 27.8, 65.5, 38.4, 28.5, 34.2, 72.8, 21.3, 27.1, 31.5, 35.5, 15.3, 38.3, 50.4, 88.5, 21.3, 70.1, 30.0, 77.0, 23.2, 56.7, -4.5, 39.7, 13.4, 57.2, -10.6, 44.3, 26.4, 44.3, -19.3, -2.2, -23.9, -3.1, 83.5, 82.4, 96.9, 19.3, 73.4, 45.2, 71.9, 52.1, 79.4, 47.9, 82.7, 50.7, 76.2, 52.6, 79.4, 54.0, 89.0, 63.0, 114.1, 18.5, 93.3, 56.2, 112.8, 48.7, 85.9, 56.7, 84.1, 56.6, 72.9, 48.9, 78.0, 50.6, 81.3, 52.5, 85.0, 56.7, 83.1, 59.0, 83.5, 56.6, 78.1, 54.8, 74.8, 54.0, 71.0, 53.9, 72.0, 75.9, 72.5, 70.5, 72.4, 66.3, 71.6, 61.8, 70.6, 58.9, 77.9, 58.0, 79.4, 59.4, 80.8, 61.6, 82.2, 64.0, 89.6, 44.2, 121.6, 14.8, 80.3, 57.1, 81.7, 58.1, 75.2, 31.9, 82.6, 30.5, 91.0, 5.6, 101.2, 10.6, 84.9, 67.7, 126.5, -0.4, 118.1, 0.0, 111.5, 3.2, 100.8, 2.3, 125.2, 14.8, 86.3, 23.5, 118.2, 31.3, 104.4, 66.3, 101.5, 72.4, 126.4, 15.1, 111.7, 57.2, 83.1, 87.2, 89.1, 13.8, 84.5, 60.3, 121.9, 28.6, 72.5, 95.9, 87.2, 86.2, 93.6, 80.6, 84.9, 40.1, 75.6, 37.7, 97.0, 74.6, 90.1, 80.6, 74.3, 92.7, 107.3, 62.7, 80.4, 91.6, 122.8, 30.3, 74.8, 58.5, 76.2, 60.8, 77.5, 64.0, 78.1, 67.7, 79.3, 72.3, 82.0, 55.3, 83.6, 54.4, 85.0, 53.5, 92.4, 49.7, 115.8, 33.2, 80.4, 55.7, 112.2, 48.8, 81.7, 77.0, 73.4, 81.5, 93.8, 64.8, 91.3, 28.7, 88.2, 71.8, 105.3, 27.6, 96.4, 35.5, 108.0, 38.7, 74.7, 87.9, 97.3, 68.6, 90.4, 75.6, 99.2, 56.6, 118.2, 40.1, 105.3, 56.7, 118.1, 44.2, 99.2, 44.7, 128.0, -0.0, 123.4, -0.9]}, {"rect": [245, 430, 523, 708], "points": [0.35749, 0.00112, 0.06955, 0.0, -0.0071, 0.36135, -0.00894, 0.0, -0.08172, -0.02169, 0.35491, 0.0, -125.57094, -226.52992, -46.75067, 1.0, 67.5, 46.4, 69.0, 32.0, 67.4, 49.2, 67.0, 52.0, 66.6, 53.9, 66.1, 59.1, 66.2, 62.7, 66.2, 66.9, 65.8, 71.0, 64.9, 76.4, 39.1, 84.2, 32.7, 18.9, 60.1, 45.5, 60.1, 52.0, 51.8, 48.3, 46.0, 51.2, 53.7, 52.9, 48.7, 54.3, 35.3, 63.5, 10.5, 17.9, 30.8, 56.6, -13.2, 49.6, 38.7, 56.3, 40.2, 56.3, 60.1, 49.1, 52.8, 50.7, 47.3, 52.9, 39.6, 56.3, 42.4, 59.0, 41.0, 56.3, 49.3, 54.8, 54.3, 54.3, 60.2, 53.9, 56.0, 76.1, 57.6, 70.6, 58.3, 66.4, 59.2, 62.2, 59.7, 59.0, 49.1, 58.1, 47.8, 59.5, 46.1, 61.4, 44.7, 64.0, 39.9, 44.2, -23.0, 13.4, 45.2, 57.2, 43.8, 58.1, 61.2, 32.0, 50.5, 30.8, 38.7, 5.1, 27.1, 9.7, 40.4, 68.6, -10.1, -1.9, 3.6, -0.6, 12.8, 2.6, 26.2, 1.4, -8.3, 13.8, 45.4, 23.3, -19.6, 31.2, 8.3, 68.4, 6.0, 75.1, -18.3, 13.8, -1.8, 58.4, 37.3, 89.3, 41.4, 13.4, 41.0, 60.0, -6.8, 28.0, 48.4, 97.6, 27.6, 89.3, 18.0, 83.8, 61.6, 98.5, 68.5, 37.2, 47.0, 40.4, 60.2, 37.7, 18.4, 76.9, 27.6, 83.3, 49.3, 93.9, -4.1, 64.4, 62.9, 94.8, 37.3, 94.3, -15.6, 29.8, 53.9, 58.6, 52.8, 60.9, 51.5, 64.1, 50.5, 67.8, 47.3, 72.9, 44.2, 55.3, 42.8, 54.5, 41.5, 53.9, 34.4, 49.7, 4.6, 32.6, 45.2, 55.7, 3.3, 49.2, 42.7, 78.3, 63.9, 89.4, 64.4, 82.5, 53.3, 82.4, 28.1, 65.8, 38.7, 28.5, 34.5, 73.1, 21.6, 27.2, 31.8, 35.5, 15.6, 38.6, 51.0, 88.8, 21.6, 70.4, 30.3, 77.4, 23.4, 57.0, -4.5, 40.0, 13.5, 57.5, -10.9, 44.6, 26.7, 44.6, -19.4, -1.9, -24.3, -2.9, 84.2, 82.4, 97.5, 19.2, 73.9, 45.2, 72.6, 52.0, 80.0, 47.8, 83.3, 50.7, 76.8, 52.8, 80.1, 53.9, 89.7, 63.0, 114.9, 18.4, 93.9, 56.2, 113.5, 48.4, 86.5, 56.6, 84.7, 56.4, 73.5, 49.1, 78.6, 50.6, 81.9, 52.5, 85.6, 56.6, 83.8, 59.0, 83.9, 56.3, 78.7, 54.8, 75.5, 54.2, 71.6, 53.9, 72.6, 75.7, 73.1, 70.5, 73.0, 66.0, 72.2, 61.8, 71.3, 59.0, 78.6, 57.8, 80.1, 59.4, 81.5, 61.4, 82.8, 63.8, 90.2, 44.1, 122.3, 14.7, 80.9, 57.1, 82.4, 58.1, 75.8, 32.0, 83.2, 30.7, 91.5, 5.5, 102.0, 10.5, 85.5, 67.7, 127.3, -0.5, 118.7, -0.1, 111.8, 3.1, 101.2, 2.2, 126.0, 14.7, 86.9, 23.5, 118.7, 31.0, 105.3, 66.3, 102.1, 72.3, 127.0, 14.7, 112.3, 57.1, 83.7, 87.4, 89.7, 13.8, 85.1, 60.0, 122.8, 28.5, 73.1, 96.2, 87.8, 86.2, 94.3, 80.6, 85.6, 40.3, 76.3, 37.7, 97.6, 74.6, 90.7, 80.6, 74.9, 93.0, 108.1, 62.6, 81.0, 91.7, 123.3, 30.0, 75.4, 58.5, 76.8, 60.8, 78.2, 64.0, 79.0, 67.8, 79.7, 72.3, 82.4, 55.3, 84.2, 54.4, 85.6, 53.5, 93.2, 49.6, 116.4, 33.1, 81.0, 55.7, 113.1, 48.8, 82.4, 77.3, 74.1, 81.5, 94.7, 64.8, 91.9, 28.8, 88.8, 71.8, 106.2, 27.5, 97.0, 35.4, 108.9, 38.6, 75.1, 88.0, 98.0, 68.6, 91.1, 75.5, 99.8, 56.6, 119.1, 40.0, 105.9, 56.6, 118.7, 44.1, 99.8, 44.6, 128.7, -0.4, 124.1, -1.3]}, {"rect": [247, 431, 525, 709], "points": [0.3582, 0.00018, 0.07061, 0.0, -0.006, 0.36224, -0.00918, 0.0, -0.08299, -0.02118, 0.35584, 0.0, -127.06234, -226.85723, -47.3748, 1.0, 67.1, 46.0, 68.9, 31.3, 67.1, 48.7, 66.7, 51.6, 66.2, 53.4, 65.8, 58.9, 66.2, 62.3, 66.2, 66.7, 65.8, 70.9, 64.9, 76.1, 39.1, 83.8, 32.6, 18.4, 59.8, 45.0, 59.8, 51.6, 51.5, 47.9, 45.7, 51.0, 53.5, 52.5, 48.4, 53.8, 35.0, 63.2, 10.1, 17.5, 30.5, 56.2, -13.7, 49.2, 38.4, 56.2, 40.2, 56.2, 59.8, 48.4, 52.5, 50.3, 47.0, 52.4, 39.3, 56.2, 42.4, 58.6, 41.0, 56.2, 49.3, 54.4, 54.2, 53.8, 59.9, 53.4, 55.8, 76.0, 57.5, 70.4, 58.1, 66.3, 59.0, 61.8, 59.4, 58.6, 48.9, 57.7, 47.6, 59.4, 46.0, 61.3, 44.6, 63.7, 39.6, 43.7, -23.7, 13.0, 45.1, 57.1, 43.8, 57.7, 61.1, 31.3, 50.2, 30.3, 38.6, 4.6, 26.7, 9.2, 40.1, 68.2, -10.6, -2.3, 2.9, -1.3, 12.1, 1.9, 25.8, 0.9, -8.7, 13.4, 45.1, 22.6, -20.1, 30.6, 7.9, 68.1, 5.6, 75.0, -18.8, 13.4, -2.2, 58.1, 37.3, 89.2, 41.3, 12.9, 41.0, 59.9, -7.2, 27.6, 48.3, 97.2, 27.5, 89.2, 17.9, 83.7, 61.6, 98.1, 68.5, 36.7, 46.9, 39.9, 59.9, 37.2, 18.0, 76.8, 27.2, 82.9, 49.2, 93.8, -4.5, 64.1, 62.7, 94.5, 37.3, 94.0, -16.1, 29.5, 53.9, 58.4, 52.5, 60.8, 51.2, 64.0, 50.3, 67.7, 47.0, 72.8, 43.9, 54.9, 42.5, 54.3, 41.4, 53.5, 34.1, 49.3, 4.2, 32.2, 45.1, 55.3, 2.9, 48.8, 42.4, 78.2, 63.9, 89.0, 64.4, 82.4, 53.3, 82.0, 28.0, 65.4, 38.5, 28.1, 34.4, 72.8, 21.2, 26.7, 31.7, 35.0, 15.3, 38.2, 50.7, 88.5, 21.2, 70.0, 30.0, 77.3, 23.1, 56.6, -5.0, 39.6, 13.3, 57.1, -11.4, 44.2, 26.3, 44.2, -20.1, -2.3, -24.8, -3.5, 84.2, 81.9, 97.2, 18.5, 73.6, 44.7, 72.3, 51.6, 79.9, 47.1, 83.3, 50.2, 76.8, 52.1, 80.1, 53.4, 89.5, 62.3, 114.7, 17.9, 93.9, 55.7, 113.0, 47.9, 86.5, 56.2, 84.7, 56.1, 73.2, 48.4, 78.6, 49.8, 81.9, 52.0, 85.6, 56.2, 83.8, 58.6, 84.1, 55.8, 78.7, 54.3, 75.4, 53.5, 71.4, 53.4, 72.4, 75.6, 73.1, 70.1, 72.8, 65.8, 72.2, 61.7, 71.2, 58.6, 78.3, 57.5, 80.1, 59.0, 81.5, 61.2, 82.8, 63.6, 90.2, 43.4, 121.8, 13.8, 80.9, 56.7, 82.4, 57.6, 75.6, 31.3, 83.2, 29.9, 91.2, 5.0, 101.5, 9.6, 85.3, 67.3, 126.8, -1.3, 118.3, -1.0, 111.5, 2.3, 100.8, 1.4, 125.7, 13.8, 86.9, 22.9, 118.2, 30.4, 105.0, 65.8, 101.9, 71.8, 126.7, 13.9, 112.0, 56.6, 83.8, 87.0, 89.4, 13.2, 85.1, 59.8, 122.5, 27.6, 72.8, 95.8, 87.6, 86.0, 94.0, 80.1, 85.6, 39.5, 76.0, 37.2, 97.3, 74.1, 90.7, 80.1, 74.7, 92.6, 107.8, 62.1, 81.0, 91.3, 123.1, 29.4, 75.4, 58.1, 76.8, 60.4, 78.1, 63.6, 78.7, 67.6, 79.7, 71.9, 82.4, 54.8, 84.2, 53.9, 85.6, 53.0, 93.0, 48.9, 116.2, 32.3, 81.0, 55.2, 112.8, 48.2, 82.4, 76.9, 74.1, 81.1, 94.4, 64.1, 91.7, 28.0, 88.8, 71.3, 105.9, 26.7, 96.8, 34.9, 108.7, 37.8, 75.1, 87.6, 97.8, 68.1, 90.9, 75.1, 99.5, 55.8, 118.8, 39.2, 105.9, 56.1, 118.4, 43.3, 99.5, 43.8, 128.2, -0.9, 123.3, -1.9]}, {"rect": [249, 431, 527, 709], "points": [0.35942, -0.00078, 0.07064, 0.0, -0.00501, 0.36317, -0.00965, 0.0, -0.08297, -0.01983, 0.35738, 0.0, -128.47723, -226.86845, -47.0573, 1.0, 66.7, 45.9, 68.6, 30.9, 66.7, 48.7, 66.4, 51.5, 65.9, 53.3, 65.7, 59.0, 65.9, 62.6, 65.9, 66.9, 65.8, 71.0, 64.8, 76.4, 38.8, 83.9, 32.2, 18.4, 59.4, 45.0, 59.5, 51.6, 51.2, 47.9, 45.6, 51.1, 53.4, 52.5, 48.3, 53.8, 34.9, 63.5, 9.7, 17.5, 30.7, 56.3, -13.8, 49.3, 38.6, 56.5, 40.4, 56.5, 59.4, 48.6, 52.4, 50.5, 46.9, 52.5, 39.5, 56.5, 42.3, 59.2, 41.0, 56.5, 49.2, 54.7, 53.9, 53.8, 59.8, 53.4, 55.7, 76.4, 57.5, 70.5, 58.0, 66.4, 58.9, 62.1, 59.4, 59.0, 48.8, 58.3, 47.8, 59.7, 46.0, 61.7, 44.6, 64.0, 39.5, 43.8, -24.0, 13.3, 45.1, 57.5, 44.0, 58.3, 60.8, 30.9, 50.1, 30.0, 38.1, 4.6, 26.3, 9.2, 40.1, 68.6, -11.1, -2.2, 2.4, -1.2, 11.6, 1.9, 25.4, 0.9, -9.2, 13.4, 44.7, 22.6, -20.3, 30.9, 7.8, 68.2, 5.5, 75.1, -19.3, 13.5, -2.3, 58.4, 37.2, 89.4, 40.9, 12.9, 40.9, 60.2, -7.4, 27.7, 48.3, 97.6, 27.2, 89.4, 17.5, 83.9, 61.3, 98.5, 68.2, 36.3, 46.5, 39.7, 59.8, 36.9, 17.9, 76.9, 27.1, 83.3, 49.2, 94.0, -4.6, 64.4, 62.7, 94.8, 37.2, 94.4, -16.6, 29.5, 53.8, 58.6, 52.5, 61.1, 51.4, 64.4, 50.5, 68.1, 47.0, 73.1, 44.1, 55.2, 42.7, 54.6, 41.4, 53.8, 34.0, 49.4, 4.1, 32.3, 45.1, 55.6, 2.7, 48.9, 42.3, 78.4, 63.6, 89.3, 64.4, 82.5, 53.0, 82.4, 27.7, 65.8, 38.2, 28.1, 34.1, 72.9, 21.1, 26.7, 31.3, 35.0, 15.1, 38.2, 50.7, 88.8, 21.1, 70.1, 29.9, 77.4, 22.9, 56.7, -5.1, 39.7, 13.0, 57.5, -11.6, 44.3, 26.2, 44.2, -20.4, -2.2, -25.3, -3.2, 84.3, 82.0, 97.1, 18.3, 73.3, 44.6, 72.2, 51.5, 79.6, 47.0, 83.2, 50.1, 76.7, 52.0, 80.0, 53.4, 89.7, 62.5, 114.6, 17.5, 93.9, 55.7, 113.3, 47.8, 86.5, 56.2, 84.9, 56.1, 73.1, 48.3, 78.3, 49.8, 81.8, 52.0, 85.6, 56.1, 83.7, 58.8, 84.1, 56.1, 78.6, 54.3, 75.4, 53.4, 71.3, 53.3, 72.6, 75.9, 72.8, 70.4, 72.7, 65.9, 71.9, 61.8, 70.9, 58.9, 78.3, 57.6, 80.0, 59.3, 81.4, 61.3, 82.8, 63.9, 90.2, 43.3, 121.9, 13.7, 80.9, 57.0, 82.4, 57.9, 75.5, 30.9, 82.9, 29.8, 91.1, 4.6, 101.6, 9.3, 85.5, 67.6, 126.9, -1.5, 118.0, -1.4, 111.5, 2.2, 100.5, 1.3, 125.7, 13.7, 86.6, 22.6, 118.4, 30.2, 105.1, 65.7, 101.9, 71.8, 126.7, 13.7, 112.0, 56.5, 83.8, 87.0, 89.3, 12.9, 85.1, 59.8, 122.5, 27.5, 72.8, 96.2, 87.9, 86.0, 94.1, 80.1, 85.6, 39.2, 76.0, 36.9, 97.6, 74.1, 90.7, 80.1, 75.0, 92.9, 107.8, 62.0, 81.1, 91.6, 123.3, 29.3, 75.1, 58.4, 76.7, 60.7, 77.8, 63.9, 78.7, 67.7, 79.9, 72.2, 82.4, 54.7, 84.2, 53.9, 85.6, 52.9, 93.0, 48.8, 116.4, 32.1, 81.0, 55.2, 112.8, 47.9, 82.4, 76.9, 74.1, 81.4, 94.4, 64.3, 91.6, 27.7, 88.9, 71.3, 105.8, 26.6, 96.7, 34.6, 108.6, 37.7, 75.1, 87.9, 98.0, 68.1, 91.1, 75.1, 99.5, 55.7, 118.8, 39.0, 105.9, 56.0, 118.4, 43.2, 99.5, 43.7, 128.4, -1.1, 123.7, -2.0]}, {"rect": [251, 431, 529, 709], "points": [0.36076, -0.00222, 0.07105, 0.0, -0.00403, 0.36394, -0.01066, 0.0, -0.08305, -0.01851, 0.35857, 0.0, -129.94022, -226.5311, -46.67867, 1.0, 66.4, 45.6, 68.5, 30.8, 66.4, 48.4, 66.2, 51.5, 65.8, 53.0, 65.4, 59.4, 65.8, 62.7, 65.8, 67.2, 65.7, 71.4, 64.6, 76.6, 38.7, 84.3, 31.8, 18.4, 59.0, 44.7, 59.3, 51.5, 51.0, 47.8, 45.5, 51.0, 53.3, 52.4, 48.2, 53.8, 34.6, 63.6, 9.2, 17.5, 30.4, 56.6, -14.2, 49.7, 38.5, 56.6, 40.3, 56.6, 59.3, 48.4, 52.0, 50.5, 46.8, 52.4, 39.5, 56.6, 42.3, 59.3, 41.2, 56.6, 49.1, 54.7, 53.8, 53.8, 59.4, 53.3, 55.7, 76.5, 57.5, 70.9, 57.9, 66.7, 58.8, 62.2, 59.3, 59.4, 48.7, 58.4, 47.7, 59.8, 46.0, 62.0, 44.6, 64.4, 39.2, 43.8, -24.4, 13.7, 45.3, 57.6, 44.0, 58.4, 60.7, 30.8, 49.7, 29.9, 37.7, 4.5, 26.1, 9.2, 40.0, 68.7, -11.6, -1.9, 2.1, -1.0, 11.4, 1.9, 25.2, 0.9, -9.7, 13.7, 44.5, 22.5, -20.7, 31.2, 7.5, 68.6, 5.2, 75.5, -19.8, 13.8, -2.7, 58.5, 36.9, 89.8, 40.5, 12.8, 40.9, 60.4, -7.9, 28.0, 48.0, 97.8, 26.8, 89.8, 17.2, 84.3, 61.3, 98.6, 68.1, 36.0, 46.4, 39.6, 59.4, 36.8, 17.5, 77.3, 26.8, 83.4, 48.9, 94.4, -5.0, 64.6, 62.7, 95.0, 36.9, 94.5, -17.0, 29.8, 53.8, 58.9, 52.4, 61.3, 51.1, 64.5, 50.3, 68.2, 46.9, 73.3, 44.0, 55.2, 42.6, 54.7, 41.3, 53.8, 33.7, 49.7, 3.7, 32.6, 45.0, 55.6, 2.4, 49.2, 42.3, 78.7, 63.6, 89.5, 64.1, 82.6, 53.0, 82.5, 27.6, 65.9, 37.8, 28.0, 34.0, 73.3, 20.7, 26.7, 31.2, 35.0, 14.8, 38.3, 50.7, 89.0, 20.8, 70.4, 29.5, 77.8, 22.6, 57.1, -5.5, 40.0, 12.8, 57.6, -12.0, 44.7, 25.8, 44.2, -21.1, -1.9, -25.8, -2.8, 84.3, 82.0, 97.0, 18.0, 73.2, 44.6, 71.9, 51.5, 79.2, 46.9, 83.2, 50.1, 76.4, 52.0, 80.0, 53.3, 89.7, 62.5, 114.5, 17.3, 93.9, 55.6, 113.3, 47.4, 86.5, 56.2, 84.7, 56.1, 72.8, 48.3, 78.1, 49.7, 81.5, 51.9, 85.5, 56.1, 83.7, 58.9, 84.1, 56.0, 78.3, 54.2, 75.1, 53.4, 70.9, 53.0, 72.4, 76.0, 72.8, 70.5, 72.7, 66.3, 71.8, 62.1, 70.9, 59.0, 78.2, 57.9, 79.9, 59.4, 81.4, 61.6, 82.8, 63.9, 90.2, 43.2, 121.9, 13.3, 80.6, 57.0, 82.3, 58.0, 75.4, 30.8, 82.8, 29.5, 91.0, 4.4, 101.5, 9.1, 85.6, 67.6, 126.9, -1.9, 118.2, -1.6, 111.5, 1.7, 100.5, 0.9, 125.6, 13.3, 86.5, 22.4, 118.6, 29.9, 105.4, 65.4, 102.2, 71.7, 126.9, 13.3, 112.2, 56.2, 84.0, 87.1, 89.2, 12.7, 85.1, 59.8, 122.7, 27.1, 72.9, 96.3, 88.0, 85.8, 94.4, 80.1, 85.6, 39.1, 75.9, 36.7, 97.7, 74.0, 90.9, 80.1, 75.1, 93.1, 108.1, 61.7, 81.2, 91.7, 123.3, 28.9, 75.0, 58.5, 76.4, 60.8, 77.8, 64.0, 78.7, 68.0, 79.8, 72.3, 82.3, 54.7, 84.2, 53.8, 85.5, 52.9, 93.0, 48.7, 116.3, 31.7, 81.0, 55.1, 112.8, 47.7, 82.5, 76.9, 74.2, 81.5, 94.5, 64.1, 91.6, 27.6, 88.9, 71.3, 105.8, 26.2, 96.9, 34.5, 108.5, 37.3, 75.1, 88.0, 98.1, 68.1, 91.2, 75.1, 99.8, 55.7, 118.8, 38.7, 105.9, 55.7, 118.7, 43.1, 99.7, 43.6, 128.3, -1.5, 123.7, -2.4]}, {"rect": [252, 431, 530, 709], "points": [0.36178, -0.00383, 0.07142, 0.0, -0.00274, 0.36491, -0.01115, 0.0, -0.08293, -0.01677, 0.35905, 0.0, -131.32402, -226.20637, -46.68168, 1.0, 66.5, 45.5, 68.6, 30.4, 66.5, 48.3, 66.4, 51.1, 65.9, 52.9, 65.6, 59.7, 65.9, 63.0, 66.0, 67.5, 65.9, 71.7, 65.1, 77.2, 39.1, 84.6, 31.8, 18.1, 59.1, 44.6, 59.5, 51.4, 51.2, 47.7, 45.6, 51.0, 53.4, 52.4, 48.4, 53.8, 34.8, 64.0, 9.2, 17.6, 30.6, 56.7, -13.8, 49.8, 38.7, 56.6, 40.5, 56.6, 59.2, 48.2, 52.2, 50.2, 47.0, 52.4, 39.6, 56.6, 42.5, 59.4, 41.1, 56.6, 49.3, 54.7, 54.0, 53.7, 59.6, 53.0, 55.9, 76.9, 57.7, 71.2, 58.1, 66.8, 58.7, 62.5, 59.4, 59.7, 48.9, 58.5, 47.9, 59.9, 46.1, 62.1, 44.8, 64.5, 39.3, 43.8, -24.5, 13.6, 45.3, 57.9, 43.9, 58.4, 60.8, 30.4, 49.8, 29.6, 37.7, 4.3, 25.9, 9.0, 40.2, 69.1, -11.6, -2.1, 1.9, -0.9, 11.2, 1.9, 25.0, 0.9, -9.7, 13.6, 44.4, 22.2, -20.7, 31.1, 7.8, 68.7, 5.5, 75.6, -19.8, 14.0, -2.3, 58.6, 37.3, 90.2, 40.6, 12.6, 41.1, 60.7, -7.8, 27.9, 48.4, 98.5, 27.2, 90.2, 17.5, 84.6, 61.8, 99.0, 68.3, 35.8, 46.3, 39.6, 59.6, 36.4, 17.6, 77.4, 27.1, 83.8, 49.3, 94.8, -4.6, 64.9, 63.2, 95.3, 37.3, 95.2, -16.9, 29.7, 53.9, 59.3, 52.6, 61.6, 51.5, 64.9, 50.7, 68.6, 47.1, 73.7, 44.2, 55.2, 42.5, 54.7, 41.4, 53.8, 33.8, 49.7, 3.8, 32.5, 45.2, 55.6, 2.8, 49.3, 42.5, 79.1, 64.1, 90.1, 64.6, 83.2, 53.5, 82.9, 27.7, 66.0, 37.9, 27.8, 34.2, 73.6, 20.8, 26.8, 31.3, 35.0, 15.1, 38.3, 51.1, 89.3, 21.2, 70.6, 29.9, 77.9, 22.8, 57.2, -5.4, 40.1, 13.0, 57.7, -11.9, 44.8, 25.9, 44.3, -21.2, -1.7, -26.1, -2.6, 84.9, 82.0, 97.0, 17.6, 73.3, 44.2, 72.0, 51.1, 79.4, 46.8, 83.1, 49.8, 76.6, 51.9, 79.9, 53.0, 90.0, 62.3, 114.5, 16.7, 94.2, 55.4, 113.9, 47.1, 86.6, 56.1, 84.9, 55.8, 72.9, 47.9, 78.1, 49.6, 81.7, 51.5, 85.7, 55.9, 83.9, 58.9, 84.1, 55.8, 78.4, 53.9, 75.2, 53.3, 71.1, 52.9, 72.9, 76.3, 73.2, 70.8, 72.8, 66.6, 72.0, 62.4, 71.0, 59.3, 78.4, 58.0, 79.9, 59.4, 81.6, 61.6, 83.0, 64.0, 90.4, 42.9, 122.0, 12.7, 80.7, 57.0, 82.5, 58.0, 75.5, 30.4, 83.0, 29.0, 91.0, 3.8, 101.2, 8.5, 85.9, 67.7, 126.6, -2.6, 118.3, -2.4, 112.2, 1.1, 101.1, 0.2, 125.6, 12.6, 86.7, 21.8, 118.7, 29.3, 105.7, 65.1, 102.8, 71.5, 126.9, 12.7, 112.5, 55.8, 84.8, 87.4, 89.2, 12.1, 85.3, 59.8, 122.7, 26.5, 73.7, 96.7, 88.6, 86.1, 95.0, 80.1, 85.8, 38.7, 76.1, 36.3, 98.3, 73.8, 91.7, 80.1, 75.7, 93.4, 108.5, 61.4, 82.0, 92.0, 123.6, 28.3, 75.2, 58.8, 76.6, 61.1, 78.0, 64.3, 78.9, 68.1, 80.3, 72.4, 82.5, 54.4, 84.3, 53.8, 85.4, 52.8, 93.2, 48.4, 116.3, 31.1, 81.1, 54.8, 113.0, 47.1, 83.0, 77.0, 74.7, 81.9, 95.0, 64.0, 91.8, 27.2, 89.5, 71.1, 105.7, 25.8, 97.0, 34.1, 108.5, 36.9, 75.7, 88.3, 98.7, 67.8, 91.8, 75.1, 100.1, 55.4, 119.0, 38.3, 106.1, 55.4, 119.0, 42.5, 99.7, 43.0, 128.1, -2.1, 123.5, -2.9]}, {"rect": [254, 431, 532, 709], "points": [0.36398, -0.00514, 0.07075, 0.0, -0.00192, 0.36566, -0.01258, 0.0, -0.08216, -0.01403, 0.36069, 0.0, -132.88418, -225.65831, -45.3246, 1.0, 66.5, 45.1, 68.3, 30.2, 66.5, 47.9, 66.1, 51.0, 65.6, 52.6, 65.5, 59.8, 65.6, 63.0, 66.0, 67.6, 65.6, 71.8, 65.4, 77.3, 38.8, 84.8, 31.4, 18.2, 59.0, 44.2, 59.2, 51.1, 50.9, 47.4, 45.3, 50.6, 53.1, 52.1, 48.0, 53.5, 35.3, 64.3, 8.8, 17.8, 30.8, 57.3, -14.0, 50.2, 38.7, 56.6, 40.2, 56.6, 59.1, 47.9, 52.1, 49.8, 46.7, 52.1, 39.6, 56.6, 42.4, 59.5, 41.0, 56.6, 49.0, 54.4, 53.9, 53.4, 59.5, 52.9, 56.2, 77.2, 57.7, 71.3, 58.2, 67.1, 58.7, 62.6, 59.2, 59.8, 48.8, 58.8, 47.6, 60.2, 46.1, 62.2, 44.7, 64.8, 39.2, 44.0, -25.0, 14.3, 45.2, 58.0, 43.8, 58.5, 60.5, 30.3, 49.4, 29.7, 37.0, 4.4, 25.4, 9.4, 40.4, 69.4, -12.4, -1.6, 1.6, -0.6, 11.1, 2.1, 25.0, 0.8, -10.1, 14.1, 44.2, 22.3, -20.9, 31.7, 7.7, 69.1, 5.4, 76.0, -20.3, 14.5, -2.4, 59.2, 37.0, 90.6, 40.1, 12.7, 41.0, 60.7, -8.3, 28.4, 48.4, 99.0, 27.1, 90.7, 17.5, 84.8, 62.1, 99.5, 68.2, 35.4, 46.2, 39.5, 59.5, 36.3, 17.5, 77.8, 26.8, 84.2, 49.4, 95.2, -4.7, 65.4, 63.5, 95.7, 37.3, 95.4, -17.1, 30.3, 53.6, 59.3, 52.5, 61.7, 51.3, 65.0, 50.7, 68.9, 47.4, 74.0, 43.9, 55.2, 42.4, 54.4, 41.1, 53.5, 34.0, 50.0, 3.6, 33.0, 45.1, 55.3, 2.7, 49.7, 42.5, 79.2, 64.4, 90.2, 64.9, 83.3, 53.5, 83.2, 27.7, 66.6, 37.8, 27.9, 34.2, 74.0, 20.4, 27.0, 31.0, 35.2, 14.8, 38.5, 51.2, 89.7, 20.9, 71.2, 29.6, 78.3, 22.9, 57.7, -5.6, 40.5, 12.9, 58.3, -12.0, 45.4, 25.8, 44.5, -21.7, -1.1, -26.4, -1.9, 85.3, 82.3, 97.1, 17.4, 73.0, 44.1, 72.0, 51.0, 79.4, 46.5, 83.0, 49.6, 76.6, 51.6, 80.1, 52.9, 90.4, 62.5, 114.7, 16.5, 94.5, 55.5, 114.5, 47.0, 86.5, 56.1, 84.8, 55.8, 72.9, 47.8, 78.0, 49.3, 81.6, 51.1, 85.6, 56.0, 83.8, 58.9, 84.2, 55.8, 78.4, 53.8, 75.2, 52.9, 71.1, 52.5, 73.3, 76.4, 72.9, 70.9, 72.6, 66.7, 72.0, 62.5, 71.0, 59.4, 78.4, 58.0, 79.8, 59.4, 81.6, 61.6, 83.0, 63.9, 90.4, 42.7, 122.7, 12.8, 80.7, 57.0, 82.4, 57.9, 75.2, 30.2, 83.0, 28.8, 91.1, 3.6, 101.4, 8.5, 86.2, 67.6, 127.0, -2.8, 119.1, -2.4, 113.0, 0.9, 101.6, 0.2, 126.1, 12.4, 86.7, 21.5, 119.5, 29.4, 106.3, 65.3, 103.2, 71.4, 127.4, 12.7, 112.9, 55.7, 85.2, 87.4, 89.4, 11.9, 85.2, 59.8, 123.0, 26.5, 74.1, 97.1, 89.3, 86.1, 95.7, 80.1, 85.8, 38.5, 76.1, 35.9, 98.9, 73.7, 92.1, 80.1, 76.0, 93.5, 109.0, 61.3, 82.5, 92.1, 124.1, 28.1, 75.2, 58.8, 76.6, 61.1, 77.9, 64.4, 78.9, 68.1, 80.6, 72.6, 82.5, 54.3, 84.3, 53.5, 85.6, 52.5, 93.5, 48.6, 116.5, 31.1, 81.1, 54.7, 113.3, 47.0, 83.3, 77.2, 74.7, 81.9, 95.4, 64.0, 91.7, 27.0, 89.9, 71.3, 105.9, 25.7, 97.2, 33.9, 108.7, 36.7, 76.1, 88.4, 99.0, 67.7, 92.2, 75.0, 100.4, 55.5, 119.3, 38.1, 106.4, 55.3, 119.5, 42.4, 100.0, 43.1, 129.0, -2.3, 124.4, -2.9]}, {"rect": [256, 431, 534, 709], "points": [0.36578, -0.00636, 0.07222, 0.0, -0.0007, 0.36705, -0.01503, 0.0, -0.08334, -0.01153, 0.36232, 0.0, -134.88065, -225.75809, -44.79116, 1.0, 66.7, 44.7, 68.5, 29.5, 66.7, 47.7, 66.3, 50.6, 65.8, 52.4, 65.8, 59.8, 65.9, 63.1, 66.3, 67.4, 65.9, 71.9, 65.6, 77.3, 39.0, 85.1, 31.2, 17.9, 59.0, 43.7, 59.4, 50.7, 51.1, 47.0, 45.2, 50.3, 53.1, 52.0, 48.0, 53.4, 35.3, 64.4, 8.4, 17.8, 30.7, 57.1, -14.4, 50.6, 38.4, 56.6, 40.1, 56.6, 59.4, 47.5, 52.1, 49.7, 46.6, 52.0, 39.3, 56.6, 42.3, 59.7, 41.0, 56.6, 48.9, 54.3, 53.9, 53.1, 59.8, 52.5, 56.4, 77.3, 57.9, 71.4, 58.4, 67.2, 58.9, 62.6, 59.4, 59.8, 48.8, 58.8, 47.5, 60.3, 46.1, 62.5, 44.7, 64.9, 39.1, 43.7, -25.7, 14.7, 45.1, 58.0, 43.8, 58.5, 60.6, 29.8, 49.3, 29.1, 36.8, 4.1, 25.3, 9.1, 40.4, 69.5, -12.9, -1.5, 0.6, -0.6, 10.2, 1.8, 24.4, 0.4, -10.6, 14.2, 44.1, 22.0, -21.6, 32.1, 7.4, 69.4, 5.1, 76.3, -20.8, 14.6, -2.8, 59.4, 37.2, 90.8, 40.0, 12.4, 41.0, 60.8, -8.7, 28.5, 48.7, 99.4, 27.0, 91.1, 17.3, 85.2, 62.5, 99.9, 68.4, 34.9, 46.3, 39.1, 59.7, 35.9, 17.4, 78.2, 27.0, 84.6, 49.6, 95.4, -5.1, 65.7, 63.9, 96.1, 37.3, 95.8, -17.6, 30.7, 53.8, 59.4, 52.5, 61.7, 51.5, 65.2, 50.6, 69.0, 47.4, 74.1, 43.8, 54.9, 42.3, 54.4, 41.0, 53.5, 34.0, 49.8, 3.2, 33.0, 44.8, 55.3, 2.3, 50.0, 42.6, 79.5, 64.8, 90.3, 65.2, 83.3, 53.7, 83.3, 27.6, 66.7, 37.6, 27.6, 34.3, 74.1, 20.2, 26.7, 30.9, 35.0, 14.6, 38.5, 51.4, 89.8, 21.0, 71.3, 29.7, 78.6, 22.9, 57.6, -6.0, 40.8, 12.8, 58.4, -12.4, 45.5, 25.8, 44.5, -22.5, -1.0, -27.2, -1.6, 85.9, 82.3, 97.2, 16.9, 73.5, 43.6, 72.3, 50.7, 79.6, 46.1, 83.2, 49.3, 76.8, 51.2, 80.1, 52.6, 91.0, 62.5, 114.7, 16.0, 95.1, 55.2, 114.4, 46.9, 86.5, 55.8, 84.9, 55.7, 73.2, 47.4, 78.3, 48.9, 81.8, 50.8, 85.6, 55.8, 84.0, 58.6, 84.1, 55.7, 78.6, 53.5, 75.4, 52.6, 71.3, 52.2, 73.8, 76.4, 73.2, 70.9, 73.1, 66.5, 72.3, 62.3, 71.3, 59.4, 78.6, 57.9, 80.0, 59.4, 81.8, 61.4, 83.2, 63.7, 90.9, 42.3, 122.6, 12.7, 80.9, 56.8, 82.4, 57.7, 75.4, 29.5, 83.2, 28.2, 91.1, 3.1, 101.6, 7.9, 86.8, 67.6, 127.1, -3.0, 119.0, -2.6, 113.0, 0.4, 101.8, -0.5, 126.1, 12.2, 86.9, 21.1, 119.4, 29.3, 106.4, 65.0, 103.6, 71.4, 127.2, 12.3, 113.3, 55.6, 85.9, 87.5, 89.6, 11.4, 85.1, 59.6, 123.1, 26.1, 74.7, 97.2, 89.7, 86.1, 96.2, 80.1, 86.0, 38.1, 76.3, 35.5, 99.4, 73.7, 92.5, 80.1, 76.6, 93.5, 109.2, 61.2, 83.1, 92.1, 124.0, 27.9, 75.4, 58.6, 76.8, 60.9, 78.2, 64.2, 79.1, 68.1, 81.2, 72.6, 82.7, 54.0, 84.2, 53.2, 85.5, 52.2, 93.8, 48.0, 116.6, 30.7, 81.2, 54.4, 113.6, 46.9, 83.7, 77.2, 75.2, 81.9, 96.0, 63.9, 92.0, 26.3, 90.5, 71.2, 105.9, 25.2, 97.5, 33.5, 109.0, 36.3, 76.7, 88.4, 99.4, 67.6, 92.8, 75.0, 100.8, 55.2, 119.4, 37.7, 106.8, 55.1, 119.4, 42.2, 100.3, 42.8, 128.6, -2.5, 124.1, -3.0]}, {"rect": [258, 431, 536, 709], "points": [0.36788, -0.00744, 0.07305, 0.0, -1e-05, 0.36931, -0.01612, 0.0, -0.08355, -0.00988, 0.36405, 0.0, -136.49926, -226.74661, -44.74717, 1.0, 66.8, 44.3, 68.3, 28.8, 66.8, 47.2, 66.4, 50.3, 65.9, 52.1, 65.9, 59.6, 66.0, 63.1, 66.4, 67.6, 66.0, 72.2, 65.5, 77.4, 39.0, 85.2, 30.9, 17.6, 59.0, 43.3, 59.5, 50.3, 51.1, 46.7, 45.1, 50.3, 53.3, 51.7, 48.2, 53.1, 35.0, 64.5, 8.2, 17.5, 30.4, 57.1, -14.8, 50.9, 38.5, 56.7, 40.0, 56.6, 59.4, 47.1, 52.1, 49.4, 46.8, 51.8, 39.5, 56.7, 42.3, 59.6, 40.9, 56.6, 49.1, 54.0, 54.0, 53.0, 59.8, 52.2, 56.2, 77.3, 58.0, 71.7, 58.5, 67.3, 59.0, 62.7, 59.5, 59.6, 48.8, 58.7, 47.7, 60.3, 46.1, 62.6, 44.7, 64.9, 39.1, 43.4, -26.2, 15.0, 45.1, 58.0, 43.7, 58.6, 60.4, 29.2, 49.2, 28.7, 36.5, 3.7, 24.9, 8.7, 40.1, 69.5, -13.4, -1.5, -0.2, -0.7, 9.5, 1.7, 23.7, 0.0, -11.1, 14.2, 43.8, 21.4, -22.1, 32.2, 7.2, 69.5, 4.9, 76.5, -21.2, 14.7, -2.9, 59.5, 37.2, 91.2, 39.7, 12.0, 40.9, 60.8, -8.9, 28.5, 48.7, 99.8, 26.7, 91.2, 17.0, 85.6, 62.5, 100.2, 68.2, 34.3, 46.1, 38.8, 59.4, 35.5, 17.3, 78.3, 26.7, 84.8, 49.6, 95.7, -5.2, 65.9, 64.0, 96.2, 37.2, 96.2, -18.0, 30.8, 53.9, 59.4, 52.6, 61.7, 51.6, 65.3, 50.7, 69.1, 47.3, 74.1, 43.7, 54.9, 42.3, 54.4, 41.0, 53.4, 33.9, 49.8, 3.1, 33.0, 45.0, 55.3, 2.2, 49.8, 42.4, 79.6, 64.8, 90.6, 65.0, 83.4, 53.5, 83.3, 27.5, 66.7, 37.3, 27.2, 34.0, 74.1, 20.1, 26.6, 30.8, 34.7, 14.3, 38.3, 51.2, 90.2, 20.7, 71.4, 29.5, 78.7, 22.6, 57.6, -6.2, 40.9, 12.4, 58.5, -12.6, 45.6, 25.7, 44.3, -23.0, -1.0, -27.7, -1.5, 86.1, 82.1, 97.2, 16.2, 73.4, 43.0, 72.4, 50.3, 79.7, 45.7, 83.1, 49.0, 76.6, 51.1, 79.9, 52.5, 91.1, 62.3, 115.0, 15.3, 95.3, 54.9, 115.0, 46.6, 86.2, 55.8, 84.4, 55.7, 73.3, 47.0, 78.3, 48.8, 81.7, 50.7, 85.3, 55.8, 83.5, 58.6, 83.9, 55.7, 78.4, 53.4, 75.5, 52.5, 71.4, 52.1, 73.7, 76.4, 73.3, 71.0, 73.0, 66.7, 72.4, 62.3, 71.1, 59.4, 78.4, 57.7, 79.8, 59.4, 81.6, 61.3, 83.0, 63.9, 90.8, 42.0, 122.9, 12.1, 80.7, 56.7, 82.1, 57.6, 75.2, 28.8, 83.0, 27.7, 91.1, 2.4, 101.7, 7.4, 87.0, 67.3, 127.1, -3.7, 119.9, -3.5, 113.8, -0.1, 102.4, -0.9, 126.3, 11.6, 86.7, 20.4, 119.7, 28.7, 106.8, 64.9, 104.0, 71.4, 127.5, 11.7, 113.7, 55.3, 86.1, 87.5, 89.4, 10.7, 84.9, 59.8, 123.4, 25.5, 74.6, 97.5, 90.1, 86.2, 96.6, 80.1, 86.1, 37.5, 76.1, 35.0, 99.8, 73.7, 92.9, 80.1, 76.5, 93.8, 109.6, 60.9, 83.3, 92.2, 124.3, 27.3, 75.2, 58.6, 76.9, 60.9, 78.3, 64.4, 79.2, 68.2, 81.1, 72.4, 82.5, 53.9, 84.0, 53.3, 85.3, 52.4, 93.9, 47.9, 116.9, 30.1, 80.8, 54.3, 113.8, 46.5, 83.8, 77.0, 75.1, 82.0, 96.2, 63.6, 92.0, 25.9, 90.7, 71.0, 106.0, 24.6, 97.3, 32.9, 109.1, 36.0, 76.9, 88.4, 99.8, 67.3, 93.0, 75.0, 100.9, 54.9, 119.7, 37.4, 107.2, 54.8, 119.8, 41.6, 100.4, 42.4, 128.9, -3.2, 124.6, -3.6]}, {"rect": [260, 431, 538, 709], "points": [0.36941, -0.00778, 0.07459, 0.0, 0.0009, 0.37154, -0.01726, 0.0, -0.08475, -0.00893, 0.36567, 0.0, -138.19003, -228.15473, -45.13217, 1.0, 67.2, 43.9, 68.3, 28.6, 67.2, 47.0, 66.7, 50.0, 66.2, 52.1, 66.2, 59.8, 66.6, 63.2, 66.7, 67.7, 66.6, 72.0, 65.5, 77.4, 38.8, 85.6, 30.7, 17.4, 59.3, 43.0, 59.8, 50.2, 51.1, 46.6, 45.2, 50.2, 53.4, 51.6, 48.0, 53.4, 34.7, 64.5, 7.6, 17.4, 30.1, 57.1, -15.5, 51.0, 38.3, 56.7, 39.7, 56.7, 59.8, 47.0, 52.4, 49.3, 46.6, 52.0, 39.2, 56.7, 42.0, 59.8, 40.7, 56.7, 48.9, 54.0, 54.2, 53.0, 59.9, 52.2, 56.3, 77.3, 58.1, 71.6, 58.8, 67.3, 59.3, 63.0, 59.8, 59.8, 48.8, 58.9, 47.5, 60.4, 46.1, 62.7, 44.7, 65.0, 38.9, 43.3, -26.7, 15.0, 44.8, 58.1, 43.7, 58.9, 60.2, 29.1, 49.0, 28.6, 36.5, 3.3, 24.6, 8.4, 39.9, 69.6, -14.0, -1.8, -0.4, -1.3, 9.3, 1.1, 23.5, -0.4, -11.7, 14.2, 43.6, 21.2, -22.6, 32.5, 6.7, 69.6, 4.4, 76.8, -21.9, 14.6, -3.5, 59.8, 37.0, 91.5, 39.4, 11.6, 40.7, 60.8, -9.5, 28.5, 48.6, 99.9, 26.4, 91.6, 16.7, 86.0, 62.4, 100.4, 68.0, 34.2, 45.9, 38.7, 59.2, 35.1, 16.8, 78.7, 26.4, 85.1, 49.5, 95.9, -5.9, 66.2, 64.1, 96.3, 37.0, 96.6, -18.7, 30.8, 53.9, 59.5, 52.9, 61.8, 51.6, 65.1, 50.7, 69.2, 47.1, 74.2, 43.5, 54.9, 42.0, 54.4, 41.0, 53.5, 33.5, 49.7, 2.5, 32.8, 44.8, 55.3, 1.6, 50.1, 42.4, 79.7, 64.7, 90.7, 65.1, 83.7, 53.6, 83.4, 27.3, 66.8, 37.1, 27.1, 33.8, 74.2, 19.7, 26.3, 30.6, 34.6, 14.0, 38.3, 51.2, 90.3, 20.4, 71.4, 29.2, 78.8, 22.3, 57.6, -6.8, 40.9, 12.1, 58.5, -13.2, 45.6, 25.5, 44.2, -23.5, -1.1, -28.5, -1.5, 86.2, 82.4, 97.3, 15.8, 73.7, 42.8, 72.7, 50.2, 80.1, 45.5, 83.4, 49.1, 77.0, 51.0, 80.1, 52.4, 91.2, 62.2, 115.2, 15.0, 95.4, 54.9, 115.1, 46.5, 85.9, 56.0, 84.4, 55.7, 73.6, 46.7, 78.7, 48.5, 82.0, 50.7, 85.3, 56.0, 83.6, 58.8, 83.6, 55.7, 78.4, 53.3, 75.6, 52.5, 71.5, 52.0, 73.8, 76.4, 73.7, 71.1, 73.5, 66.8, 72.7, 62.6, 71.4, 59.4, 78.4, 57.9, 79.8, 59.4, 81.7, 61.6, 83.1, 63.9, 90.9, 41.6, 123.2, 11.7, 80.7, 57.0, 82.2, 57.9, 75.3, 28.6, 83.1, 27.3, 91.0, 2.0, 101.6, 7.0, 87.1, 67.3, 127.5, -4.3, 120.1, -3.9, 113.8, -0.7, 102.3, -1.6, 126.6, 11.2, 86.8, 20.0, 120.0, 28.6, 107.2, 64.9, 104.4, 71.4, 127.9, 11.6, 114.1, 55.3, 86.2, 87.6, 89.4, 10.3, 84.9, 59.8, 123.8, 25.1, 74.7, 97.7, 90.3, 86.5, 96.7, 80.2, 86.2, 37.4, 76.2, 34.7, 100.0, 73.7, 93.1, 80.2, 76.9, 93.9, 110.0, 60.9, 83.4, 92.5, 124.7, 26.9, 75.5, 58.8, 77.0, 61.1, 78.4, 64.5, 79.3, 68.2, 81.2, 72.4, 82.5, 53.8, 84.0, 53.3, 85.4, 52.4, 94.1, 47.6, 117.1, 29.7, 80.8, 54.3, 114.2, 46.3, 83.9, 77.0, 75.2, 82.0, 96.3, 63.6, 91.9, 25.5, 90.8, 71.0, 106.4, 24.2, 97.6, 32.7, 109.3, 35.6, 77.0, 88.5, 100.0, 67.3, 93.1, 74.8, 101.3, 54.9, 120.1, 37.1, 107.4, 54.5, 120.1, 41.6, 100.5, 42.1, 129.3, -3.6, 124.6, -4.0]}, {"rect": [263, 431, 541, 709], "points": [0.37058, -0.00765, 0.07665, 0.0, 0.00154, 0.37378, -0.01812, 0.0, -0.08698, -0.00849, 0.36656, 0.0, -139.777, -229.8851, -46.05926, 1.0, 66.8, 43.8, 68.3, 28.5, 66.8, 47.0, 66.6, 50.2, 65.9, 52.0, 65.9, 59.9, 66.3, 63.5, 66.3, 67.8, 66.3, 72.4, 65.4, 77.5, 38.4, 85.7, 30.5, 17.1, 59.0, 42.8, 59.4, 50.2, 50.7, 46.5, 44.8, 50.3, 53.0, 51.6, 47.8, 53.4, 34.2, 64.6, 7.1, 17.1, 29.7, 57.2, -16.4, 50.8, 37.8, 57.1, 39.3, 56.8, 59.4, 47.0, 52.0, 49.3, 46.2, 52.0, 38.7, 57.1, 41.6, 59.9, 40.2, 56.8, 48.8, 54.3, 53.8, 52.9, 59.5, 52.4, 55.9, 77.1, 57.9, 71.9, 58.4, 67.6, 58.9, 63.1, 59.4, 59.9, 48.4, 59.0, 47.1, 60.5, 45.6, 62.8, 44.3, 65.3, 38.4, 43.3, -27.8, 14.8, 44.6, 58.1, 43.3, 59.0, 60.0, 29.0, 48.7, 28.5, 36.1, 3.1, 24.2, 8.2, 39.7, 69.6, -14.6, -1.9, -1.2, -1.8, 8.5, 0.9, 22.8, -0.5, -12.3, 13.9, 43.4, 21.1, -23.7, 32.3, 6.1, 69.6, 3.8, 77.0, -22.8, 14.3, -4.4, 59.9, 36.6, 91.7, 39.2, 11.4, 40.2, 60.9, -10.3, 28.5, 48.4, 100.1, 25.9, 91.7, 15.9, 86.2, 62.2, 100.5, 68.1, 34.1, 45.7, 38.7, 59.1, 35.0, 16.3, 78.8, 25.9, 85.2, 49.3, 96.3, -6.8, 66.1, 63.7, 96.5, 36.6, 96.8, -19.6, 30.5, 53.5, 59.5, 52.5, 62.1, 51.2, 65.5, 50.3, 69.6, 46.7, 74.2, 43.2, 55.2, 41.6, 54.4, 40.5, 53.5, 33.2, 49.7, 2.0, 32.7, 44.3, 55.4, 1.1, 49.9, 42.0, 79.8, 64.6, 90.8, 64.9, 83.6, 53.4, 83.5, 26.8, 66.9, 36.6, 26.8, 33.3, 74.2, 19.4, 26.2, 30.2, 34.5, 13.5, 38.2, 50.8, 90.4, 19.9, 71.5, 28.7, 78.9, 21.8, 57.6, -7.6, 40.7, 11.6, 58.5, -14.1, 45.6, 25.0, 44.2, -24.5, -1.4, -29.6, -1.9, 86.1, 82.3, 97.2, 15.7, 73.6, 42.5, 72.3, 50.2, 79.7, 45.2, 83.3, 48.9, 76.9, 50.8, 79.8, 52.2, 90.8, 62.3, 114.8, 14.9, 95.3, 54.9, 114.7, 46.4, 85.8, 55.8, 84.1, 55.5, 73.3, 46.6, 78.3, 48.4, 81.6, 50.7, 85.0, 55.5, 83.4, 58.6, 83.4, 55.5, 78.3, 53.1, 75.2, 52.2, 71.4, 52.0, 73.7, 76.3, 73.6, 71.4, 73.2, 66.9, 72.3, 62.6, 71.3, 59.5, 78.3, 57.8, 79.7, 59.2, 81.6, 61.4, 82.9, 63.8, 90.8, 41.6, 122.6, 11.7, 80.3, 56.8, 82.0, 57.7, 75.2, 28.5, 82.9, 27.2, 90.9, 1.9, 101.5, 6.6, 86.7, 67.4, 127.0, -4.5, 119.5, -4.1, 113.2, -0.8, 101.7, -1.8, 126.3, 10.8, 86.7, 19.9, 119.4, 28.4, 106.9, 64.8, 104.1, 71.6, 127.3, 11.3, 113.8, 55.1, 86.1, 87.7, 89.1, 10.2, 84.8, 59.6, 123.5, 25.0, 74.6, 97.8, 90.2, 86.7, 96.6, 80.3, 86.1, 37.3, 76.1, 34.6, 99.9, 73.8, 93.0, 80.3, 76.5, 94.1, 109.6, 61.0, 83.3, 92.7, 124.4, 26.9, 75.2, 58.6, 76.9, 61.0, 78.3, 64.5, 79.2, 68.3, 81.1, 72.4, 82.1, 53.6, 83.9, 53.1, 85.2, 52.1, 94.0, 47.6, 117.0, 29.6, 80.7, 54.1, 113.9, 46.3, 83.8, 77.1, 75.2, 82.1, 96.3, 63.7, 91.8, 25.4, 90.7, 71.1, 106.1, 24.1, 97.3, 32.5, 109.2, 35.6, 76.9, 88.6, 99.9, 67.4, 93.0, 74.9, 101.0, 54.9, 119.8, 37.0, 107.3, 54.6, 119.8, 41.6, 100.4, 42.1, 128.7, -3.9, 123.7, -4.4]}, {"rect": [265, 431, 543, 709], "points": [0.37167, -0.00718, 0.0779, 0.0, 0.00149, 0.37649, -0.01929, 0.0, -0.08882, -0.00758, 0.36699, 0.0, -140.49035, -231.97727, -46.22912, 1.0, 67.1, 43.7, 68.9, 28.2, 67.1, 46.9, 66.7, 50.2, 66.2, 52.0, 66.2, 60.0, 66.6, 63.6, 66.6, 68.2, 66.6, 72.8, 65.7, 77.9, 38.9, 86.1, 30.8, 17.0, 59.3, 42.8, 59.7, 50.2, 51.0, 46.5, 45.0, 50.5, 53.3, 51.6, 47.8, 53.4, 34.5, 64.8, 7.6, 17.0, 30.1, 57.4, -16.7, 51.1, 37.8, 57.2, 39.5, 57.1, 59.4, 46.9, 52.0, 49.3, 46.4, 52.0, 38.7, 57.2, 41.8, 60.3, 40.4, 57.1, 48.8, 54.3, 53.9, 53.0, 59.8, 52.4, 56.4, 77.4, 58.0, 72.4, 58.5, 67.8, 59.2, 63.2, 59.7, 60.0, 48.7, 59.4, 47.3, 60.8, 45.8, 63.1, 44.5, 65.5, 39.0, 43.2, -27.8, 14.7, 44.6, 58.5, 43.3, 59.3, 60.6, 28.7, 49.5, 28.2, 36.6, 2.8, 24.7, 7.9, 39.9, 69.9, -14.4, -2.3, -1.1, -2.2, 8.7, 0.5, 22.9, -0.9, -12.1, 13.7, 43.9, 20.8, -23.7, 32.2, 6.2, 69.9, 3.9, 77.4, -22.7, 14.2, -4.3, 60.2, 37.0, 92.1, 39.5, 11.1, 40.4, 61.3, -9.9, 28.5, 48.6, 100.5, 26.1, 92.1, 16.3, 86.5, 62.5, 101.0, 68.5, 34.0, 46.3, 38.6, 59.7, 35.0, 16.5, 79.1, 26.1, 85.6, 49.6, 96.7, -7.0, 66.6, 64.2, 97.1, 37.0, 97.2, -19.5, 30.7, 53.8, 59.9, 52.7, 62.3, 51.5, 65.8, 50.5, 69.9, 47.2, 74.6, 43.2, 55.3, 41.8, 54.7, 40.5, 53.8, 33.5, 49.7, 2.2, 32.6, 44.6, 55.7, 1.2, 50.1, 42.3, 80.1, 65.1, 91.2, 65.2, 84.2, 53.7, 83.9, 27.0, 67.1, 37.1, 26.7, 33.5, 74.6, 19.7, 26.2, 30.7, 34.5, 13.7, 38.2, 51.3, 90.8, 20.1, 71.8, 29.2, 79.2, 22.0, 57.9, -7.5, 40.8, 11.8, 58.8, -14.0, 45.9, 25.2, 44.2, -24.5, -1.8, -29.6, -2.3, 86.5, 82.9, 97.8, 15.6, 74.0, 42.4, 72.6, 50.2, 80.0, 45.2, 83.7, 48.9, 77.2, 50.8, 80.3, 52.2, 91.2, 62.6, 115.4, 15.1, 95.6, 55.2, 115.0, 46.9, 86.3, 55.9, 84.8, 55.8, 73.6, 46.5, 78.6, 48.4, 82.1, 50.7, 85.7, 55.8, 84.0, 58.6, 84.0, 55.8, 78.6, 53.1, 75.7, 52.4, 71.7, 52.0, 74.0, 76.9, 73.9, 71.8, 73.5, 67.3, 72.6, 62.7, 71.6, 59.5, 78.6, 58.1, 80.3, 59.5, 82.1, 61.8, 83.5, 64.1, 91.1, 41.8, 122.9, 11.9, 80.8, 57.1, 82.6, 57.7, 75.8, 28.5, 83.3, 27.2, 91.5, 1.8, 102.1, 6.5, 87.3, 67.7, 127.8, -4.6, 120.0, -4.2, 113.9, -0.9, 102.4, -1.9, 126.9, 11.0, 87.3, 19.9, 119.6, 28.9, 107.2, 65.4, 104.4, 72.2, 127.9, 11.5, 114.1, 55.7, 86.4, 88.4, 89.7, 10.1, 85.3, 59.9, 123.8, 25.3, 74.9, 98.5, 90.2, 87.1, 96.7, 81.0, 86.5, 37.3, 76.7, 34.6, 100.2, 74.2, 93.3, 81.0, 76.8, 94.4, 109.9, 61.6, 83.7, 93.1, 124.7, 27.1, 75.7, 58.7, 77.2, 61.3, 78.6, 64.7, 79.5, 68.7, 81.5, 72.8, 82.6, 53.9, 84.4, 53.1, 85.8, 52.2, 94.3, 47.9, 117.3, 29.9, 81.2, 54.3, 114.5, 46.8, 84.2, 77.4, 75.7, 82.5, 96.6, 64.0, 92.3, 25.4, 91.1, 71.4, 106.7, 24.3, 97.9, 32.7, 109.8, 35.8, 77.2, 89.3, 100.3, 68.0, 93.4, 75.4, 101.5, 55.2, 120.1, 37.5, 107.6, 55.1, 120.4, 41.9, 100.8, 42.3, 129.2, -3.8, 124.2, -4.2]}, {"rect": [267, 432, 545, 710], "points": [0.3727, -0.00662, 0.07922, 0.0, 0.00127, 0.3788, -0.01998, 0.0, -0.09043, -0.00707, 0.36736, 0.0, -141.12021, -234.06166, -46.76384, 1.0, 67.2, 43.0, 69.0, 27.7, 67.2, 46.2, 66.7, 49.7, 66.2, 51.6, 66.2, 59.9, 66.3, 63.5, 66.6, 68.1, 66.3, 73.0, 65.8, 77.8, 38.7, 85.7, 30.9, 16.2, 59.3, 42.0, 59.8, 49.8, 51.0, 46.0, 45.0, 49.8, 53.3, 51.2, 47.8, 53.0, 34.5, 64.5, 7.4, 16.2, 29.9, 56.8, -17.1, 50.7, 37.8, 57.0, 39.5, 57.0, 59.4, 46.2, 52.0, 48.8, 46.4, 51.6, 38.7, 57.0, 41.8, 59.9, 40.4, 57.0, 48.8, 53.9, 53.8, 52.5, 59.8, 51.7, 56.5, 77.4, 57.9, 72.5, 58.5, 67.7, 59.0, 63.1, 59.4, 59.9, 48.7, 59.3, 47.3, 60.7, 45.6, 63.0, 44.2, 65.4, 39.0, 42.5, -28.2, 13.9, 44.6, 58.4, 43.2, 59.0, 60.7, 28.2, 49.6, 27.7, 36.4, 2.0, 24.8, 7.1, 40.0, 69.6, -14.7, -3.1, -1.5, -2.8, 8.4, -0.4, 22.7, -1.7, -12.4, 13.0, 43.8, 20.0, -24.4, 31.8, 5.9, 69.6, 3.6, 77.3, -23.1, 13.5, -4.7, 59.5, 36.8, 91.8, 39.6, 10.3, 40.4, 61.2, -10.2, 27.7, 48.6, 100.8, 26.1, 92.1, 16.0, 86.2, 62.5, 101.2, 68.6, 33.3, 46.4, 37.9, 59.8, 34.3, 16.4, 78.8, 26.1, 85.3, 49.6, 96.7, -7.4, 66.3, 64.0, 97.1, 36.8, 97.2, -19.9, 30.0, 53.8, 59.8, 52.5, 62.2, 51.5, 65.7, 50.6, 69.9, 47.3, 74.2, 43.2, 54.9, 41.8, 54.3, 40.5, 53.4, 33.5, 49.3, 1.9, 31.9, 44.6, 55.3, 0.9, 49.7, 42.3, 79.8, 64.9, 91.2, 65.3, 84.2, 53.8, 83.8, 27.0, 66.8, 37.2, 26.2, 33.5, 74.2, 19.7, 25.4, 30.7, 33.8, 13.7, 37.8, 51.2, 90.7, 19.8, 71.7, 29.0, 79.2, 22.0, 57.5, -7.8, 40.1, 11.5, 58.2, -14.4, 45.2, 25.3, 43.7, -24.6, -2.7, -30.0, -3.1, 86.8, 82.9, 98.0, 14.9, 74.0, 41.9, 72.7, 49.7, 80.1, 44.8, 83.7, 48.4, 77.3, 50.6, 80.1, 52.0, 91.5, 62.3, 115.7, 14.4, 95.7, 54.9, 115.2, 46.8, 86.2, 55.7, 84.7, 55.7, 73.6, 46.0, 78.7, 47.9, 82.0, 50.3, 85.6, 55.7, 83.8, 58.5, 83.8, 55.6, 78.7, 52.9, 75.5, 52.0, 71.7, 51.6, 74.1, 76.8, 73.7, 71.8, 73.5, 67.2, 72.7, 62.6, 71.4, 59.4, 78.7, 58.0, 80.1, 59.4, 81.9, 61.7, 83.3, 64.0, 91.5, 41.1, 123.1, 11.5, 80.7, 57.0, 82.4, 57.6, 75.9, 27.8, 83.6, 26.8, 91.8, 1.1, 102.4, 6.0, 87.4, 67.7, 128.1, -5.0, 120.2, -4.9, 114.1, -1.4, 102.4, -2.6, 127.2, 10.6, 87.4, 19.4, 119.8, 28.5, 107.5, 65.3, 104.3, 71.9, 128.1, 11.1, 114.3, 55.6, 86.5, 88.4, 90.0, 9.4, 85.2, 59.8, 124.1, 24.9, 75.0, 98.5, 90.5, 87.0, 96.9, 80.9, 86.8, 36.9, 76.8, 34.2, 100.2, 74.1, 93.4, 80.9, 77.1, 94.4, 109.9, 61.6, 83.7, 93.1, 125.0, 26.8, 75.5, 58.8, 77.2, 61.2, 78.7, 64.8, 79.6, 68.9, 81.8, 72.7, 82.5, 53.5, 84.3, 52.9, 85.6, 52.0, 94.6, 47.5, 117.6, 29.5, 81.0, 53.9, 114.8, 46.5, 84.5, 77.4, 75.8, 82.4, 96.9, 63.9, 92.4, 24.9, 91.4, 71.4, 107.0, 23.7, 98.0, 32.3, 109.8, 35.4, 77.3, 89.2, 100.6, 67.7, 93.6, 75.4, 101.6, 54.9, 120.4, 37.0, 107.9, 54.8, 120.4, 41.5, 101.0, 41.9, 129.5, -4.4, 124.4, -4.9]}, {"rect": [269, 432, 547, 710], "points": [0.37275, -0.00575, 0.08104, 0.0, 0.0011, 0.38067, -0.02058, 0.0, -0.09251, -0.00717, 0.36657, 0.0, -141.40485, -235.88876, -47.71873, 1.0, 67.1, 43.1, 69.3, 28.0, 67.1, 46.1, 66.7, 49.7, 66.2, 51.7, 65.9, 60.2, 66.3, 63.9, 66.3, 68.6, 66.3, 73.2, 65.8, 78.2, 38.6, 86.1, 31.1, 16.1, 59.3, 42.2, 59.7, 49.8, 50.9, 46.0, 45.0, 50.0, 53.3, 51.5, 47.8, 53.3, 34.4, 64.5, 7.6, 16.1, 29.9, 57.0, -17.6, 51.0, 37.9, 57.3, 39.4, 57.1, 59.4, 46.4, 51.9, 48.8, 46.4, 51.6, 38.8, 57.3, 41.7, 60.2, 40.3, 57.1, 48.9, 54.2, 53.8, 52.6, 59.8, 52.0, 56.5, 77.8, 57.9, 72.8, 58.4, 68.1, 58.9, 63.5, 59.4, 60.2, 48.7, 59.4, 47.3, 60.8, 45.5, 63.1, 44.1, 65.8, 39.1, 42.8, -28.7, 13.7, 44.5, 58.5, 43.1, 59.3, 61.0, 28.4, 49.6, 27.6, 36.7, 1.9, 25.0, 7.2, 40.0, 70.0, -14.5, -3.3, -0.9, -3.1, 8.8, -0.5, 23.1, -1.8, -12.5, 12.8, 44.0, 20.2, -24.9, 31.7, 5.6, 69.9, 3.1, 77.7, -23.5, 13.4, -5.1, 59.8, 36.7, 92.4, 39.9, 10.4, 40.3, 61.6, -10.3, 27.7, 48.4, 101.3, 25.7, 92.5, 15.6, 86.8, 62.5, 101.7, 68.9, 33.6, 46.4, 38.1, 60.1, 34.5, 16.0, 79.1, 25.8, 85.6, 49.6, 97.1, -7.9, 66.6, 64.0, 97.6, 36.7, 97.6, -20.3, 29.9, 53.7, 59.9, 52.4, 62.5, 51.4, 65.9, 50.5, 70.0, 47.3, 74.6, 43.1, 55.2, 41.7, 54.6, 40.4, 53.7, 33.5, 49.3, 2.0, 32.1, 44.5, 55.6, 0.8, 49.7, 42.3, 80.2, 64.9, 91.6, 65.3, 84.4, 53.8, 84.2, 26.7, 66.8, 37.2, 26.2, 33.5, 74.6, 19.7, 25.4, 30.7, 34.0, 13.7, 37.7, 51.4, 91.1, 19.7, 71.9, 28.9, 79.5, 22.0, 57.5, -8.0, 40.1, 11.4, 58.4, -14.8, 45.5, 25.3, 43.7, -24.9, -2.8, -30.4, -3.3, 86.6, 83.3, 98.0, 15.2, 74.0, 41.9, 72.7, 49.7, 80.1, 45.0, 83.7, 48.7, 77.3, 50.6, 80.1, 52.1, 91.5, 62.6, 115.6, 14.6, 95.7, 55.2, 114.7, 47.0, 86.4, 56.0, 84.7, 56.0, 73.6, 46.0, 78.7, 47.9, 82.0, 50.5, 85.6, 56.0, 83.8, 58.9, 83.8, 55.7, 78.7, 53.0, 75.5, 52.0, 71.5, 51.6, 74.1, 77.0, 73.7, 72.3, 73.3, 67.6, 72.7, 63.0, 71.4, 59.8, 78.7, 58.3, 80.1, 59.8, 81.9, 62.0, 83.3, 64.4, 91.5, 41.4, 122.5, 11.6, 80.9, 57.1, 82.4, 58.0, 76.2, 28.0, 83.7, 27.0, 91.6, 1.3, 102.2, 6.0, 87.4, 68.1, 127.6, -5.0, 119.7, -4.6, 113.4, -1.3, 102.1, -2.3, 127.0, 10.6, 87.7, 19.7, 119.3, 28.7, 107.2, 65.5, 104.1, 72.3, 127.7, 11.1, 113.9, 55.8, 86.4, 88.8, 90.1, 9.6, 85.2, 60.2, 123.9, 25.3, 74.9, 99.0, 90.2, 87.5, 96.6, 81.1, 86.9, 37.2, 76.9, 34.4, 99.9, 74.5, 93.4, 81.1, 76.9, 94.9, 109.6, 61.8, 83.7, 93.8, 124.7, 27.1, 75.5, 59.0, 77.0, 61.6, 78.7, 65.0, 79.6, 69.1, 81.9, 73.2, 82.7, 53.8, 84.3, 53.2, 85.7, 52.0, 94.4, 47.8, 117.4, 29.9, 81.1, 54.2, 114.6, 46.6, 84.3, 77.8, 75.9, 82.9, 96.7, 64.1, 92.5, 25.2, 91.2, 71.8, 106.8, 23.9, 98.0, 32.6, 109.6, 35.5, 77.3, 89.5, 100.3, 68.1, 93.4, 75.6, 101.6, 55.2, 120.1, 37.3, 107.7, 55.2, 120.2, 41.9, 100.8, 42.3, 129.0, -4.2, 123.6, -4.6]}, {"rect": [271, 433, 549, 711], "points": [0.37347, -0.00502, 0.08251, 0.0, 0.00091, 0.38242, -0.02079, 0.0, -0.09393, -0.00674, 0.36692, 0.0, -141.94357, -237.63055, -48.67198, 1.0, 67.1, 42.4, 69.3, 27.5, 67.0, 45.9, 66.7, 49.3, 66.2, 51.5, 65.8, 59.9, 66.2, 63.7, 66.2, 68.3, 66.2, 73.0, 65.7, 78.2, 38.5, 86.1, 31.0, 15.6, 59.2, 41.5, 59.4, 49.6, 50.6, 45.6, 44.6, 49.4, 52.9, 51.1, 47.4, 52.9, 34.3, 64.4, 7.5, 15.6, 29.8, 56.6, -18.3, 50.3, 37.3, 56.7, 39.0, 56.7, 59.3, 46.0, 51.6, 48.4, 46.0, 51.1, 38.2, 56.7, 41.3, 59.9, 39.7, 56.7, 48.4, 53.8, 53.7, 52.4, 59.7, 51.6, 56.4, 77.8, 57.5, 72.5, 58.3, 67.9, 58.8, 63.2, 59.3, 59.9, 48.3, 59.3, 46.9, 60.8, 45.1, 63.1, 43.7, 65.5, 39.0, 42.3, -29.4, 13.0, 44.2, 58.4, 42.8, 58.9, 61.0, 28.0, 49.5, 27.2, 36.6, 1.3, 24.7, 6.5, 39.9, 69.9, -14.9, -4.1, -1.5, -3.7, 8.2, -1.3, 22.8, -2.4, -12.7, 12.1, 44.0, 19.7, -25.4, 31.0, 5.4, 69.6, 2.4, 77.4, -24.0, 12.9, -5.5, 59.4, 36.3, 92.2, 39.8, 9.7, 39.7, 61.2, -10.7, 27.2, 48.2, 101.3, 25.3, 92.5, 15.2, 86.5, 62.5, 101.8, 68.9, 33.3, 46.3, 37.6, 60.1, 34.3, 15.6, 78.8, 25.7, 85.6, 49.3, 97.1, -8.3, 66.0, 63.9, 97.6, 36.3, 97.6, -20.8, 29.5, 53.4, 59.8, 52.0, 62.3, 51.1, 65.9, 50.2, 69.8, 47.0, 74.6, 42.8, 54.8, 41.4, 54.0, 40.0, 53.1, 33.5, 48.8, 1.7, 31.4, 44.1, 55.2, 0.4, 49.3, 42.2, 80.1, 64.8, 91.6, 65.3, 84.3, 53.7, 84.2, 26.6, 66.7, 37.1, 25.7, 33.4, 74.5, 19.6, 24.9, 30.7, 33.5, 13.6, 37.3, 51.1, 91.1, 19.6, 71.7, 28.5, 79.2, 21.6, 57.1, -8.4, 39.6, 11.3, 58.0, -15.2, 44.8, 25.2, 43.3, -25.4, -3.6, -30.9, -4.1, 86.5, 83.3, 98.0, 15.0, 74.0, 41.4, 72.6, 49.3, 80.3, 44.5, 83.7, 48.3, 77.2, 50.2, 80.3, 51.9, 91.5, 62.5, 115.5, 14.2, 95.7, 55.1, 114.4, 46.9, 86.4, 55.7, 84.9, 55.6, 73.6, 45.6, 78.9, 47.4, 82.2, 50.1, 85.8, 55.7, 84.0, 58.8, 84.0, 55.6, 78.6, 52.8, 75.7, 51.6, 71.6, 51.1, 74.0, 77.3, 73.7, 72.0, 73.2, 67.3, 72.6, 62.7, 71.3, 59.8, 78.6, 58.0, 80.3, 59.7, 81.9, 61.7, 83.3, 64.4, 91.5, 41.2, 122.2, 11.5, 80.9, 57.0, 82.6, 57.9, 76.2, 27.5, 83.7, 26.6, 91.6, 0.8, 102.2, 5.8, 87.4, 68.1, 127.6, -5.2, 119.1, -4.9, 113.0, -1.6, 101.8, -2.5, 126.8, 10.5, 87.7, 19.2, 119.1, 28.8, 107.0, 65.6, 103.8, 72.3, 127.6, 10.9, 113.8, 55.7, 86.2, 88.8, 90.1, 9.1, 85.4, 59.9, 123.8, 25.2, 74.7, 99.0, 89.9, 87.4, 96.3, 81.1, 86.9, 36.7, 77.1, 34.0, 99.6, 74.5, 93.1, 81.1, 76.8, 94.9, 109.3, 62.0, 83.3, 93.8, 124.5, 27.0, 75.4, 58.9, 77.2, 61.3, 78.6, 64.9, 79.5, 69.1, 81.8, 73.2, 82.7, 53.4, 84.5, 52.9, 85.8, 51.6, 94.4, 47.7, 117.4, 29.7, 81.2, 53.9, 114.3, 46.5, 84.3, 77.8, 75.6, 82.9, 96.6, 63.9, 92.5, 24.7, 91.1, 71.7, 106.8, 23.7, 98.0, 32.1, 109.6, 35.3, 77.2, 89.7, 100.0, 68.1, 93.1, 75.5, 101.4, 55.1, 119.9, 37.2, 107.4, 55.1, 119.9, 41.8, 100.8, 41.9, 128.7, -4.3, 123.6, -4.8]}, {"rect": [272, 433, 550, 711], "points": [0.3745, -0.00487, 0.08275, 0.0, 0.00101, 0.38419, -0.02101, 0.0, -0.09393, -0.00586, 0.36788, 0.0, -142.50945, -238.89666, -48.67953, 1.0, 67.0, 42.4, 69.2, 27.3, 66.9, 45.7, 66.8, 49.3, 66.3, 51.5, 65.9, 60.3, 66.3, 64.1, 66.4, 69.0, 66.3, 73.7, 65.9, 78.5, 38.3, 86.3, 30.9, 15.6, 59.1, 41.5, 59.5, 49.7, 50.7, 45.6, 44.7, 49.4, 53.0, 51.1, 47.5, 53.0, 34.2, 64.5, 7.1, 15.6, 29.9, 56.7, -18.1, 50.6, 37.4, 56.8, 38.8, 56.8, 59.4, 46.0, 51.7, 48.4, 46.1, 51.2, 38.3, 56.8, 41.1, 60.0, 39.7, 56.7, 48.5, 53.9, 53.6, 52.4, 59.6, 51.6, 56.3, 78.3, 57.6, 73.2, 58.4, 68.6, 59.0, 63.6, 59.4, 60.3, 48.4, 59.5, 47.0, 60.9, 45.2, 63.2, 43.8, 65.9, 39.1, 42.4, -29.5, 12.9, 44.2, 58.5, 42.9, 59.1, 60.9, 27.7, 49.4, 27.2, 36.5, 1.0, 24.5, 6.4, 39.7, 70.1, -15.1, -4.2, -1.8, -3.8, 8.2, -1.4, 22.6, -2.7, -12.9, 12.0, 43.9, 19.4, -25.4, 31.2, 5.4, 70.0, 2.6, 77.5, -24.0, 12.8, -5.2, 59.5, 36.4, 92.6, 39.7, 9.6, 39.7, 61.4, -11.0, 27.1, 48.3, 101.8, 25.3, 92.7, 15.2, 86.7, 62.6, 102.3, 68.8, 32.9, 46.2, 37.4, 60.0, 33.9, 15.7, 79.2, 25.7, 85.8, 49.3, 97.3, -8.4, 66.3, 64.0, 98.1, 36.4, 98.1, -20.8, 29.5, 53.5, 59.9, 52.1, 62.6, 51.1, 66.4, 50.2, 70.5, 47.0, 75.1, 42.9, 54.8, 41.4, 54.0, 40.0, 53.1, 33.6, 48.8, 1.4, 31.4, 43.9, 55.3, 0.4, 49.3, 42.0, 80.6, 65.0, 92.1, 65.4, 84.8, 53.5, 84.4, 26.7, 66.8, 37.3, 25.5, 33.3, 74.7, 19.5, 24.8, 30.5, 33.3, 13.5, 37.3, 51.2, 91.3, 19.4, 71.9, 28.5, 79.4, 21.7, 57.2, -8.4, 39.6, 11.1, 58.1, -15.3, 45.0, 25.3, 43.3, -25.4, -3.7, -31.0, -4.1, 86.6, 83.5, 98.2, 14.8, 73.9, 41.4, 72.8, 49.3, 80.2, 44.3, 83.8, 48.1, 77.4, 50.2, 80.2, 51.8, 91.7, 62.6, 115.8, 14.0, 95.8, 55.0, 114.7, 47.1, 86.6, 55.6, 84.8, 55.5, 73.7, 45.6, 78.9, 47.5, 82.1, 49.9, 85.7, 55.6, 84.2, 58.7, 83.9, 55.4, 78.8, 52.7, 75.6, 51.7, 71.5, 51.2, 74.2, 77.5, 74.0, 72.7, 73.6, 67.8, 72.8, 63.2, 71.4, 59.9, 78.8, 58.1, 80.2, 59.7, 82.0, 61.9, 83.4, 64.6, 91.7, 41.1, 122.6, 11.6, 81.0, 56.9, 82.5, 57.8, 76.1, 27.3, 83.9, 26.4, 91.7, 0.6, 102.3, 5.6, 87.6, 68.2, 128.0, -5.4, 119.6, -5.3, 113.2, -1.8, 101.8, -2.7, 127.2, 10.3, 87.6, 19.0, 119.7, 28.7, 107.4, 65.6, 104.1, 72.4, 128.1, 10.8, 114.1, 55.9, 86.5, 89.0, 90.0, 8.9, 85.5, 60.0, 124.0, 25.0, 75.0, 99.5, 90.2, 87.7, 96.7, 81.5, 86.8, 36.5, 77.0, 33.7, 99.9, 74.7, 93.4, 81.5, 76.9, 95.4, 109.7, 61.9, 83.4, 94.1, 124.9, 26.9, 75.5, 59.1, 77.3, 61.7, 78.8, 65.4, 79.7, 69.5, 82.0, 73.4, 82.8, 53.5, 84.4, 52.7, 85.8, 51.7, 94.5, 47.5, 117.9, 29.6, 81.1, 54.0, 114.7, 46.6, 84.7, 78.0, 76.0, 83.3, 96.8, 64.1, 92.6, 24.5, 91.2, 71.9, 107.0, 23.5, 98.2, 31.9, 109.8, 35.2, 77.4, 89.9, 100.4, 68.2, 93.5, 75.7, 101.7, 55.0, 120.3, 37.1, 107.8, 55.0, 120.3, 42.0, 101.0, 41.9, 129.4, -4.5, 124.0, -4.9]}, {"rect": [273, 434, 551, 712], "points": [0.37543, -0.00446, 0.08391, 0.0, 0.00083, 0.3859, -0.02062, 0.0, -0.09462, -0.00557, 0.3687, 0.0, -142.86267, -240.42854, -49.72191, 1.0, 67.3, 42.0, 69.5, 26.8, 67.3, 45.2, 67.2, 48.9, 66.7, 51.1, 66.2, 60.3, 66.6, 64.3, 66.7, 69.2, 66.6, 74.2, 66.2, 78.7, 38.6, 86.5, 30.9, 14.9, 59.4, 41.0, 59.8, 49.3, 50.7, 45.2, 44.7, 49.2, 53.3, 50.6, 47.8, 52.5, 34.5, 64.2, 7.3, 14.9, 30.0, 56.4, -18.4, 50.3, 37.6, 56.6, 39.0, 56.6, 59.8, 45.3, 52.0, 47.9, 46.4, 51.0, 38.5, 56.6, 41.4, 60.1, 39.9, 56.6, 48.7, 53.4, 53.9, 52.0, 59.9, 51.2, 56.6, 78.3, 57.9, 73.4, 58.5, 68.8, 59.2, 63.8, 59.7, 60.3, 48.6, 59.4, 47.2, 61.1, 45.4, 63.4, 44.0, 66.1, 39.1, 42.0, -29.8, 12.3, 44.5, 58.4, 43.1, 58.9, 61.2, 27.3, 49.7, 26.7, 36.8, 0.6, 24.8, 5.7, 40.0, 70.0, -15.2, -5.1, -1.8, -4.8, 8.0, -2.1, 22.7, -3.2, -13.2, 11.3, 44.1, 19.0, -25.7, 30.6, 5.2, 69.7, 2.4, 77.4, -24.3, 11.9, -5.5, 59.1, 36.5, 92.5, 40.0, 8.9, 39.9, 61.2, -11.0, 26.5, 48.3, 101.7, 25.3, 92.6, 15.2, 86.7, 62.7, 102.5, 69.4, 32.7, 46.5, 37.0, 60.3, 33.6, 15.7, 78.9, 25.8, 85.7, 49.6, 97.5, -8.6, 66.0, 64.4, 98.3, 36.4, 98.0, -21.1, 28.8, 53.8, 59.8, 52.4, 62.6, 51.4, 66.6, 50.5, 70.7, 47.3, 75.0, 43.1, 54.4, 41.4, 53.8, 40.1, 52.9, 33.6, 48.5, 1.4, 31.0, 44.1, 54.9, 0.5, 48.9, 42.3, 80.5, 65.3, 92.1, 65.7, 85.0, 53.8, 84.7, 26.7, 66.5, 37.3, 25.0, 33.5, 74.6, 19.7, 24.2, 30.8, 32.8, 13.7, 36.6, 51.5, 91.5, 19.5, 71.6, 28.6, 79.3, 22.0, 56.8, -8.6, 39.2, 11.1, 57.7, -15.6, 44.5, 25.3, 42.9, -25.7, -4.4, -31.3, -4.8, 86.9, 83.6, 98.5, 14.3, 74.5, 40.7, 73.1, 48.9, 80.6, 43.9, 84.2, 47.9, 77.7, 49.8, 80.5, 51.6, 92.0, 62.3, 116.4, 13.8, 96.2, 54.8, 115.3, 47.2, 86.9, 55.7, 85.1, 55.6, 74.1, 45.2, 79.2, 47.1, 82.7, 49.8, 86.0, 55.7, 84.3, 58.9, 84.2, 55.3, 79.1, 52.5, 76.0, 51.5, 71.8, 51.0, 74.6, 77.7, 74.4, 72.9, 73.9, 68.0, 73.1, 63.3, 71.7, 59.8, 79.0, 58.0, 80.5, 59.8, 82.3, 62.0, 84.0, 64.7, 92.0, 40.6, 123.4, 11.4, 81.1, 57.0, 82.8, 57.9, 76.4, 26.8, 84.2, 25.9, 92.1, 0.1, 102.6, 5.1, 87.9, 68.1, 128.4, -5.6, 119.9, -5.6, 113.5, -2.3, 102.0, -3.2, 127.8, 10.1, 88.0, 18.5, 120.3, 28.5, 107.9, 65.7, 104.7, 72.6, 128.7, 10.5, 114.4, 56.0, 86.6, 89.2, 90.6, 8.4, 85.6, 60.2, 124.6, 24.8, 75.4, 99.7, 90.6, 87.8, 97.0, 81.7, 87.3, 36.0, 77.4, 33.2, 100.3, 74.6, 93.8, 81.4, 77.2, 95.6, 110.2, 62.0, 83.8, 94.3, 125.4, 26.7, 75.9, 59.2, 77.7, 61.7, 79.0, 65.3, 80.0, 69.7, 82.3, 73.6, 82.9, 53.4, 84.7, 52.5, 86.1, 51.6, 95.1, 47.1, 118.2, 29.4, 81.4, 53.9, 115.0, 46.4, 85.0, 78.2, 76.3, 83.3, 97.1, 64.0, 93.0, 24.1, 91.6, 71.8, 107.6, 23.1, 98.5, 31.7, 110.3, 35.0, 77.7, 90.1, 100.7, 68.1, 93.8, 75.9, 102.1, 54.8, 120.9, 37.1, 108.1, 54.8, 120.8, 41.8, 101.5, 41.5, 130.0, -5.0, 124.8, -5.1]}, {"rect": [275, 434, 553, 712], "points": [0.37602, -0.00455, 0.0842, 0.0, 0.00085, 0.38739, -0.02087, 0.0, -0.09517, -0.00471, 0.36995, 0.0, -143.39644, -241.28163, -49.71486, 1.0, 67.4, 42.2, 69.4, 27.0, 67.1, 45.4, 67.0, 49.1, 66.2, 51.1, 66.1, 60.6, 66.2, 64.5, 66.2, 69.2, 66.2, 74.2, 65.8, 79.1, 38.2, 86.9, 30.4, 15.1, 59.3, 41.2, 59.7, 49.3, 50.5, 45.4, 44.5, 49.5, 52.9, 50.6, 47.3, 52.8, 34.1, 64.8, 6.6, 15.1, 29.5, 56.9, -18.9, 50.6, 36.8, 57.0, 38.3, 56.9, 59.3, 45.4, 51.8, 48.2, 46.0, 51.1, 37.8, 57.0, 40.9, 60.3, 39.2, 56.7, 48.3, 53.5, 53.7, 52.1, 59.7, 51.4, 56.1, 78.8, 57.5, 73.7, 58.0, 68.8, 58.8, 64.0, 59.3, 60.6, 47.9, 59.7, 46.5, 61.2, 44.7, 63.5, 43.3, 66.3, 38.7, 42.3, -30.4, 12.7, 43.8, 58.5, 42.4, 59.3, 60.8, 27.5, 49.2, 26.7, 36.4, 0.8, 24.3, 5.9, 39.6, 70.4, -15.7, -4.7, -2.3, -4.6, 7.7, -1.9, 22.4, -3.2, -13.7, 11.8, 43.7, 19.2, -26.3, 31.2, 4.7, 70.2, 1.9, 77.7, -24.8, 12.3, -6.0, 59.7, 36.2, 92.9, 39.6, 9.1, 39.2, 61.6, -11.5, 27.0, 47.9, 102.2, 24.8, 93.3, 14.7, 87.3, 62.5, 102.7, 69.0, 32.7, 46.0, 37.2, 59.8, 33.9, 15.2, 79.5, 25.3, 86.3, 49.2, 97.9, -9.1, 66.6, 63.9, 98.5, 35.9, 98.4, -21.6, 29.3, 53.3, 60.2, 52.0, 62.9, 50.7, 66.8, 49.8, 70.9, 46.9, 75.5, 42.4, 54.7, 40.9, 53.8, 39.6, 53.2, 33.2, 48.7, 1.0, 31.2, 43.7, 55.2, 0.0, 49.2, 41.9, 80.9, 64.9, 92.5, 65.3, 85.5, 53.4, 85.1, 26.3, 67.1, 36.9, 25.2, 33.1, 75.0, 19.3, 24.7, 30.4, 33.1, 13.1, 37.1, 51.1, 92.0, 19.2, 72.1, 28.1, 79.9, 21.3, 57.4, -9.1, 39.5, 10.7, 58.3, -16.1, 45.0, 24.9, 43.2, -26.3, -4.2, -31.9, -4.3, 86.5, 83.8, 98.3, 14.5, 74.4, 40.8, 72.7, 49.2, 80.4, 44.1, 83.7, 48.2, 77.3, 50.1, 80.4, 51.9, 91.8, 62.9, 116.2, 14.0, 96.0, 55.1, 114.9, 47.3, 86.4, 56.0, 84.6, 55.7, 73.9, 45.4, 79.0, 47.3, 82.3, 50.1, 85.5, 56.0, 84.1, 59.2, 83.8, 55.7, 78.7, 52.8, 75.8, 51.6, 71.7, 51.1, 74.4, 78.2, 73.7, 72.8, 73.5, 68.2, 72.7, 63.5, 71.3, 60.2, 78.6, 58.3, 80.1, 60.2, 81.9, 62.2, 83.3, 64.9, 91.8, 40.9, 122.9, 11.4, 80.8, 57.4, 82.3, 58.0, 76.3, 27.0, 84.0, 26.1, 91.9, 0.2, 102.5, 5.3, 87.8, 68.5, 128.2, -5.7, 119.3, -5.7, 112.8, -2.1, 101.4, -3.3, 127.7, 10.3, 87.8, 18.7, 119.9, 28.8, 107.5, 66.0, 104.3, 72.9, 128.3, 10.8, 114.0, 56.0, 86.4, 89.6, 90.4, 8.6, 85.2, 60.3, 124.4, 25.0, 75.0, 99.9, 90.2, 88.2, 96.6, 81.8, 86.9, 36.3, 77.2, 33.4, 100.1, 74.9, 93.3, 81.8, 76.9, 96.0, 109.8, 62.3, 83.6, 94.7, 125.0, 26.9, 75.5, 59.3, 77.2, 62.0, 78.6, 65.4, 79.6, 69.6, 81.9, 74.0, 82.7, 53.7, 84.5, 52.8, 85.9, 51.9, 94.7, 47.3, 118.0, 29.4, 80.9, 54.2, 114.8, 46.7, 84.6, 78.6, 75.9, 83.7, 96.9, 64.3, 92.8, 24.3, 91.4, 72.2, 107.4, 23.3, 98.3, 31.7, 110.2, 35.2, 77.3, 90.5, 100.6, 68.4, 93.7, 76.2, 101.7, 55.1, 120.7, 37.2, 107.9, 55.1, 120.4, 42.1, 101.2, 41.8, 129.7, -4.8, 124.2, -4.9]}, {"rect": [275, 434, 553, 712], "points": [0.37623, -0.00481, 0.08481, 0.0, 0.0009, 0.38858, -0.02011, 0.0, -0.09575, -0.00398, 0.37023, 0.0, -143.4952, -241.95354, -50.64028, 1.0, 67.9, 41.9, 69.8, 26.7, 67.6, 45.2, 67.2, 48.9, 66.7, 51.2, 66.3, 60.7, 66.7, 64.8, 66.7, 69.8, 66.7, 74.6, 66.3, 79.5, 38.6, 87.0, 30.9, 15.1, 59.8, 41.0, 60.1, 49.3, 51.0, 45.2, 44.7, 49.3, 53.3, 50.7, 47.8, 52.6, 34.5, 64.9, 7.0, 15.2, 30.2, 57.1, -18.5, 50.7, 37.2, 57.1, 39.0, 57.0, 59.8, 45.2, 52.0, 47.9, 46.4, 51.1, 38.2, 57.1, 41.3, 60.4, 39.9, 57.0, 48.7, 53.5, 54.2, 52.1, 60.2, 51.3, 56.6, 79.4, 58.0, 74.1, 58.4, 69.4, 59.0, 64.4, 59.8, 60.7, 48.3, 59.8, 47.0, 61.3, 45.1, 63.9, 43.7, 66.7, 39.2, 42.3, -30.0, 12.8, 44.2, 58.5, 42.8, 59.4, 61.5, 27.2, 49.7, 26.7, 36.8, 0.5, 24.6, 5.9, 40.0, 70.8, -15.5, -4.7, -2.1, -4.6, 7.9, -1.9, 22.6, -3.3, -13.3, 11.6, 44.1, 19.0, -25.9, 31.3, 5.4, 70.4, 2.3, 77.9, -24.4, 12.4, -5.6, 59.8, 36.7, 93.1, 40.0, 9.1, 39.6, 61.7, -11.1, 26.8, 48.3, 102.6, 25.3, 93.5, 15.1, 87.5, 62.9, 103.1, 69.5, 32.7, 46.5, 37.2, 60.3, 33.6, 15.6, 79.7, 25.7, 86.5, 49.7, 98.1, -8.5, 66.8, 64.4, 98.9, 36.3, 98.6, -21.2, 29.4, 53.8, 60.3, 52.4, 63.0, 51.1, 67.1, 50.2, 71.3, 47.4, 75.8, 42.8, 54.8, 41.4, 53.9, 40.0, 53.0, 33.9, 48.8, 1.4, 31.3, 44.1, 55.2, 0.5, 49.3, 42.3, 81.1, 65.3, 92.9, 65.8, 85.7, 53.8, 85.5, 26.7, 67.2, 37.6, 25.3, 33.6, 75.1, 19.8, 24.5, 30.8, 33.1, 13.8, 36.9, 51.5, 92.1, 19.7, 72.3, 28.6, 80.0, 22.0, 57.5, -8.7, 39.6, 11.4, 58.4, -15.7, 45.1, 25.4, 43.3, -26.1, -4.2, -31.8, -4.3, 87.0, 84.1, 98.8, 14.2, 74.8, 40.6, 73.2, 49.2, 80.9, 44.1, 84.2, 48.2, 77.7, 50.1, 80.6, 52.0, 92.1, 63.0, 116.7, 13.7, 96.2, 55.2, 115.1, 47.3, 86.6, 56.1, 84.8, 56.0, 74.4, 45.2, 79.5, 47.4, 82.8, 50.1, 85.7, 56.1, 84.3, 59.3, 84.2, 56.0, 79.1, 52.9, 76.3, 51.6, 72.1, 51.1, 74.9, 78.6, 74.1, 73.2, 73.7, 68.5, 73.1, 63.8, 71.8, 60.3, 78.8, 58.4, 80.5, 60.3, 82.4, 62.5, 83.7, 64.9, 92.1, 40.9, 123.3, 11.3, 81.1, 57.5, 82.5, 58.3, 76.7, 26.7, 84.2, 25.8, 92.4, -0.0, 102.9, 5.0, 88.3, 68.6, 128.7, -6.0, 119.8, -6.0, 113.1, -2.4, 101.8, -3.4, 127.9, 10.0, 88.3, 18.4, 120.2, 28.5, 107.7, 65.8, 104.5, 72.7, 128.7, 10.5, 114.2, 56.1, 86.9, 89.7, 90.6, 8.3, 85.6, 60.6, 124.7, 24.7, 75.5, 100.3, 90.7, 88.3, 96.8, 81.9, 87.4, 36.3, 77.6, 33.2, 100.4, 74.9, 93.5, 81.9, 77.3, 96.2, 110.0, 62.1, 83.8, 94.8, 125.2, 26.6, 75.9, 59.4, 77.4, 62.1, 78.8, 65.8, 80.0, 70.0, 82.4, 74.1, 82.9, 53.8, 84.7, 52.9, 86.1, 52.0, 95.2, 47.4, 118.2, 29.3, 81.1, 54.3, 115.0, 46.4, 85.1, 78.7, 76.3, 84.1, 97.2, 64.4, 93.3, 24.3, 91.7, 72.2, 107.6, 23.0, 98.8, 31.7, 110.4, 35.0, 77.8, 90.6, 100.8, 68.5, 93.9, 76.3, 102.1, 55.1, 121.0, 37.1, 108.2, 55.1, 120.6, 41.8, 101.6, 41.8, 130.1, -5.2, 124.7, -5.2]}, {"rect": [276, 435, 554, 713], "points": [0.37601, -0.0054, 0.08532, 0.0, 0.00086, 0.38938, -0.01904, 0.0, -0.09624, -0.00364, 0.36918, 0.0, -143.49493, -242.414, -51.52509, 1.0, 67.7, 41.5, 69.6, 26.2, 67.6, 44.7, 67.2, 48.5, 66.7, 51.0, 66.3, 60.3, 66.4, 64.5, 66.7, 69.3, 66.4, 74.3, 66.3, 79.3, 38.6, 86.7, 31.1, 14.6, 59.8, 40.5, 59.9, 48.9, 50.7, 44.7, 44.6, 48.9, 53.0, 50.2, 47.5, 52.2, 34.7, 64.8, 7.5, 14.7, 30.2, 56.9, -18.9, 50.6, 37.0, 56.7, 38.8, 56.6, 59.8, 44.7, 52.0, 47.5, 46.1, 50.7, 37.9, 56.7, 41.1, 60.2, 39.7, 56.6, 48.5, 53.4, 53.9, 52.0, 59.9, 51.1, 56.5, 79.2, 58.0, 73.8, 58.4, 69.1, 58.9, 64.0, 59.5, 60.3, 48.3, 59.4, 46.9, 61.1, 45.1, 63.6, 43.7, 66.3, 39.4, 41.9, -30.4, 12.5, 44.2, 58.4, 42.8, 59.0, 61.2, 26.7, 49.6, 26.2, 37.0, 0.0, 25.0, 5.4, 40.0, 70.4, -15.4, -5.1, -1.7, -5.1, 8.1, -2.3, 22.8, -3.8, -13.2, 11.4, 44.1, 18.7, -26.3, 30.9, 5.4, 70.0, 2.2, 77.8, -24.5, 12.0, -5.6, 59.7, 36.4, 93.0, 39.9, 8.7, 39.7, 61.3, -10.9, 26.6, 48.3, 102.3, 25.2, 93.4, 14.8, 87.4, 62.7, 102.8, 69.4, 32.2, 46.7, 36.8, 60.2, 33.2, 15.6, 79.5, 25.7, 86.2, 49.6, 98.0, -8.8, 66.7, 64.4, 98.6, 36.3, 98.6, -21.3, 29.0, 53.5, 59.9, 52.4, 62.7, 51.1, 66.8, 50.2, 71.0, 47.3, 75.5, 42.8, 54.4, 41.1, 53.5, 40.0, 52.6, 33.9, 48.6, 1.6, 30.8, 43.9, 54.8, 0.6, 49.2, 42.3, 81.0, 65.3, 92.6, 65.8, 85.6, 53.8, 85.2, 26.9, 67.0, 37.6, 24.8, 33.5, 75.0, 20.0, 24.2, 31.0, 32.6, 14.0, 36.7, 51.5, 92.0, 19.7, 72.1, 28.8, 79.7, 22.0, 57.4, -8.5, 39.5, 11.3, 58.0, -15.8, 44.7, 25.8, 43.1, -26.0, -4.6, -32.2, -4.9, 87.0, 83.5, 98.3, 13.5, 74.6, 40.1, 73.1, 48.8, 80.7, 43.7, 84.2, 47.5, 77.4, 49.7, 80.6, 51.6, 91.8, 62.6, 116.2, 13.0, 96.0, 54.7, 114.8, 46.3, 86.6, 55.7, 84.8, 55.6, 74.1, 44.7, 79.3, 47.0, 82.5, 49.7, 85.7, 55.7, 84.2, 59.0, 84.2, 55.6, 78.8, 52.5, 76.0, 51.5, 71.9, 50.8, 74.7, 78.3, 74.1, 72.9, 73.7, 68.2, 72.9, 63.3, 71.8, 59.9, 78.8, 58.0, 80.5, 59.9, 82.4, 62.2, 83.5, 64.6, 91.8, 40.4, 123.0, 10.4, 81.0, 57.1, 82.5, 57.9, 76.5, 26.2, 83.9, 25.3, 92.1, -0.8, 102.5, 4.2, 88.0, 68.2, 128.2, -6.8, 120.0, -6.8, 113.5, -3.5, 102.1, -4.4, 127.4, 9.0, 88.0, 17.9, 119.8, 27.8, 107.5, 65.1, 104.2, 72.1, 128.2, 9.5, 113.9, 55.4, 86.6, 89.1, 90.4, 7.8, 85.6, 60.2, 124.1, 23.8, 75.4, 100.0, 90.7, 88.0, 96.8, 81.2, 87.1, 35.9, 77.4, 32.7, 100.1, 74.3, 93.5, 81.2, 77.4, 95.8, 109.7, 61.5, 83.8, 94.4, 124.9, 25.9, 75.9, 59.0, 77.4, 61.7, 78.8, 65.4, 79.8, 69.7, 82.4, 73.8, 82.9, 53.4, 84.7, 52.5, 86.1, 51.6, 94.9, 46.9, 117.7, 28.6, 81.1, 53.9, 114.5, 45.7, 84.8, 78.3, 76.1, 83.8, 97.2, 64.0, 93.1, 23.5, 91.7, 71.8, 107.1, 22.5, 98.3, 31.2, 109.9, 34.5, 77.7, 90.3, 100.6, 67.8, 93.7, 75.7, 101.8, 54.4, 120.4, 36.2, 107.9, 54.4, 120.3, 41.1, 101.4, 41.0, 129.6, -6.1, 124.4, -6.1]}, {"rect": [277, 435, 555, 713], "points": [0.37648, -0.00556, 0.08637, 0.0, 0.00113, 0.39004, -0.01916, 0.0, -0.09658, -0.00284, 0.37036, 0.0, -144.10459, -242.70986, -52.16707, 1.0, 67.3, 41.5, 69.3, 26.2, 67.3, 44.8, 66.9, 48.8, 66.4, 51.1, 66.0, 60.4, 66.4, 64.6, 66.5, 69.6, 66.4, 74.7, 66.0, 79.7, 38.3, 87.0, 30.8, 14.4, 59.5, 40.3, 59.5, 48.9, 50.7, 44.8, 44.4, 49.0, 53.0, 50.3, 47.5, 52.3, 34.2, 64.6, 7.2, 14.8, 29.9, 56.7, -19.2, 50.7, 36.9, 56.8, 38.8, 56.5, 59.5, 44.8, 51.7, 47.6, 46.1, 50.8, 37.9, 56.8, 41.1, 60.1, 39.7, 56.5, 48.5, 53.5, 53.9, 52.1, 59.9, 51.2, 56.3, 79.3, 57.7, 74.2, 58.2, 69.2, 58.7, 64.1, 59.5, 60.4, 48.1, 59.5, 46.7, 61.0, 44.9, 63.7, 43.5, 66.4, 39.1, 41.8, -30.5, 12.6, 44.2, 58.3, 42.5, 59.1, 60.9, 26.7, 49.3, 26.2, 36.4, 0.0, 24.4, 5.2, 39.7, 70.5, -15.8, -5.0, -2.0, -5.0, 7.8, -2.3, 22.2, -4.0, -13.5, 11.2, 43.7, 18.5, -26.7, 31.0, 5.1, 70.1, 1.9, 77.9, -24.9, 12.1, -5.9, 59.6, 36.3, 93.1, 39.6, 8.4, 39.7, 61.4, -11.5, 26.4, 48.0, 102.7, 24.9, 93.6, 14.7, 87.6, 62.6, 103.2, 69.1, 32.2, 46.2, 36.8, 59.9, 33.1, 15.3, 79.7, 25.4, 86.5, 49.3, 98.2, -9.1, 66.8, 64.1, 98.7, 36.0, 99.0, -21.7, 29.1, 53.5, 60.0, 52.2, 62.8, 50.8, 66.9, 49.9, 71.4, 47.0, 75.6, 42.8, 54.5, 41.1, 53.6, 39.8, 52.7, 33.6, 48.4, 1.3, 30.9, 43.8, 54.9, 0.1, 49.3, 42.0, 81.1, 65.1, 92.7, 65.8, 85.7, 53.5, 85.3, 26.6, 66.9, 37.3, 24.8, 33.2, 75.1, 19.7, 24.0, 30.5, 32.7, 13.7, 36.5, 51.2, 92.2, 19.3, 72.0, 28.5, 79.8, 21.7, 57.2, -8.8, 39.3, 11.0, 58.1, -16.1, 44.8, 25.3, 42.9, -26.4, -4.5, -32.4, -4.8, 87.0, 83.8, 98.2, 13.4, 74.2, 40.2, 72.8, 48.8, 80.6, 43.5, 83.9, 47.6, 77.4, 49.8, 80.6, 51.6, 92.0, 62.6, 116.1, 12.9, 96.1, 54.7, 114.9, 46.5, 86.6, 55.7, 84.7, 55.4, 73.8, 44.7, 79.2, 47.0, 82.4, 49.7, 85.6, 55.7, 84.0, 59.0, 83.9, 55.4, 78.8, 52.5, 76.0, 51.6, 71.9, 51.1, 74.7, 78.4, 73.9, 73.3, 73.5, 68.6, 72.9, 63.6, 71.5, 60.0, 78.7, 58.1, 80.3, 59.9, 82.1, 62.3, 83.5, 65.0, 92.0, 40.2, 123.1, 10.3, 80.8, 57.1, 82.4, 57.7, 76.5, 26.2, 83.9, 25.3, 91.8, -0.9, 102.6, 4.1, 88.0, 68.2, 128.3, -6.8, 119.8, -6.8, 113.0, -3.5, 101.8, -4.5, 127.4, 9.2, 88.0, 17.6, 119.8, 27.8, 107.5, 65.4, 104.3, 72.3, 128.2, 9.7, 114.0, 55.3, 86.6, 89.4, 90.3, 7.8, 85.4, 60.1, 124.3, 23.9, 75.2, 100.1, 90.6, 88.1, 96.9, 81.5, 87.1, 35.8, 77.1, 32.7, 100.3, 74.6, 93.4, 81.5, 77.3, 95.9, 109.8, 61.7, 83.8, 94.5, 125.0, 25.9, 75.7, 59.0, 77.4, 61.8, 78.8, 65.6, 79.8, 70.1, 82.4, 74.1, 82.6, 53.4, 84.4, 52.5, 86.1, 51.6, 94.9, 46.9, 117.8, 28.5, 81.0, 53.9, 114.6, 45.7, 84.8, 78.4, 76.1, 83.9, 97.1, 64.0, 93.0, 23.5, 91.6, 71.9, 107.2, 22.2, 98.2, 31.0, 110.0, 34.2, 77.5, 90.4, 100.7, 67.8, 93.8, 76.0, 101.8, 54.4, 120.5, 36.4, 108.0, 54.4, 120.4, 41.1, 101.3, 41.0, 129.6, -6.0, 124.4, -5.9]}, {"rect": [278, 436, 556, 714], "points": [0.37692, -0.00574, 0.08784, 0.0, 0.00173, 0.39078, -0.01894, 0.0, -0.09793, -0.00189, 0.3723, 0.0, -145.08506, -243.13682, -53.20006, 1.0, 67.2, 41.1, 69.4, 25.5, 67.2, 44.7, 66.8, 48.4, 66.3, 50.8, 66.2, 60.3, 66.6, 64.4, 66.7, 69.8, 66.6, 74.9, 66.2, 79.6, 38.2, 86.9, 30.4, 14.0, 59.4, 40.2, 59.5, 48.8, 50.6, 44.7, 44.5, 48.8, 52.9, 50.2, 47.4, 52.4, 34.1, 64.5, 6.6, 14.4, 29.5, 56.3, -19.4, 50.6, 37.1, 56.7, 39.0, 56.6, 59.4, 44.7, 51.6, 47.5, 46.0, 50.7, 38.1, 56.6, 41.3, 60.3, 39.8, 56.6, 48.6, 53.4, 53.8, 52.0, 59.8, 51.1, 56.2, 79.2, 57.9, 74.4, 58.4, 69.1, 58.8, 64.0, 59.4, 60.3, 48.2, 59.4, 46.9, 61.1, 45.1, 63.5, 43.6, 66.3, 38.7, 41.2, -31.2, 12.4, 44.1, 58.4, 42.7, 59.0, 60.8, 26.0, 49.2, 25.5, 36.0, -0.4, 24.0, 4.8, 39.6, 70.4, -16.4, -5.4, -2.6, -5.4, 7.4, -2.7, 22.1, -4.4, -14.1, 11.1, 43.4, 18.1, -27.1, 30.9, 5.0, 70.0, 1.8, 77.8, -25.3, 12.0, -6.0, 59.4, 36.0, 93.0, 39.2, 8.0, 39.9, 61.6, -11.9, 26.3, 47.9, 102.6, 24.8, 93.5, 14.3, 87.5, 62.6, 103.1, 69.1, 31.5, 46.0, 36.2, 59.8, 32.4, 15.2, 79.3, 25.3, 86.2, 49.3, 98.1, -9.2, 66.4, 64.3, 98.9, 35.9, 99.0, -22.1, 28.7, 53.4, 59.9, 52.4, 62.6, 51.0, 66.8, 50.1, 71.3, 46.9, 75.5, 42.8, 54.4, 41.3, 53.7, 39.9, 52.8, 33.2, 48.0, 1.0, 30.5, 44.0, 54.8, -0.0, 48.9, 41.9, 81.0, 65.2, 92.9, 65.8, 85.6, 53.4, 85.2, 26.3, 66.5, 36.9, 24.1, 33.1, 74.7, 19.0, 23.6, 30.3, 32.0, 13.4, 36.1, 51.1, 92.1, 19.0, 71.9, 28.2, 79.7, 21.6, 56.8, -9.2, 39.2, 10.7, 57.7, -16.5, 44.6, 25.0, 42.5, -27.0, -4.6, -33.0, -4.7, 86.9, 83.4, 98.3, 13.0, 74.1, 40.0, 72.7, 48.5, 80.5, 43.3, 83.8, 47.4, 77.3, 49.4, 80.5, 51.2, 92.0, 62.2, 116.2, 12.2, 96.1, 54.1, 114.4, 46.1, 86.5, 55.3, 84.7, 55.2, 73.7, 44.3, 79.1, 46.6, 82.4, 49.3, 85.6, 55.3, 84.2, 58.9, 83.8, 55.2, 78.7, 52.1, 75.9, 51.2, 71.8, 50.7, 74.8, 78.3, 74.4, 73.5, 73.9, 68.5, 73.0, 63.5, 71.7, 59.8, 78.7, 58.0, 80.5, 59.8, 82.3, 62.1, 83.7, 64.9, 92.0, 39.7, 122.4, 10.1, 80.9, 56.7, 82.4, 57.5, 76.4, 25.5, 84.0, 24.6, 91.9, -1.3, 102.5, 3.4, 87.9, 68.1, 127.9, -7.3, 119.9, -7.2, 113.4, -4.0, 102.0, -4.9, 127.3, 8.5, 87.9, 17.1, 119.1, 27.6, 107.2, 64.9, 103.9, 72.2, 127.8, 9.3, 113.6, 54.9, 86.5, 89.3, 90.2, 7.1, 85.5, 59.9, 124.1, 23.2, 75.3, 100.2, 90.6, 88.0, 96.6, 81.2, 87.3, 35.1, 77.2, 32.0, 100.2, 74.2, 93.3, 81.2, 77.3, 95.8, 109.4, 61.3, 83.7, 94.4, 124.6, 25.4, 75.9, 58.9, 77.3, 61.6, 79.0, 65.7, 80.0, 70.2, 82.4, 73.7, 82.8, 53.0, 84.3, 52.1, 86.0, 51.2, 94.8, 46.2, 117.7, 27.8, 81.0, 53.5, 114.5, 45.3, 85.0, 78.2, 76.3, 83.8, 97.0, 63.6, 92.9, 22.8, 91.5, 71.5, 107.1, 21.8, 98.3, 30.5, 109.9, 33.8, 77.6, 90.3, 100.7, 67.4, 93.8, 75.6, 101.7, 53.9, 120.4, 35.9, 107.7, 54.0, 120.0, 40.6, 101.2, 40.3, 129.2, -6.4, 123.7, -6.4]}, {"rect": [279, 436, 557, 714], "points": [0.37667, -0.00608, 0.08913, 0.0, 0.00213, 0.39114, -0.0187, 0.0, -0.09911, -0.00159, 0.37281, 0.0, -145.61394, -243.10264, -54.17367, 1.0, 67.1, 41.5, 69.3, 25.8, 67.1, 45.0, 66.7, 48.8, 66.2, 51.1, 66.2, 60.4, 66.6, 64.5, 66.6, 69.9, 66.6, 75.1, 66.1, 80.0, 38.1, 87.1, 30.3, 14.3, 59.2, 40.5, 59.6, 49.2, 50.5, 45.0, 44.4, 49.2, 52.8, 50.6, 47.3, 52.8, 33.9, 64.8, 6.4, 14.7, 29.3, 56.6, -19.5, 50.7, 37.1, 57.0, 38.9, 56.9, 59.3, 45.0, 51.8, 47.9, 45.9, 51.0, 38.0, 57.0, 41.2, 60.6, 39.5, 56.9, 48.6, 53.8, 53.7, 52.4, 59.7, 51.4, 56.1, 79.5, 57.9, 74.6, 58.3, 69.4, 58.8, 64.4, 59.6, 60.4, 48.2, 59.7, 46.8, 61.3, 45.3, 63.9, 43.6, 66.7, 38.5, 41.4, -31.4, 12.8, 44.1, 58.5, 42.7, 59.4, 60.7, 26.2, 49.1, 25.8, 35.9, -0.4, 23.9, 5.0, 39.4, 70.5, -16.6, -5.1, -2.7, -5.1, 7.1, -2.4, 21.7, -4.1, -14.3, 11.4, 43.2, 18.4, -27.3, 31.2, 4.6, 70.4, 1.7, 78.2, -25.5, 12.3, -6.2, 59.8, 35.9, 93.5, 39.1, 8.3, 39.8, 61.7, -12.0, 26.6, 47.8, 103.0, 24.7, 93.9, 14.2, 87.9, 62.5, 103.5, 68.9, 31.8, 45.9, 36.5, 59.7, 32.7, 15.1, 79.7, 25.2, 86.6, 49.2, 98.5, -9.4, 66.8, 64.0, 99.0, 35.8, 99.3, -22.3, 29.0, 53.6, 60.2, 52.3, 63.0, 51.0, 67.1, 50.1, 71.7, 46.8, 75.9, 42.7, 54.7, 41.2, 53.9, 39.8, 53.0, 33.0, 48.3, 0.8, 30.8, 44.0, 55.2, -0.2, 49.2, 41.8, 81.4, 65.2, 93.0, 65.7, 86.0, 53.3, 85.5, 26.2, 66.8, 36.7, 24.4, 33.0, 75.0, 18.9, 23.9, 30.0, 32.3, 13.2, 36.4, 51.0, 92.5, 18.8, 72.2, 28.0, 80.0, 21.5, 57.1, -9.3, 39.5, 10.5, 58.0, -16.7, 44.8, 24.8, 42.8, -27.2, -4.3, -33.2, -4.3, 86.8, 83.8, 98.0, 13.0, 74.0, 40.1, 72.7, 48.8, 80.4, 43.4, 83.7, 47.4, 77.2, 49.7, 80.4, 51.5, 91.9, 62.2, 115.6, 12.4, 95.7, 54.3, 113.7, 46.5, 86.4, 55.3, 84.6, 55.3, 73.6, 44.7, 79.0, 46.9, 82.3, 49.4, 85.5, 55.3, 84.1, 58.9, 83.7, 55.3, 78.6, 52.4, 75.8, 51.5, 71.7, 51.1, 74.5, 78.6, 74.4, 74.0, 73.9, 68.7, 73.0, 63.6, 71.7, 59.9, 78.6, 58.1, 80.4, 59.8, 82.2, 62.2, 83.6, 65.3, 91.9, 39.7, 121.6, 10.2, 80.9, 57.0, 82.3, 57.6, 76.3, 25.8, 83.7, 24.9, 91.6, -1.3, 102.2, 3.7, 87.8, 68.2, 127.4, -7.3, 119.6, -7.0, 113.2, -3.7, 101.7, -4.7, 126.6, 8.7, 87.7, 17.2, 118.4, 27.7, 106.7, 65.0, 103.5, 72.3, 127.1, 9.3, 113.2, 55.2, 86.4, 89.4, 90.1, 7.4, 85.5, 60.2, 123.7, 23.5, 75.0, 100.4, 90.2, 88.3, 96.2, 81.5, 86.9, 35.2, 77.1, 32.2, 99.8, 74.5, 93.0, 81.5, 77.2, 96.2, 108.7, 61.6, 83.6, 94.8, 123.9, 25.7, 75.8, 59.0, 77.2, 61.7, 79.0, 65.9, 80.0, 70.4, 82.3, 74.1, 82.7, 53.1, 84.2, 52.4, 86.0, 51.2, 94.7, 46.5, 117.3, 28.1, 80.9, 53.8, 114.1, 45.6, 84.6, 78.4, 76.2, 84.2, 96.6, 63.6, 92.8, 23.0, 91.4, 71.8, 106.8, 22.1, 98.0, 30.5, 109.5, 34.0, 77.3, 90.6, 100.3, 67.7, 93.4, 75.9, 101.6, 54.0, 119.7, 36.0, 107.6, 54.3, 119.3, 40.9, 100.8, 40.5, 128.5, -6.4, 123.0, -6.1]}, {"rect": [279, 436, 557, 714], "points": [0.37641, -0.00641, 0.09017, 0.0, 0.00232, 0.39147, -0.01789, 0.0, -0.10025, -0.0015, 0.37349, 0.0, -145.86284, -243.09114, -55.39337, 1.0, 67.3, 41.9, 69.2, 25.8, 67.3, 45.2, 66.8, 48.9, 66.4, 51.2, 66.3, 60.7, 66.8, 64.9, 66.8, 70.0, 66.8, 75.5, 66.0, 80.1, 38.2, 87.5, 30.1, 14.6, 59.2, 40.9, 59.5, 49.3, 50.4, 45.2, 44.4, 49.6, 53.0, 50.7, 47.5, 53.0, 33.8, 64.9, 6.2, 14.7, 29.2, 56.7, -19.7, 51.1, 37.0, 57.4, 38.8, 57.0, 59.5, 45.2, 51.7, 48.3, 46.1, 51.1, 37.9, 57.1, 41.1, 60.7, 39.7, 57.0, 48.5, 53.9, 53.6, 52.5, 59.9, 51.3, 56.2, 79.6, 58.0, 75.0, 58.5, 69.5, 59.0, 64.5, 59.5, 60.7, 48.3, 59.8, 47.0, 61.6, 45.2, 64.0, 43.8, 66.8, 38.4, 41.5, -31.4, 12.9, 44.2, 58.8, 42.8, 59.7, 60.8, 26.3, 49.0, 25.8, 36.0, -0.1, 23.7, 5.1, 39.3, 70.9, -16.5, -5.1, -2.4, -4.7, 7.6, -2.2, 22.0, -3.8, -14.2, 11.5, 43.4, 18.5, -27.3, 31.4, 4.6, 70.5, 1.8, 78.4, -25.7, 12.5, -6.3, 59.9, 36.0, 93.8, 39.2, 8.3, 39.7, 62.1, -12.0, 26.8, 48.0, 103.2, 24.9, 94.0, 14.3, 88.0, 62.6, 103.6, 69.1, 31.8, 45.8, 36.8, 59.9, 32.8, 15.2, 80.1, 25.0, 87.0, 49.3, 98.6, -9.3, 67.2, 64.1, 99.4, 35.9, 99.5, -22.5, 29.4, 53.5, 60.3, 52.5, 63.1, 51.2, 67.2, 50.2, 71.9, 46.7, 76.0, 42.8, 55.1, 41.1, 54.2, 39.7, 53.3, 32.9, 48.4, 0.7, 30.9, 43.9, 55.6, -0.3, 49.3, 41.9, 81.5, 65.1, 93.4, 65.6, 86.1, 53.5, 85.7, 26.3, 67.2, 36.6, 24.5, 32.9, 75.2, 19.0, 24.0, 30.1, 32.6, 13.1, 36.7, 51.1, 92.6, 19.0, 72.3, 28.2, 80.2, 21.4, 57.2, -9.5, 39.6, 10.7, 58.1, -16.6, 45.1, 24.9, 42.9, -27.2, -4.1, -33.2, -4.2, 86.7, 83.9, 98.1, 13.3, 74.2, 40.5, 72.8, 48.9, 80.3, 43.7, 83.8, 47.5, 77.4, 49.8, 80.5, 51.6, 91.8, 62.3, 115.6, 12.5, 95.8, 54.4, 113.5, 46.5, 86.5, 55.6, 84.8, 55.3, 73.7, 44.8, 78.9, 47.0, 82.4, 49.7, 85.7, 55.6, 84.2, 59.0, 83.9, 55.3, 78.8, 52.5, 75.9, 51.6, 71.9, 51.2, 74.6, 78.7, 74.5, 74.1, 74.1, 69.0, 72.9, 63.9, 71.9, 60.2, 78.8, 58.3, 80.5, 59.9, 82.4, 62.5, 83.8, 65.4, 91.8, 40.0, 121.3, 10.5, 81.0, 57.1, 82.5, 57.9, 76.4, 25.9, 83.8, 24.9, 91.6, -1.0, 102.2, 3.7, 87.9, 68.3, 127.2, -7.0, 119.4, -6.9, 113.1, -3.7, 101.8, -4.6, 126.6, 8.8, 87.6, 17.4, 118.1, 28.0, 106.6, 65.3, 103.3, 72.4, 126.8, 9.6, 113.0, 55.2, 86.5, 89.7, 90.2, 7.4, 85.6, 60.3, 123.5, 23.5, 75.1, 100.8, 90.3, 88.4, 96.3, 81.9, 87.0, 35.5, 77.0, 32.3, 99.7, 74.6, 93.1, 81.9, 77.1, 96.6, 108.7, 61.7, 83.5, 94.9, 123.6, 25.8, 75.9, 59.3, 77.4, 62.0, 79.2, 66.2, 80.1, 70.5, 82.4, 74.1, 82.8, 53.4, 84.3, 52.5, 86.1, 51.5, 94.8, 46.6, 117.4, 28.1, 81.0, 53.9, 113.9, 45.7, 84.8, 78.7, 76.1, 84.2, 96.7, 63.7, 92.7, 23.1, 91.3, 71.9, 106.9, 22.1, 98.1, 30.8, 109.6, 34.1, 77.4, 90.8, 100.4, 68.0, 93.5, 76.0, 101.5, 54.3, 119.8, 36.0, 107.4, 54.4, 119.3, 41.0, 100.9, 40.6, 128.2, -6.1, 122.7, -6.0]}, {"rect": [280, 437, 558, 715], "points": [0.37618, -0.007, 0.09149, 0.0, 0.00273, 0.39182, -0.01674, 0.0, -0.10123, -0.00174, 0.37338, 0.0, -146.34037, -243.17578, -57.03549, 1.0, 67.2, 41.8, 69.1, 25.7, 67.1, 45.0, 66.7, 49.0, 66.3, 51.3, 66.2, 60.2, 66.7, 64.7, 66.7, 69.9, 66.7, 75.3, 66.0, 79.9, 37.9, 87.3, 30.0, 14.3, 59.3, 40.8, 59.4, 49.2, 50.6, 45.0, 44.2, 49.2, 52.9, 50.8, 47.4, 52.8, 33.7, 64.8, 6.3, 14.4, 29.1, 56.5, -20.1, 51.0, 36.9, 56.8, 38.7, 56.7, 59.4, 45.0, 51.6, 48.2, 45.7, 51.0, 37.8, 56.7, 41.0, 60.3, 39.6, 56.7, 48.4, 53.8, 53.5, 52.4, 59.8, 51.4, 55.9, 79.4, 57.9, 74.9, 58.5, 69.4, 58.9, 64.3, 59.4, 60.2, 48.0, 59.4, 46.7, 61.2, 45.1, 63.6, 43.7, 66.7, 38.3, 41.4, -32.0, 12.8, 43.9, 58.4, 42.5, 59.3, 60.8, 26.1, 48.9, 25.7, 35.8, -0.5, 23.8, 5.0, 39.3, 70.7, -16.7, -5.4, -2.8, -5.1, 7.3, -2.4, 21.7, -4.1, -14.4, 11.2, 43.3, 18.3, -27.9, 31.3, 4.3, 70.4, 1.4, 78.5, -26.1, 12.4, -6.5, 59.8, 36.0, 93.7, 39.1, 8.2, 39.6, 61.7, -12.3, 26.6, 48.0, 103.0, 24.6, 94.1, 14.2, 87.9, 62.3, 103.4, 68.8, 31.6, 45.7, 36.7, 59.6, 32.9, 14.9, 80.0, 25.0, 86.9, 49.3, 98.7, -9.9, 67.1, 64.0, 99.2, 35.6, 99.3, -22.9, 29.1, 53.4, 59.8, 52.1, 62.9, 51.1, 67.1, 50.2, 71.7, 46.6, 75.8, 42.5, 54.7, 41.0, 53.9, 39.6, 52.9, 32.8, 48.3, 0.5, 30.8, 43.8, 55.2, -0.5, 49.2, 41.6, 81.3, 65.0, 93.2, 65.5, 85.9, 53.4, 85.5, 26.0, 67.1, 36.5, 24.3, 32.8, 75.2, 18.9, 23.9, 30.0, 32.3, 12.9, 36.4, 50.8, 92.4, 18.9, 72.2, 28.1, 80.0, 21.3, 57.0, -9.6, 39.5, 10.6, 58.0, -16.9, 45.0, 24.8, 42.8, -27.6, -4.5, -33.6, -4.6, 86.6, 83.9, 97.7, 13.1, 74.0, 40.3, 72.7, 49.0, 80.1, 43.6, 83.7, 47.3, 77.3, 49.9, 80.2, 51.4, 91.6, 62.3, 115.2, 12.2, 95.4, 54.2, 113.3, 46.5, 86.2, 55.2, 84.7, 55.1, 73.6, 44.9, 78.8, 46.9, 82.0, 49.6, 85.3, 55.2, 83.9, 58.7, 83.8, 55.1, 78.7, 52.4, 75.6, 51.4, 71.7, 51.3, 74.3, 78.5, 74.2, 74.0, 73.7, 68.8, 72.8, 63.5, 71.7, 59.8, 78.7, 57.9, 80.2, 59.7, 82.0, 62.1, 83.4, 65.1, 91.6, 39.9, 121.0, 10.3, 80.6, 56.6, 82.4, 57.5, 76.1, 26.0, 83.5, 24.7, 91.3, -1.5, 101.8, 3.5, 87.6, 68.3, 126.9, -7.5, 119.3, -7.2, 113.2, -3.9, 101.8, -4.8, 126.2, 8.5, 87.5, 17.2, 117.8, 27.8, 106.4, 65.1, 103.2, 72.4, 126.6, 9.3, 112.8, 55.0, 86.2, 89.5, 89.8, 7.2, 85.2, 60.1, 123.3, 23.3, 74.8, 100.6, 89.9, 88.5, 95.9, 81.7, 86.6, 35.3, 76.9, 32.4, 99.5, 74.4, 93.0, 81.7, 77.0, 96.4, 108.3, 61.7, 83.4, 95.0, 123.4, 25.5, 75.6, 58.9, 77.3, 61.6, 78.8, 65.8, 80.0, 70.3, 82.0, 73.9, 82.5, 53.2, 84.2, 52.3, 85.7, 51.3, 94.5, 46.4, 117.0, 27.9, 80.7, 53.7, 113.7, 45.7, 84.4, 78.5, 76.0, 84.0, 96.4, 63.7, 92.5, 23.2, 91.2, 71.6, 106.8, 21.9, 97.7, 30.6, 109.2, 33.9, 77.4, 90.8, 100.0, 67.9, 93.2, 75.7, 101.3, 54.1, 119.3, 36.0, 107.3, 54.4, 118.9, 40.7, 100.8, 40.6, 127.9, -6.6, 122.3, -6.3]}, {"rect": [281, 437, 559, 715], "points": [0.37611, -0.0083, 0.09253, 0.0, 0.00347, 0.39176, -0.01557, 0.0, -0.10209, -0.00204, 0.37334, 0.0, -147.1075, -242.57317, -58.5611, 1.0, 66.9, 41.8, 69.1, 25.7, 66.6, 45.1, 66.5, 48.8, 66.0, 51.2, 65.7, 60.2, 66.2, 64.4, 66.5, 69.8, 66.2, 75.3, 66.0, 79.6, 37.9, 87.4, 29.9, 14.4, 58.8, 40.9, 59.2, 49.2, 50.3, 45.1, 44.0, 49.3, 52.6, 50.7, 47.1, 52.9, 33.7, 64.6, 6.0, 14.7, 29.1, 56.6, -20.3, 51.2, 36.6, 57.0, 38.4, 56.7, 59.1, 45.1, 51.3, 48.2, 45.7, 51.1, 37.5, 57.0, 40.7, 60.4, 39.3, 56.7, 48.1, 53.8, 53.2, 52.4, 59.2, 51.4, 56.0, 79.2, 57.4, 74.9, 58.2, 69.4, 58.6, 64.0, 59.1, 60.2, 47.7, 59.4, 46.6, 61.2, 44.8, 63.6, 43.5, 66.7, 38.3, 41.5, -32.2, 13.0, 43.8, 58.5, 42.4, 59.4, 60.5, 26.2, 48.8, 25.8, 35.5, -0.5, 23.5, 5.1, 39.3, 70.5, -17.1, -5.1, -2.9, -5.0, 6.9, -2.3, 21.5, -3.8, -14.7, 11.5, 43.2, 18.4, -28.1, 31.4, 4.2, 70.5, 1.1, 78.7, -26.3, 12.5, -6.8, 59.9, 36.0, 93.6, 38.7, 8.2, 39.3, 61.8, -12.4, 26.8, 48.0, 103.1, 24.5, 94.0, 14.0, 88.0, 62.3, 103.5, 68.7, 31.7, 45.7, 36.8, 59.5, 32.7, 14.8, 80.1, 24.9, 87.0, 49.1, 98.5, -10.0, 67.2, 63.8, 98.9, 35.6, 99.4, -23.0, 29.5, 53.1, 59.9, 51.8, 63.0, 50.8, 67.1, 49.9, 71.8, 46.6, 75.8, 42.4, 54.8, 40.7, 53.9, 39.3, 53.0, 32.8, 48.4, 0.5, 30.9, 43.5, 55.2, -0.8, 49.4, 41.6, 81.1, 65.0, 93.0, 65.5, 85.6, 53.2, 85.5, 25.9, 67.2, 36.4, 24.5, 32.8, 75.1, 18.8, 24.0, 29.9, 32.6, 12.9, 36.8, 50.8, 92.4, 18.6, 72.3, 28.1, 80.1, 21.2, 57.2, -9.7, 39.7, 10.3, 58.4, -17.1, 45.2, 24.5, 42.9, -27.7, -4.1, -34.1, -4.5, 86.3, 83.7, 97.3, 12.8, 73.5, 40.4, 72.4, 48.8, 79.8, 43.6, 83.2, 47.3, 76.7, 49.7, 79.9, 51.4, 91.3, 62.1, 114.8, 12.2, 95.1, 54.2, 112.9, 46.0, 85.9, 55.2, 84.4, 55.2, 73.3, 44.9, 78.4, 46.9, 81.7, 49.6, 85.3, 55.2, 83.5, 58.5, 83.5, 55.2, 78.2, 52.4, 75.3, 51.5, 71.2, 51.1, 74.3, 78.2, 73.9, 73.9, 73.4, 68.5, 72.5, 63.4, 71.2, 59.7, 78.2, 57.6, 79.9, 59.4, 81.7, 62.0, 83.2, 64.9, 91.3, 39.9, 120.3, 9.9, 80.3, 56.6, 82.1, 57.5, 76.0, 25.8, 83.4, 24.7, 91.1, -1.5, 101.7, 3.5, 87.3, 68.0, 126.3, -7.6, 119.2, -7.5, 113.2, -4.2, 101.7, -4.8, 125.7, 8.2, 87.1, 17.0, 117.5, 27.4, 106.1, 64.9, 102.9, 72.2, 126.2, 9.0, 112.5, 54.7, 85.9, 89.3, 89.4, 7.2, 84.9, 59.9, 122.7, 23.2, 74.8, 100.3, 89.9, 88.0, 95.9, 81.4, 86.3, 35.3, 76.6, 32.2, 99.2, 74.1, 92.7, 81.4, 76.7, 96.2, 107.9, 61.2, 83.2, 94.8, 122.9, 25.1, 75.2, 58.8, 77.0, 61.6, 78.5, 65.7, 79.5, 70.3, 81.7, 73.6, 82.2, 53.0, 84.0, 52.4, 85.4, 51.1, 94.1, 46.4, 116.6, 27.8, 80.7, 53.5, 113.4, 45.4, 84.4, 78.2, 75.7, 83.8, 96.3, 63.4, 92.2, 22.9, 90.9, 71.6, 106.4, 21.9, 97.6, 30.3, 108.9, 33.8, 77.1, 90.6, 99.7, 67.6, 93.1, 75.5, 101.0, 53.8, 118.9, 35.7, 107.0, 54.1, 118.5, 40.4, 100.5, 40.4, 127.2, -7.0, 121.6, -6.7]}, {"rect": [281, 437, 559, 715], "points": [0.37649, -0.00983, 0.0936, 0.0, 0.00515, 0.3916, -0.01515, 0.0, -0.10321, -0.00214, 0.37382, 0.0, -148.56697, -241.77447, -59.6224, 1.0, 67.5, 41.9, 69.4, 25.7, 67.4, 45.1, 67.1, 48.9, 66.6, 51.2, 66.5, 59.9, 67.0, 64.2, 67.1, 69.6, 67.0, 74.8, 66.7, 79.3, 38.6, 87.2, 30.0, 14.6, 59.6, 41.0, 60.0, 49.3, 50.9, 45.1, 44.8, 49.3, 53.3, 50.7, 47.7, 52.9, 34.4, 64.9, 6.2, 14.8, 29.8, 56.7, -20.2, 51.5, 37.2, 57.1, 39.0, 57.0, 59.7, 45.2, 52.2, 48.0, 46.3, 51.1, 38.1, 57.1, 41.3, 60.6, 39.9, 57.0, 48.7, 53.9, 54.0, 52.2, 60.1, 51.3, 56.9, 78.9, 58.3, 74.6, 58.8, 69.2, 59.3, 64.0, 59.7, 59.9, 48.3, 59.4, 47.3, 61.2, 45.4, 63.9, 44.1, 66.7, 39.0, 41.8, -32.2, 13.3, 44.5, 58.5, 42.8, 59.4, 61.1, 26.2, 49.2, 25.8, 35.6, -0.4, 23.6, 5.1, 40.0, 70.6, -17.2, -4.7, -3.3, -4.7, 6.8, -1.9, 21.4, -3.7, -14.6, 11.9, 43.3, 18.4, -28.0, 31.8, 4.7, 70.8, 1.5, 78.8, -26.2, 12.8, -6.4, 60.3, 36.5, 93.8, 39.1, 8.3, 39.9, 62.0, -12.3, 27.1, 48.7, 103.1, 25.0, 94.3, 14.4, 88.3, 63.0, 103.2, 69.4, 31.4, 46.3, 36.8, 60.1, 32.8, 15.3, 80.2, 25.4, 87.0, 50.0, 98.5, -9.7, 67.3, 64.8, 98.7, 36.3, 99.4, -22.9, 29.8, 53.7, 59.8, 52.7, 62.7, 51.4, 66.9, 50.5, 71.8, 47.3, 75.6, 42.8, 54.8, 41.3, 54.2, 39.9, 53.3, 33.5, 48.7, 0.9, 31.3, 44.1, 55.3, -0.4, 49.7, 42.4, 81.1, 65.7, 92.7, 66.2, 85.3, 54.2, 85.2, 26.6, 67.3, 36.8, 24.8, 33.5, 75.1, 19.0, 24.3, 30.3, 32.6, 13.0, 36.9, 51.6, 92.2, 19.3, 72.6, 28.6, 80.2, 21.6, 57.5, -9.5, 40.0, 10.7, 58.5, -16.9, 45.6, 25.0, 43.2, -27.9, -3.8, -34.3, -4.2, 87.0, 83.4, 97.6, 12.5, 74.3, 40.1, 73.0, 48.8, 80.4, 43.4, 84.0, 47.3, 77.6, 49.7, 80.4, 51.2, 92.0, 61.8, 115.1, 11.6, 95.7, 53.9, 113.0, 45.6, 86.5, 55.2, 85.0, 55.1, 73.9, 44.7, 79.1, 46.9, 82.3, 49.3, 85.9, 55.2, 84.1, 58.4, 84.1, 55.1, 79.0, 52.2, 75.9, 51.2, 72.0, 50.8, 75.0, 77.9, 74.5, 73.4, 74.0, 68.2, 73.1, 63.1, 72.0, 59.4, 79.0, 57.6, 80.4, 59.3, 82.3, 61.7, 84.0, 64.5, 91.9, 39.6, 120.3, 9.3, 80.9, 56.5, 82.7, 57.4, 76.4, 25.8, 84.1, 24.5, 91.2, -1.8, 101.8, 3.2, 87.9, 67.7, 126.3, -8.2, 119.2, -7.9, 113.2, -4.6, 101.7, -5.1, 125.8, 7.8, 87.4, 16.7, 117.6, 26.8, 106.8, 64.5, 103.6, 71.8, 126.2, 8.4, 112.9, 54.4, 86.8, 89.0, 89.8, 6.9, 85.5, 59.8, 123.0, 22.6, 75.5, 100.0, 90.4, 87.9, 96.3, 81.1, 86.9, 35.0, 77.2, 32.2, 99.9, 73.7, 93.4, 81.1, 77.7, 95.9, 108.3, 60.8, 84.1, 94.5, 123.0, 24.5, 75.8, 58.5, 77.7, 61.3, 79.1, 65.4, 80.4, 70.0, 82.4, 73.3, 82.7, 53.0, 84.6, 52.1, 86.0, 51.0, 94.8, 46.1, 117.0, 27.3, 81.3, 53.4, 113.7, 44.8, 85.1, 77.9, 76.4, 83.4, 96.7, 63.1, 92.5, 22.6, 91.5, 71.1, 106.7, 21.3, 98.0, 30.0, 109.5, 33.3, 77.8, 90.0, 100.3, 67.3, 93.5, 75.2, 101.7, 53.5, 119.3, 35.1, 107.4, 53.6, 118.8, 40.1, 100.9, 40.1, 127.2, -7.4, 121.4, -7.3]}, {"rect": [282, 437, 560, 715], "points": [0.3766, -0.0113, 0.09334, 0.0, 0.006, 0.39164, -0.01444, 0.0, -0.1027, -0.00251, 0.37304, 0.0, -149.20251, -241.17272, -59.8738, 1.0, 67.0, 41.9, 69.2, 25.7, 67.0, 45.1, 66.8, 49.1, 66.4, 51.5, 66.1, 59.8, 66.5, 64.3, 66.8, 69.4, 66.8, 74.9, 66.7, 79.2, 38.9, 87.4, 30.0, 14.7, 59.1, 41.0, 59.5, 49.3, 50.4, 45.1, 44.3, 49.3, 53.0, 50.9, 47.5, 52.9, 34.5, 64.9, 6.3, 15.1, 29.9, 57.0, -20.2, 51.6, 37.2, 57.1, 38.7, 57.0, 59.2, 45.5, 51.7, 48.3, 46.1, 51.1, 37.8, 57.1, 41.0, 60.6, 39.7, 57.0, 48.4, 53.9, 53.6, 52.4, 59.6, 51.5, 57.0, 79.1, 58.1, 74.5, 58.6, 69.3, 59.0, 63.9, 59.5, 59.9, 48.3, 59.4, 47.0, 61.2, 45.2, 63.9, 43.9, 66.7, 39.0, 41.9, -32.3, 13.4, 44.2, 58.5, 42.8, 59.4, 60.8, 26.2, 48.9, 26.1, 35.4, -0.4, 23.5, 5.4, 40.0, 70.8, -17.1, -4.6, -3.0, -4.6, 7.1, -1.9, 21.5, -3.7, -14.4, 12.0, 43.3, 18.4, -28.1, 32.1, 4.9, 70.9, 1.7, 79.1, -26.3, 12.9, -6.4, 60.6, 36.7, 93.9, 38.8, 8.3, 39.7, 62.0, -12.1, 27.2, 48.8, 102.8, 25.2, 94.3, 14.7, 88.4, 63.1, 103.1, 69.1, 31.6, 46.1, 36.8, 59.9, 33.0, 15.5, 80.5, 25.7, 87.0, 50.1, 98.5, -9.7, 67.6, 64.9, 98.6, 36.3, 99.4, -22.7, 30.0, 53.5, 59.8, 52.2, 62.9, 51.2, 67.1, 50.3, 71.7, 47.4, 75.5, 42.7, 54.8, 41.0, 54.2, 39.7, 53.3, 33.6, 48.8, 0.8, 31.6, 43.8, 55.3, -0.2, 50.1, 42.7, 81.0, 65.8, 92.6, 66.3, 85.2, 54.3, 85.2, 26.7, 67.5, 36.8, 24.8, 33.6, 75.4, 19.2, 24.4, 30.3, 32.7, 13.2, 37.2, 51.9, 92.1, 19.3, 72.7, 28.8, 80.5, 21.6, 57.8, -9.4, 40.4, 10.9, 58.8, -17.0, 45.9, 25.2, 43.2, -27.8, -3.6, -34.2, -4.1, 87.0, 83.3, 97.3, 12.4, 73.9, 40.1, 72.6, 48.8, 80.2, 43.3, 83.6, 47.1, 77.1, 49.7, 80.2, 51.1, 91.8, 61.7, 114.8, 11.2, 95.8, 53.8, 113.2, 45.2, 86.4, 54.9, 84.8, 54.9, 73.5, 44.7, 78.8, 46.9, 82.0, 49.3, 85.6, 54.9, 83.9, 58.1, 83.9, 54.9, 78.8, 52.3, 75.6, 51.4, 71.6, 51.1, 75.0, 77.8, 74.2, 73.5, 73.7, 68.1, 72.8, 63.0, 71.6, 59.3, 78.8, 57.5, 80.2, 59.0, 82.0, 61.6, 83.7, 64.4, 91.7, 39.5, 120.3, 8.6, 80.6, 56.3, 82.5, 57.1, 76.1, 25.7, 83.8, 24.4, 90.8, -1.9, 101.5, 2.9, 87.9, 67.6, 126.0, -8.6, 119.9, -8.5, 113.9, -4.9, 102.4, -5.4, 125.5, 7.4, 87.2, 16.6, 117.5, 26.4, 106.8, 64.4, 103.6, 71.5, 125.9, 8.0, 112.9, 54.0, 86.7, 88.9, 89.5, 6.6, 85.2, 59.5, 122.7, 22.2, 75.6, 99.9, 90.6, 87.6, 96.6, 81.0, 86.7, 35.0, 77.0, 32.2, 99.9, 73.6, 93.5, 81.0, 77.8, 95.8, 108.6, 60.5, 84.2, 94.4, 122.7, 24.1, 75.6, 58.4, 77.4, 61.2, 78.8, 65.3, 80.1, 69.9, 82.5, 73.2, 82.5, 52.9, 84.3, 52.1, 85.7, 50.8, 94.6, 46.0, 116.7, 27.2, 81.1, 53.4, 113.5, 44.7, 84.9, 77.8, 76.4, 83.3, 96.8, 63.0, 92.2, 22.5, 91.3, 70.9, 106.2, 21.2, 97.7, 30.0, 109.2, 33.2, 77.9, 90.1, 100.4, 67.2, 93.6, 75.1, 101.5, 53.4, 119.0, 34.7, 107.4, 53.4, 118.8, 39.7, 100.9, 40.0, 126.9, -8.0, 121.3, -8.0]}, {"rect": [283, 437, 561, 715], "points": [0.37725, -0.01353, 0.09299, 0.0, 0.0073, 0.39175, -0.01254, 0.0, -0.10217, -0.00239, 0.37328, 0.0, -150.37892, -240.22181, -60.7798, 1.0, 67.2, 41.9, 69.1, 25.3, 67.2, 45.1, 66.8, 48.8, 66.3, 51.6, 66.3, 59.9, 66.8, 64.0, 66.8, 69.1, 66.8, 74.6, 66.8, 79.2, 38.7, 87.5, 29.9, 14.7, 59.4, 41.0, 59.4, 49.3, 50.6, 45.1, 44.2, 49.3, 52.9, 50.6, 47.4, 52.9, 34.5, 64.9, 6.0, 15.2, 29.9, 57.1, -20.3, 52.0, 36.8, 57.1, 38.7, 57.1, 59.4, 45.6, 51.6, 48.3, 46.0, 51.1, 37.8, 57.1, 41.0, 60.3, 39.6, 57.1, 48.3, 53.9, 53.9, 52.5, 59.9, 51.6, 57.1, 79.2, 58.5, 74.1, 58.5, 69.1, 58.9, 63.5, 59.4, 59.9, 48.3, 59.4, 47.0, 61.2, 45.1, 64.0, 44.2, 66.8, 38.7, 41.9, -32.7, 13.8, 44.2, 58.5, 42.8, 59.4, 60.8, 26.2, 48.8, 25.8, 35.0, 0.0, 23.5, 5.5, 40.1, 70.9, -17.5, -4.1, -3.2, -4.1, 6.9, -1.8, 21.2, -3.7, -14.7, 12.4, 42.8, 18.4, -28.1, 32.2, 4.6, 71.4, 1.4, 79.2, -26.7, 13.4, -6.4, 60.8, 36.8, 93.9, 38.7, 8.3, 39.6, 61.7, -12.4, 27.6, 48.8, 103.1, 25.3, 94.4, 14.7, 88.4, 63.5, 103.1, 69.1, 31.3, 46.0, 36.8, 59.9, 32.7, 15.7, 80.6, 25.8, 87.0, 50.2, 98.5, -9.7, 67.7, 64.9, 98.5, 36.4, 99.5, -23.0, 30.4, 53.4, 59.9, 52.5, 62.6, 51.1, 66.8, 50.6, 71.4, 47.4, 75.5, 42.4, 54.8, 41.0, 53.9, 39.6, 52.9, 33.6, 48.8, 0.5, 31.8, 43.7, 55.3, -0.5, 50.2, 42.8, 81.0, 65.8, 92.5, 66.3, 85.2, 54.3, 85.2, 26.7, 67.7, 36.4, 24.9, 33.6, 75.5, 18.9, 24.4, 29.9, 32.7, 12.9, 37.3, 52.0, 92.1, 19.3, 72.7, 28.5, 80.6, 21.6, 58.0, -9.7, 40.5, 11.1, 58.9, -17.0, 46.0, 24.9, 43.3, -28.1, -3.2, -34.5, -3.7, 87.0, 82.9, 97.6, 12.0, 74.1, 40.1, 72.7, 48.8, 80.1, 43.3, 83.8, 47.0, 77.4, 49.7, 80.1, 51.1, 92.1, 61.7, 114.6, 11.1, 95.8, 53.4, 113.3, 44.7, 86.1, 54.8, 84.7, 54.8, 73.7, 44.7, 78.7, 46.5, 82.0, 49.3, 85.2, 54.8, 83.8, 58.0, 83.8, 54.8, 78.7, 52.0, 76.0, 51.1, 71.8, 51.1, 75.1, 77.8, 74.1, 73.2, 73.7, 67.7, 72.7, 62.6, 71.8, 58.9, 78.7, 57.1, 80.1, 58.9, 82.0, 61.2, 83.3, 64.0, 91.6, 39.1, 120.2, 8.3, 80.6, 56.2, 82.4, 57.1, 76.0, 25.3, 83.8, 24.4, 90.7, -2.3, 101.3, 2.8, 87.9, 67.2, 126.2, -9.2, 119.7, -8.7, 113.7, -5.1, 102.2, -5.5, 125.7, 6.9, 87.0, 16.6, 117.9, 25.8, 106.8, 64.0, 104.1, 71.4, 126.2, 7.4, 113.3, 53.9, 87.0, 88.9, 89.3, 6.4, 85.2, 59.4, 122.9, 21.6, 76.0, 99.9, 90.7, 87.5, 96.7, 80.6, 87.0, 34.5, 76.9, 31.8, 99.9, 73.2, 93.5, 80.6, 77.8, 95.8, 108.7, 60.3, 84.3, 93.9, 122.9, 23.9, 75.5, 58.0, 77.4, 60.8, 78.7, 64.9, 80.1, 69.5, 82.9, 73.2, 82.4, 52.9, 84.3, 52.0, 85.6, 50.6, 94.8, 45.6, 116.9, 26.7, 81.0, 53.4, 113.7, 44.2, 85.2, 77.8, 76.4, 83.3, 97.2, 62.6, 92.1, 22.1, 91.6, 70.9, 106.4, 20.7, 97.6, 29.9, 109.1, 32.7, 78.3, 89.8, 100.4, 66.8, 93.9, 75.1, 101.8, 53.4, 119.3, 34.5, 107.7, 52.9, 118.8, 39.1, 100.8, 39.6, 127.1, -8.3, 121.6, -8.3]}, {"rect": [284, 437, 562, 715], "points": [0.37823, -0.01307, 0.09385, 0.0, 0.00655, 0.39103, -0.01572, 0.0, -0.10427, -0.00155, 0.37352, 0.0, -150.68401, -239.85601, -59.51648, 1.0, 67.2, 41.9, 69.5, 25.3, 67.2, 45.1, 66.8, 48.8, 66.3, 51.1, 66.3, 59.4, 66.3, 63.5, 66.8, 69.1, 66.8, 74.1, 66.8, 78.7, 38.7, 87.0, 29.9, 14.7, 58.9, 41.0, 59.4, 49.3, 50.2, 45.1, 44.2, 49.3, 52.9, 50.6, 47.4, 52.5, 34.5, 64.9, 6.0, 15.2, 29.9, 56.6, -20.7, 52.0, 36.8, 57.1, 38.7, 57.1, 59.4, 45.6, 51.6, 47.9, 46.0, 51.1, 37.8, 57.1, 41.0, 60.3, 39.6, 57.1, 48.3, 53.9, 53.4, 52.5, 59.9, 51.6, 57.1, 78.7, 58.0, 73.7, 58.5, 68.6, 58.9, 63.5, 59.4, 59.9, 47.9, 59.4, 47.0, 60.8, 45.1, 63.5, 43.7, 66.3, 39.1, 41.9, -33.2, 13.8, 43.7, 58.5, 42.4, 59.4, 60.8, 26.2, 49.3, 25.8, 35.5, 0.0, 23.5, 5.5, 40.1, 70.4, -17.5, -4.1, -3.7, -4.1, 6.4, -1.8, 21.2, -3.7, -15.2, 12.4, 43.3, 18.4, -28.5, 32.2, 4.6, 70.9, 1.4, 79.2, -26.7, 13.4, -6.4, 60.8, 36.8, 93.5, 38.7, 8.3, 39.6, 61.7, -12.4, 27.6, 48.8, 102.7, 25.3, 94.4, 14.7, 88.4, 63.5, 102.7, 69.1, 31.3, 46.0, 36.8, 59.9, 32.7, 15.2, 80.6, 25.3, 87.0, 50.2, 98.1, -10.1, 67.7, 64.9, 98.5, 36.4, 99.5, -23.0, 30.4, 53.4, 59.4, 52.5, 62.6, 51.1, 66.8, 50.2, 71.4, 47.4, 75.5, 42.4, 54.8, 41.0, 53.9, 39.6, 53.4, 33.6, 48.8, 0.5, 31.8, 43.7, 55.3, -0.5, 50.2, 42.8, 81.0, 65.8, 92.1, 66.3, 84.7, 54.3, 84.7, 26.7, 67.2, 36.8, 24.9, 33.6, 75.1, 18.9, 24.4, 29.9, 32.7, 12.9, 37.3, 52.0, 92.1, 19.3, 72.7, 28.5, 80.6, 21.6, 57.6, -9.7, 40.5, 10.6, 58.9, -17.5, 46.0, 24.9, 43.3, -28.5, -3.2, -35.0, -3.7, 87.0, 82.9, 97.6, 12.0, 74.1, 40.1, 72.7, 48.8, 80.1, 43.3, 83.8, 47.0, 77.4, 49.3, 80.1, 51.1, 92.1, 61.2, 115.1, 11.1, 96.2, 53.4, 112.8, 45.1, 86.1, 54.8, 84.7, 54.8, 73.7, 44.7, 78.7, 46.5, 82.0, 49.3, 85.2, 54.8, 83.8, 58.0, 83.8, 54.8, 78.7, 52.0, 75.5, 51.1, 71.8, 51.1, 75.1, 77.4, 74.1, 72.7, 73.7, 67.7, 72.7, 62.6, 71.4, 58.9, 78.7, 57.1, 80.1, 58.9, 82.0, 61.2, 83.3, 64.0, 91.6, 39.1, 120.2, 8.7, 80.6, 56.2, 82.4, 56.6, 76.4, 25.3, 83.8, 24.4, 90.7, -2.3, 101.8, 2.8, 87.9, 67.2, 126.2, -8.7, 119.7, -8.3, 113.7, -5.1, 102.2, -5.5, 125.7, 6.9, 87.5, 16.6, 117.4, 26.2, 106.8, 64.0, 103.6, 70.9, 126.2, 7.8, 112.8, 53.9, 87.0, 88.4, 89.8, 6.4, 85.2, 58.9, 122.9, 22.1, 76.0, 99.5, 90.7, 87.0, 96.7, 80.6, 87.0, 34.5, 77.4, 31.8, 99.9, 73.2, 93.5, 80.6, 77.8, 95.3, 108.7, 60.3, 84.3, 93.9, 122.9, 23.9, 75.5, 58.0, 77.4, 60.8, 78.7, 64.5, 79.7, 69.1, 82.9, 72.7, 82.4, 52.5, 84.3, 52.0, 85.6, 50.6, 94.8, 45.6, 116.9, 26.7, 81.0, 52.9, 113.7, 44.2, 85.2, 77.4, 76.4, 82.9, 97.2, 62.6, 92.5, 22.1, 91.6, 70.4, 106.8, 20.7, 98.1, 29.9, 109.6, 32.7, 78.3, 89.8, 100.4, 66.8, 93.9, 74.6, 101.8, 52.9, 119.3, 34.5, 107.7, 52.9, 118.8, 39.6, 101.3, 39.6, 127.1, -8.3, 121.1, -7.8]}, {"rect": [286, 436, 564, 714], "points": [0.37833, -0.01219, 0.09347, 0.0, 0.00831, 0.39007, -0.02091, 0.0, -0.10274, -0.00068, 0.37457, 0.0, -152.13104, -238.98208, -56.19082, 1.0, 67.2, 42.4, 68.6, 26.2, 67.2, 46.0, 66.8, 49.7, 66.3, 52.0, 65.8, 59.4, 66.3, 63.1, 66.3, 68.1, 66.3, 73.2, 66.3, 78.3, 38.7, 87.5, 29.5, 15.2, 58.9, 41.4, 59.4, 49.7, 50.2, 45.6, 44.2, 49.7, 52.5, 51.1, 47.0, 53.4, 34.1, 64.9, 5.5, 15.7, 29.5, 57.1, -20.7, 52.5, 36.4, 57.6, 38.2, 57.1, 59.4, 46.0, 51.6, 48.8, 45.6, 51.6, 37.3, 57.6, 40.5, 60.3, 39.1, 57.1, 47.9, 54.3, 53.4, 52.9, 59.4, 52.0, 56.6, 78.3, 58.0, 73.2, 58.5, 68.1, 58.9, 63.1, 59.4, 59.4, 47.9, 58.9, 46.5, 60.8, 44.7, 63.5, 43.3, 66.3, 38.2, 42.4, -33.2, 14.7, 43.7, 58.5, 42.4, 59.4, 60.3, 26.7, 48.3, 26.7, 34.5, 0.5, 22.6, 6.0, 39.6, 70.4, -18.0, -3.7, -4.1, -3.7, 6.0, -1.4, 20.7, -3.2, -15.7, 12.9, 42.8, 18.9, -28.5, 33.2, 4.1, 71.4, 1.4, 79.7, -27.2, 13.8, -6.9, 61.2, 36.4, 93.9, 38.2, 8.7, 39.1, 61.7, -13.4, 28.1, 48.8, 102.7, 24.9, 94.4, 14.3, 88.9, 63.1, 103.1, 68.6, 32.2, 45.6, 37.3, 59.4, 33.2, 15.2, 80.6, 25.3, 87.5, 49.7, 98.5, -10.1, 68.6, 64.9, 98.5, 36.4, 99.5, -23.5, 30.8, 52.9, 59.4, 52.0, 62.2, 51.1, 66.3, 50.2, 70.9, 47.4, 75.5, 41.9, 55.3, 40.5, 54.3, 39.1, 53.4, 33.2, 49.3, 0.0, 32.2, 43.3, 55.7, -0.9, 50.6, 42.4, 81.0, 65.8, 92.5, 66.3, 84.7, 53.9, 84.7, 26.2, 67.7, 35.9, 25.3, 33.2, 75.5, 18.4, 24.9, 29.5, 33.2, 12.4, 37.8, 51.6, 92.1, 18.9, 73.2, 28.5, 80.6, 21.2, 58.0, -10.1, 41.0, 10.1, 59.4, -17.5, 46.5, 24.4, 43.7, -29.0, -2.8, -35.5, -2.8, 87.0, 83.3, 97.2, 12.9, 74.1, 41.0, 72.7, 49.3, 80.1, 43.7, 83.3, 47.9, 76.9, 50.2, 80.1, 51.6, 91.6, 61.7, 114.6, 12.0, 95.8, 53.9, 113.3, 46.0, 85.6, 55.3, 84.3, 55.3, 73.7, 45.6, 78.7, 47.4, 82.0, 49.7, 85.2, 55.3, 83.3, 58.5, 83.3, 55.3, 78.3, 52.5, 75.5, 52.0, 71.4, 51.6, 74.6, 77.4, 73.7, 72.3, 73.2, 67.2, 72.3, 62.2, 71.4, 58.5, 78.3, 57.1, 79.7, 58.9, 81.5, 61.2, 82.9, 64.0, 91.6, 39.6, 120.2, 9.7, 80.1, 56.2, 82.0, 57.1, 76.0, 26.2, 83.3, 24.9, 90.2, -1.4, 101.3, 3.2, 87.9, 67.2, 125.7, -7.8, 118.8, -7.8, 112.8, -4.1, 101.3, -5.1, 125.7, 7.8, 87.0, 17.0, 117.4, 27.2, 106.8, 64.9, 103.6, 71.8, 125.7, 8.7, 113.3, 54.8, 87.0, 88.9, 89.3, 7.4, 84.7, 59.4, 122.9, 23.0, 75.5, 99.9, 90.7, 87.9, 96.7, 81.0, 86.6, 35.5, 76.9, 32.7, 99.9, 74.1, 93.5, 81.0, 77.8, 95.8, 108.7, 61.2, 84.3, 94.4, 122.9, 24.9, 75.5, 58.0, 76.9, 60.8, 78.3, 64.5, 79.7, 68.6, 82.4, 72.7, 82.0, 53.4, 83.8, 52.5, 85.2, 51.6, 94.8, 46.0, 116.9, 27.6, 80.6, 53.9, 113.7, 45.1, 84.7, 77.8, 76.4, 82.9, 96.7, 63.1, 92.1, 23.0, 91.6, 70.9, 106.4, 21.6, 97.6, 30.4, 109.1, 33.6, 77.8, 89.8, 100.4, 67.2, 93.5, 75.1, 101.8, 53.9, 119.3, 35.5, 107.7, 53.9, 118.8, 40.5, 100.8, 40.5, 126.6, -6.9, 121.1, -6.9]}]
\ No newline at end of file
diff --git a/web_demo/static/assets/ref_data.txt b/web_demo/static/assets/ref_data.txt
new file mode 100644
index 0000000..a0bbe9f
--- /dev/null
+++ b/web_demo/static/assets/ref_data.txt
@@ -0,0 +1,5040 @@
+0.98990387
+1.00289595
+0.94648540
+0.96182400
+0.86435580
+0.88414758
+0.83362508
+0.72759557
+0.85907161
+0.97541338
+0.79422355
+0.92718285
+0.77051193
+0.60334933
+0.72510010
+0.74222976
+0.75313497
+0.71428871
+0.00000000
+0.22440299
+0.59242952
+0.60128969
+0.61232698
+0.96787494
+1.26779473
+1.45333040
+2.10168076
+1.94305289
+1.67534757
+1.46914542
+1.26829827
+0.82285535
+0.26284206
+0.23949599
+0.16423447
+0.00000000
+0.00000000
+0.00000000
+0.14831083
+0.65671110
+1.16738570
+1.75980997
+1.63779318
+1.37603772
+1.51680720
+0.98565471
+1.83979654
+1.50037539
+1.22455525
+1.28241909
+0.46333674
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.44357532
+1.21919072
+1.66886187
+1.11037755
+0.61407876
+0.02349027
+0.36467990
+0.35951799
+0.42556971
+0.40475214
+0.25810215
+0.79183513
+1.47267568
+0.22609578
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.36924413
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.78448153
+0.41095686
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.04243696
+0.00000000
+0.00000000
+0.49406648
+0.00000000
+0.18914625
+0.30140847
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.42878285
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.12507081
+0.56320071
+0.88213986
+0.84105951
+0.88768148
+0.67495072
+0.78572881
+0.74747294
+1.40783513
+0.75584632
+0.47924334
+0.12195109
+0.00000000
+0.28061795
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.03665102
+0.64686859
+1.04323304
+1.21456039
+1.06400228
+1.21645260
+1.04604578
+1.36568451
+0.97305173
+0.80338067
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.06812065
+0.70768553
+0.94739306
+0.86218959
+1.15178025
+1.04333782
+1.22461438
+0.69121873
+0.19969960
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.09084208
+0.00000000
+0.00000000
+0.00000000
+0.17408694
+0.07496575
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.02472596
+0.12525050
+0.17600405
+0.17528248
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.06307872
+0.04051042
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.05360165
+0.00000000
+0.00000000
+0.01697787
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.21458493
+0.32943985
+0.32121542
+0.33016986
+0.30526382
+0.41186970
+0.38541904
+0.32562780
+0.44538000
+0.40877789
+0.40124857
+0.66705871
+0.38099664
+0.33926076
+0.35208726
+0.30157617
+0.19975099
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.47041053
+0.77860630
+0.69711834
+1.25397754
+0.46335861
+0.39150167
+0.67397100
+0.42893383
+0.00000000
+0.00000000
+0.01198812
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.17553718
+0.62012535
+1.24542201
+1.37477481
+1.82997262
+2.09533715
+0.95551097
+1.54265285
+1.14735174
+0.57226282
+0.03813668
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.81938088
+1.44766152
+1.46189952
+1.66783190
+1.55857265
+1.34817219
+1.69887495
+2.02715802
+2.03219366
+2.28677011
+0.98623776
+1.00077081
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.79680103
+0.54524797
+1.42534137
+0.88941497
+1.70067537
+1.59649312
+1.30354464
+1.11238098
+1.47662473
+1.51452863
+1.43256104
+2.29421425
+0.97197878
+0.45313203
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+1.43541265
+1.88076496
+0.91169280
+1.08179116
+0.11857166
+0.94154388
+0.22438504
+0.87074882
+1.66722095
+0.92973745
+1.71528113
+1.64889419
+0.08291334
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+1.14381433
+1.15406108
+1.56933951
+1.80925202
+1.58231342
+1.31612194
+1.10840416
+0.56801623
+1.56324553
+1.32150483
+1.57561088
+1.22303796
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.86531532
+1.11454499
+1.28274786
+1.62474215
+1.56678176
+1.75056851
+1.33140028
+2.32323956
+1.53057301
+1.85913956
+0.30311200
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.50837696
+1.08283210
+0.93387908
+1.04861200
+1.23107910
+1.13374937
+1.87373006
+1.66239858
+0.36488530
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.27451611
+0.51988924
+0.85820872
+0.96536511
+0.88292730
+0.56908959
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.06654447
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.38964620
+0.24162766
+0.25510564
+0.26904783
+0.29533944
+0.26578879
+0.32074523
+0.30179226
+0.24733536
+0.24173431
+0.33089662
+0.40365076
+0.51063991
+0.57589442
+0.58096421
+0.58153158
+0.57374042
+0.53561848
+0.33105397
+0.28029102
+0.13436538
+0.18157749
+0.21922612
+0.01619185
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.17656326
+0.38334274
+0.59439665
+0.57850313
+0.60569972
+0.66420233
+0.24478653
+0.25931880
+0.22973874
+0.08122760
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.55170107
+0.75957185
+0.71387172
+0.50902051
+0.25341448
+0.37378162
+0.63982660
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.66234165
+0.74456877
+0.62672859
+0.19284281
+0.50381249
+1.44509387
+0.31297961
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.32185102
+0.80715644
+0.70304298
+0.27756134
+0.41233531
+0.77200717
+0.30831516
+0.07778517
+0.10084480
+0.46946487
+0.01878890
+0.28240609
+0.15803674
+0.00000000
+0.37430412
+0.00000000
+0.00000000
+0.18074763
+0.18474664
+0.83442920
+0.72620201
+0.30261829
+0.45613798
+0.05134720
+0.81018513
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00812252
+0.48890677
+0.34049648
+0.11638910
+0.00000000
+0.38781303
+0.84562784
+0.74871129
+0.30188999
+0.42427847
+0.18286672
+0.48735103
+0.70857239
+0.11463457
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.09563155
+0.30375195
+0.70345318
+0.83984441
+0.80586427
+0.29492319
+0.41532686
+0.26606554
+0.29191461
+0.62169856
+0.47041187
+0.39659050
+0.10493791
+0.00000000
+0.09702723
+0.04196464
+0.32097578
+0.41480491
+0.18346000
+0.62493944
+0.81858033
+0.81733727
+0.89990026
+0.34408689
+0.46603286
+0.36908501
+0.35009325
+0.49868178
+0.60795283
+0.58424795
+0.61162192
+0.58892345
+0.60841298
+0.55081087
+0.46462533
+0.58050579
+0.58081788
+0.78918552
+0.85274154
+0.85633278
+0.97163707
+0.37926865
+0.48250675
+0.39716223
+0.35387230
+0.35829303
+0.48253572
+0.50847501
+0.45661893
+0.63785166
+0.67059439
+0.72385836
+0.67003113
+0.64353353
+0.76797312
+0.84718060
+0.89417380
+0.99260581
+0.95227969
+0.38522631
+0.44622424
+0.39442161
+0.31652039
+0.30288315
+0.34183839
+0.42762136
+0.45131144
+0.55683672
+0.57580638
+0.55984110
+0.71399719
+0.79367006
+0.83641243
+0.87055963
+0.94892448
+1.07519400
+0.82725865
+0.39464355
+0.41793263
+0.39345786
+0.32494384
+0.30181837
+0.32212886
+0.38602185
+0.41640559
+0.46092796
+0.58443701
+0.59723008
+0.70331722
+0.80463493
+0.84298164
+0.98054719
+1.09429657
+0.97922260
+0.85995072
+0.21342714
+0.28958032
+0.18117128
+0.15119107
+0.14092292
+0.14700970
+0.17688929
+0.18818456
+0.19325064
+0.24416129
+0.21546791
+0.28146920
+0.35978800
+0.42277396
+0.60562867
+0.71239305
+0.56948560
+0.68314052
+0.10442706
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.03855011
+0.58065814
+0.18595155
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.57363725
+0.98742384
+0.72944057
+0.68349850
+0.49291146
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.02021827
+0.24758227
+0.48578498
+0.53844541
+0.48211396
+0.59581131
+0.98165840
+0.53149658
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.01599845
+0.35926330
+0.51021445
+0.45139500
+0.60006940
+0.92192572
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.45926055
+0.49139148
+0.41241592
+0.56745285
+0.77084535
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.71713954
+0.47075379
+0.44652501
+0.57092994
+0.83113301
+0.49400115
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.69265455
+0.44534877
+0.44394261
+0.56610370
+0.85736847
+0.59614658
+0.34332728
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.50305605
+0.51193988
+0.45598003
+0.39676267
+0.56321967
+0.85744035
+0.61292648
+0.62207854
+0.25792685
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.30748069
+0.42506450
+0.44871172
+0.45256156
+0.40847427
+0.56133765
+0.82215291
+0.57465267
+0.59253448
+0.56639636
+0.33108735
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00282377
+0.42718983
+0.47584647
+0.43247202
+0.44709572
+0.35521296
+0.56816643
+0.78506768
+0.54164535
+0.55333441
+0.56993610
+0.57400602
+0.49420044
+0.43161625
+0.28702745
+0.12649257
+0.10022835
+0.23803380
+0.36092091
+0.42246953
+0.44948164
+0.46936271
+0.41649956
+0.42819354
+0.56968886
+0.77026933
+0.58404499
+0.61229300
+0.60446113
+0.58764613
+0.53390539
+0.47345260
+0.50602055
+0.49543211
+0.44405413
+0.41368037
+0.42891860
+0.44347897
+0.46708590
+0.42998597
+0.36825904
+0.51761258
+0.55978417
+0.76660109
+0.58914042
+0.62863827
+0.63804060
+0.62931722
+0.59330583
+0.55780035
+0.54488242
+0.52354473
+0.47590637
+0.44098926
+0.44741020
+0.47268605
+0.44426680
+0.26278576
+0.64849472
+0.52313989
+0.45745707
+0.69870538
+0.61806935
+0.65920037
+0.67370349
+0.68016380
+0.63212472
+0.63127124
+0.56701827
+0.51686382
+0.50350779
+0.48299453
+0.48284581
+0.46366966
+0.42286718
+0.68950617
+0.73024607
+0.69104552
+0.13622464
+0.00000000
+0.31574211
+0.27971345
+0.26288989
+0.27635166
+0.24294543
+0.26545984
+0.33119625
+0.35532671
+0.28287134
+0.41662011
+0.22093479
+0.15951623
+0.25681925
+0.25164145
+0.22404742
+0.00000000
+0.02959958
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.31558955
+0.72701722
+1.05021906
+0.99405307
+0.70671219
+0.51564986
+0.41986883
+0.08098675
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.58480227
+1.16663361
+1.56581938
+1.96237504
+2.20778584
+1.93240178
+1.92348194
+1.64909565
+1.61195886
+1.56400919
+0.15380521
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.05238765
+1.31746233
+1.86607492
+1.96274149
+1.75113046
+1.64250839
+1.95916831
+2.04461432
+2.09206104
+1.86775172
+1.52945065
+1.61397862
+1.57842791
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00671667
+1.50205708
+1.58424842
+1.82496440
+1.46294534
+1.44181967
+0.87553316
+1.09373677
+1.17338800
+1.30158412
+1.62615013
+1.33882964
+1.59922147
+0.90907872
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.47769824
+0.65784514
+0.93297756
+1.11333466
+1.90096200
+1.95379138
+1.75953627
+1.75230300
+1.10323226
+1.26296604
+1.26976395
+1.11657035
+1.12566221
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.26394740
+0.53463095
+0.97316921
+1.15426302
+1.11359429
+1.02491820
+1.30228627
+1.34545767
+1.12008297
+1.09112060
+1.00031233
+1.02446043
+0.07022194
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.39186370
+0.51585007
+0.98675841
+1.01267087
+1.12969398
+1.17503369
+1.37049580
+0.92835081
+0.89714819
+0.67509741
+0.49985018
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.41721514
+0.34051600
+0.50266010
+0.76861918
+0.88272387
+1.02303994
+0.86305052
+0.41581491
+0.35706177
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.06087301
+0.20433557
+0.20799617
+0.14646125
+0.12404308
+0.14968321
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.01869388
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.09289264
+0.10534801
+0.00000000
+0.00000000
+0.00000000
+0.20541769
+0.21841967
+0.23224944
+0.36671969
+0.48462531
+0.76549757
+0.78418344
+0.84811532
+0.49191311
+0.61028755
+0.65794116
+0.26654735
+0.00000000
+0.03658586
+0.03327180
+0.00000000
+0.00000000
+0.00000000
+0.41186178
+0.14696811
+0.81071311
+0.94157690
+0.87662661
+1.29327881
+1.26250923
+1.12806427
+1.11708736
+1.20208216
+0.98005164
+0.69577098
+0.09460778
+0.03436863
+0.00689398
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.33450580
+0.21756233
+0.42639342
+0.60503769
+0.46243671
+0.28019837
+0.67005277
+0.42133650
+0.88457733
+0.95901519
+0.98875511
+0.78304291
+0.31447300
+0.00649392
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.34627482
+0.39444003
+0.08654542
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.38536522
+0.64534491
+1.04698920
+0.45111731
+0.01889407
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.48824838
+0.50503886
+0.39595371
+0.29168677
+0.22111699
+0.18754525
+0.21130811
+0.42724463
+0.47228625
+0.56129438
+0.65917230
+0.20163818
+0.09448047
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.13660526
+0.52681750
+0.69977784
+0.72537541
+0.74138236
+0.70185989
+0.58263445
+0.65569174
+0.76369834
+1.01446855
+0.27665606
+0.09394237
+0.07035573
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.11004817
+0.39332005
+0.48710242
+0.71007842
+0.83165735
+0.91025436
+1.01616991
+0.92773491
+0.40968102
+0.13494773
+0.05613689
+0.02736150
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.07769345
+0.18626349
+0.18932740
+0.24780482
+0.28366429
+0.23807243
+0.11495312
+0.07003812
+0.05767040
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.01158622
+0.01994983
+0.02109848
+0.00161383
+0.03366257
+0.05984095
+0.07147899
+0.00212551
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.02453439
+0.02241261
+0.00000000
+0.02210666
+0.10983096
+0.02703653
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.01548086
+0.03708456
+0.03857761
+0.03358498
+0.03279614
+0.00229088
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.07691437
+0.07907800
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.12298651
+0.41704848
+0.41927382
+0.22024338
+0.18337631
+0.16615109
+0.10408831
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.10397214
+0.16223785
+0.16866288
+0.12240982
+0.00335694
+0.39216864
+0.55308867
+0.36435854
+0.21938987
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.05397623
+0.28318000
+0.30942622
+0.18540877
+0.39111853
+0.51254553
+0.22578850
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.10665649
+0.28411877
+0.16950972
+0.39204672
+0.53640884
+0.03402809
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.30463582
+0.19231732
+0.38160750
+0.52770191
+0.59193075
+0.61327267
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.28260565
+0.19537763
+0.38361359
+0.53298771
+0.41960669
+0.70517606
+0.57617933
+0.30948088
+0.13957861
+0.00661501
+0.01620878
+0.00000000
+0.00000000
+0.00000000
+0.00548311
+0.00000000
+0.00000000
+0.00000000
+0.29228154
+0.14735465
+0.37220219
+0.51379931
+0.36647204
+0.38620970
+0.75983733
+0.60624623
+0.18720296
+0.19683136
+0.10161818
+0.09179515
+0.16645296
+0.18767831
+0.25502974
+0.12241726
+0.03474235
+0.30069304
+0.30161732
+0.12930398
+0.36055994
+0.47649270
+0.33996356
+0.33272785
+0.40833580
+0.69223189
+0.80479026
+0.44386399
+0.26410219
+0.17634349
+0.03829379
+0.20720530
+0.29810056
+0.20471613
+0.16746365
+0.23702815
+0.22725204
+0.04893135
+0.36463410
+0.45213056
+0.34044853
+0.34748402
+0.33575734
+0.34452772
+0.44421616
+0.54825717
+0.57708019
+0.59748888
+0.50512218
+0.49472168
+0.42094865
+0.16237949
+0.25105003
+0.22753254
+0.16684371
+0.00000000
+0.35926002
+0.48116323
+0.34521848
+0.33760279
+0.34035680
+0.32726827
+0.34611520
+0.37118530
+0.37822527
+0.34814912
+0.32918283
+0.26874009
+0.21421073
+0.20955147
+0.21048921
+0.19926867
+0.04394636
+0.00000000
+0.34824035
+0.46820572
+0.36814171
+0.37959757
+0.35937518
+0.35729522
+0.34382147
+0.28986448
+0.28679952
+0.28213370
+0.27678868
+0.24342123
+0.20233756
+0.20926832
+0.18818812
+0.06218243
+0.00000000
+0.00000000
+0.31517261
+0.42290980
+0.35870767
+0.34433728
+0.37739557
+0.37000090
+0.36990577
+0.36353242
+0.31561932
+0.29845813
+0.31089926
+0.23842333
+0.20166789
+0.20623325
+0.08053580
+0.00000000
+0.00000000
+0.00000000
+0.25582886
+0.41037452
+0.35144386
+0.37590188
+0.39297819
+0.39342207
+0.38025704
+0.36592862
+0.33669999
+0.31112751
+0.27892253
+0.22564650
+0.18631321
+0.07206917
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.76865876
+0.46405029
+0.50719035
+0.46094218
+0.40399304
+0.46119887
+0.28007746
+0.37830555
+0.58305210
+0.45072713
+0.58664680
+0.58573717
+0.32900611
+0.52669823
+0.55959332
+0.46944460
+0.47177365
+0.00000000
+0.00000000
+0.00000000
+0.32137975
+0.30508456
+0.37134612
+0.69809508
+0.88860363
+1.18963432
+1.41736805
+0.80679518
+1.17063129
+0.80170685
+0.45728776
+0.40401950
+0.18337819
+0.18869698
+0.13361715
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.15476747
+0.59620816
+1.04741144
+0.94924545
+1.44904292
+1.58498824
+1.22256589
+1.63757038
+0.72898841
+1.08715987
+0.78679252
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+1.08363307
+1.37062478
+1.60908854
+1.34796321
+1.52388430
+2.20702291
+1.95820665
+1.41784859
+1.35793960
+0.89300072
+1.21647513
+0.47826022
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.77757245
+0.82098740
+2.30544281
+1.46800876
+1.31602836
+1.04189062
+1.03465831
+0.84037131
+1.46940935
+1.77295518
+0.65539324
+0.99858493
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+1.01609862
+0.55212772
+0.80749786
+0.44111764
+1.05246639
+0.75506079
+1.75278544
+1.08141696
+0.57983112
+1.92699802
+0.94870067
+0.90441579
+0.12990321
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.15295310
+0.16065973
+1.40056825
+1.17179859
+0.76468194
+0.25190103
+0.15807936
+0.38215885
+0.66949499
+0.00000000
+0.39880913
+0.74386120
+1.25829637
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.73961765
+1.35014498
+1.50283039
+1.33938181
+1.46584237
+1.27841890
+1.60417449
+0.56727827
+1.23528707
+0.68027562
+0.40575671
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.74865872
+1.05059576
+1.11844373
+1.28055787
+1.19194233
+1.40852082
+0.95798647
+0.90233815
+0.91783363
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.16374442
+0.31506500
+0.45050433
+0.52144819
+0.59935611
+0.81956017
+0.40565965
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.08459695
+0.18342543
+0.02491204
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00310286
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.11031803
+0.21610329
+0.01910241
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.35778767
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.57587183
+0.49397549
+0.74250561
+0.48951864
+0.63857198
+0.48973000
+0.53693241
+0.34654593
+0.00000000
+0.00000000
+0.25307471
+0.27563161
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.20380402
+0.21461709
+0.44154838
+0.74726379
+0.39798576
+0.37589890
+0.71111226
+0.39489499
+0.12853198
+0.31758931
+0.20924573
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.23584181
+0.11769557
+0.46042928
+0.09691343
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.23680802
+0.11879196
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.01205283
+0.14037623
+0.30030218
+0.07816805
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.03518035
+0.21508831
+0.09891990
+0.04066180
+0.13770738
+0.13931079
+0.14462215
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.05448960
+0.06423558
+0.00000000
+0.00000000
+0.00000000
+0.08621567
+0.06554762
+0.06147541
+0.02861606
+0.07757992
+0.12024909
+0.17738105
+0.32510260
+0.29292318
+0.21595657
+0.37503400
+0.39709586
+0.22863936
+0.13529018
+0.08936357
+0.00000000
+0.00000000
+0.00000000
+0.12747529
+0.19154601
+0.25172207
+0.31762418
+0.53669339
+0.64626241
+0.84633201
+1.00547004
+0.73264408
+0.56954157
+0.59319049
+0.49074972
+0.30166674
+0.29524058
+0.31405881
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.16230679
+0.50713420
+1.02740788
+1.36096859
+1.64994836
+1.54674542
+1.18079185
+1.19287848
+1.09614921
+0.55423939
+0.04468843
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.13802637
+0.82115877
+1.43805039
+1.87903178
+2.08677936
+1.96925414
+1.77004135
+1.61323023
+2.04294848
+2.09779477
+1.92889178
+1.28838241
+0.45699108
+0.02327368
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+1.33127451
+2.17942071
+2.08089352
+1.76581323
+1.69341564
+1.85413873
+2.18819547
+2.31882739
+2.22782278
+2.23754978
+2.11944151
+1.60853922
+1.15288734
+0.17745373
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.86286163
+1.53190541
+1.56938314
+1.49328721
+0.97351903
+0.85177320
+1.03267717
+0.87339205
+1.10830748
+1.58289611
+1.69575608
+1.98788881
+1.48380983
+0.12790002
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.53877503
+1.24816239
+1.64020860
+1.75707531
+1.54942250
+1.50982535
+1.30211699
+1.12772071
+1.52007854
+1.73409963
+1.88993216
+0.86818707
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.10354343
+0.65301943
+0.86867183
+1.20450056
+1.38485646
+1.43191671
+1.43413556
+1.51013470
+1.79404294
+1.93031573
+1.20204222
+0.24580565
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.20188300
+0.67511702
+1.02108836
+1.16625655
+1.33799851
+1.39183784
+1.51338804
+1.70111787
+1.38729215
+0.46617177
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.10681851
+0.56210834
+0.99735957
+1.25022197
+1.24284410
+1.25946605
+1.06391847
+0.59237498
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.16210046
+0.32718745
+0.36473075
+0.21601966
+0.00917932
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.10739055
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.17462622
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.38183600
+0.28377810
+0.30757475
+0.29788294
+0.29493561
+0.28678292
+0.27517653
+0.25451830
+0.20434391
+0.24731226
+0.19291021
+0.16645125
+0.18837595
+0.15590863
+0.12257062
+0.14342301
+0.09178559
+1.03721213
+0.13001157
+0.43027416
+0.24416381
+0.31981257
+0.25493705
+0.18567443
+0.18396799
+0.00000000
+0.00000000
+0.05759671
+0.00000000
+0.06259009
+0.12029286
+0.03187437
+0.16404399
+0.23998925
+0.10672095
+1.56201696
+0.20166893
+0.72954494
+0.50401896
+0.31280795
+0.09138874
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.09916180
+0.33890298
+0.39188564
+0.35939142
+1.77485907
+0.21504998
+0.68779153
+0.30288500
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.15011883
+0.23066978
+0.39392662
+1.74164379
+0.13757104
+0.67384923
+1.37287033
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.26552069
+0.17404088
+0.04995177
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.14596470
+0.38694507
+1.72905326
+0.20762248
+0.46789983
+1.51534736
+0.14190035
+0.39226094
+0.40529987
+0.00000000
+0.02324133
+0.82852685
+0.00000000
+0.18279892
+0.27313632
+0.00000000
+0.20564298
+0.00000000
+0.20229328
+0.43921372
+1.65650821
+0.22685525
+0.66466880
+0.40419492
+0.29016069
+0.00000000
+0.00000000
+0.12319825
+0.07612878
+0.34824798
+0.00000000
+0.00000000
+0.68686563
+0.22826557
+0.41276637
+0.00000000
+0.22852863
+0.43624943
+1.63343716
+0.22483005
+0.68445486
+0.35882965
+0.62210643
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.07388023
+0.10581064
+0.36505276
+0.38811859
+1.48037493
+0.23427053
+0.66811478
+0.49699515
+0.53891879
+0.28320476
+0.30792928
+0.06913805
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.23434825
+0.00000000
+0.45317960
+0.40470415
+0.32712987
+1.45307708
+0.27651316
+0.71152359
+0.48662224
+0.46199021
+0.49674991
+0.37659433
+0.48004553
+0.73778784
+0.64605957
+0.46102574
+0.41447398
+0.32171872
+0.17672463
+0.27398565
+0.39205369
+0.40709931
+0.34409609
+1.55316186
+0.27062741
+0.68825805
+0.54711294
+0.51794183
+0.51974970
+0.49321586
+0.39648208
+0.41787437
+0.36560717
+0.36065573
+0.36391827
+0.26775950
+0.29071075
+0.37643513
+0.38979357
+0.40576866
+0.44001350
+1.77131176
+0.19667527
+0.68957567
+0.50889325
+0.52370995
+0.52628040
+0.51123637
+0.49417037
+0.38177004
+0.41962057
+0.34313628
+0.32893264
+0.35386735
+0.31788778
+0.35993072
+0.37996051
+0.40621021
+0.60790318
+1.78828883
+0.16272575
+0.60596222
+0.48249668
+0.44990399
+0.44051513
+0.45847484
+0.46373445
+0.38349897
+0.39275414
+0.36413592
+0.37723240
+0.30014643
+0.32517096
+0.33242080
+0.40027153
+0.76122653
+0.51021576
+1.94045591
+0.20486324
+0.64369726
+0.50799555
+0.47811058
+0.44968054
+0.49049333
+0.45325300
+0.40965459
+0.38592756
+0.35923818
+0.36679459
+0.39653468
+0.40797698
+0.50461638
+0.80461663
+0.67878324
+0.71643573
+1.83746016
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.04148370
+0.00009592
+0.00000000
+0.08976690
+0.04860723
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.26405543
+0.48004925
+0.71333587
+0.64589047
+0.31514746
+0.30293429
+0.44871536
+0.19837464
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.20418008
+0.59067613
+0.66003388
+0.66064662
+1.07507980
+1.11200595
+1.22124934
+0.72728527
+0.52248871
+0.74223638
+0.01581549
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.19856974
+0.50125641
+0.97201252
+1.13660741
+1.38180816
+1.48897994
+1.58519220
+1.57942426
+1.61621976
+1.53554881
+1.26811290
+0.25670883
+0.93709779
+0.03176794
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.67089605
+0.94597208
+1.11521280
+1.71885228
+0.87991911
+2.01891685
+1.31244338
+1.17915535
+1.17226648
+1.27854729
+1.61665773
+0.82376063
+0.67448276
+0.37573063
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+1.06478477
+1.31359863
+1.35513151
+1.34580004
+0.67814445
+0.92102015
+1.33334517
+0.50563860
+0.94908202
+1.33406150
+1.23128986
+1.48794341
+0.41199902
+0.71559578
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+1.37074769
+1.43400848
+1.44403899
+1.67550135
+1.36388266
+1.54319203
+1.14611065
+1.31850898
+1.32297885
+1.23083210
+1.13280022
+0.89362741
+0.37469432
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.61216074
+1.41729915
+1.74419522
+1.74159992
+1.63101792
+1.65786076
+1.62571669
+1.70642233
+1.62547088
+1.44308078
+1.02928102
+0.83099961
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.42361733
+1.44174564
+1.77735448
+1.59156728
+1.79385197
+1.63906670
+1.75407958
+1.70507574
+1.42738307
+0.62800151
+0.11495571
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.23157628
+0.66060615
+1.04481423
+1.03191948
+1.02678990
+1.20039213
+0.95342118
+0.49194786
+0.08438070
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.15062839
+0.26798379
+0.32778576
+0.13107951
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.10263515
+0.08540077
+0.01026617
+0.05179953
+0.00000000
+0.00358255
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.08252147
+0.20683204
+0.55587178
+0.64620531
+0.63929921
+0.41001901
+0.46340153
+0.51185608
+0.43339351
+0.20167568
+0.00086841
+0.00000000
+0.02191040
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.09839896
+0.40293854
+0.42895016
+0.23098129
+0.43739974
+0.40412080
+0.66538757
+0.65128905
+0.34966221
+0.42031139
+0.49612781
+0.12364096
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00748649
+0.21801415
+0.05247255
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.15442087
+0.00000000
+0.15188330
+0.14411521
+0.05148713
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.30455402
+1.00329995
+0.02029119
+0.13574150
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+1.24701750
+1.18045783
+1.01482749
+1.04456675
+1.03747559
+0.68393570
+0.51433831
+0.89217180
+1.07227921
+0.68531364
+0.54225856
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.43198428
+0.72892118
+0.48706707
+0.89567488
+1.06532514
+1.05546880
+1.23115718
+1.17835438
+1.13425577
+1.13575447
+1.26881075
+0.61175042
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.58607483
+0.60818070
+0.23036705
+0.32707885
+0.61175245
+0.69580913
+0.64276624
+0.72466004
+0.30709058
+0.18659694
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.01244693
+0.48751670
+0.50733632
+0.03345929
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.03670504
+0.30997685
+0.42868179
+0.50114721
+0.46646088
+0.22933304
+0.00328435
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00707581
+0.11862073
+0.28861886
+0.33753815
+0.27159286
+0.08807786
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00208620
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.01841321
+0.00000000
+0.07135591
+0.06211650
+0.05001310
+0.00843172
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.06486417
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.01820232
+0.03121383
+0.00649756
+0.00000000
+0.00000000
+0.00000000
+0.08102549
+0.23699221
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.30021304
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.68281668
+0.75601721
+0.55474776
+0.52245659
+0.51527858
+0.51838183
+0.16163801
+0.00000000
+0.00000000
+0.00000000
+0.18378523
+0.18911621
+0.31436157
+0.50273520
+0.55929613
+0.54849660
+0.62487149
+1.06534326
+1.09930325
+1.31965399
+1.04703903
+0.81865871
+0.29430857
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.14158762
+0.70463079
+0.90256369
+0.94340086
+1.36894560
+1.10253429
+1.28072190
+0.84088314
+0.05581878
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.22250393
+0.83206326
+0.93023378
+1.21475506
+1.13393831
+1.19822764
+0.16667561
+0.51701665
+0.93202126
+0.85340875
+0.79478371
+0.00000000
+0.05158180
+0.00000000
+0.01161429
+0.32550186
+0.00000000
+0.00000000
+0.00000000
+0.67247564
+0.94294733
+1.11881435
+1.09706295
+1.28694320
+0.00528765
+0.06931716
+0.58144164
+0.40499434
+1.33280253
+0.65737325
+0.78931677
+1.18609321
+1.13541484
+1.46103525
+1.29699385
+0.28843388
+0.81657040
+0.55607724
+0.96707696
+1.14427853
+1.04823077
+1.29847336
+0.81110436
+0.71920973
+0.03152759
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.02877397
+0.23322992
+0.37533590
+0.51323563
+0.15078798
+0.98320311
+0.99438202
+0.99128067
+1.10259092
+1.03937232
+1.21490073
+1.13013506
+0.81955379
+0.93323392
+0.46144694
+0.01766796
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.13975205
+0.71912831
+0.84119898
+1.16690123
+1.00817966
+1.13859868
+1.03316653
+1.24734437
+1.10527039
+0.96844566
+0.95070386
+0.96896499
+0.72781688
+0.55205452
+0.52330369
+0.66032487
+0.52159500
+0.59141749
+0.65561295
+1.14312196
+1.19321787
+1.06232834
+1.02613401
+1.06987429
+1.02220249
+1.17566943
+1.02484608
+1.10277331
+0.98679513
+0.93301702
+1.04062474
+0.88666058
+0.76273412
+0.74311441
+0.69312966
+1.02566516
+1.43340313
+1.13380456
+1.07902336
+1.02831364
+1.02524078
+0.97507441
+1.00835621
+1.15307271
+0.94694960
+0.99383587
+1.04848266
+1.00335634
+0.97880429
+0.92211556
+0.92320508
+0.97968364
+1.01899958
+1.10294819
+1.10374153
+1.07163835
+1.03624022
+1.02397132
+1.02704847
+0.83479452
+1.03887904
+1.14336157
+0.94753373
+0.96132666
+1.01193786
+1.02136362
+0.99164134
+1.02093744
+0.95942569
+0.97953886
+0.95653504
+0.99650210
+1.02557647
+1.04099536
+1.03441203
+1.03027129
+1.11163282
+0.83378619
+1.05228579
+1.17704427
+0.98136050
+0.99371344
+1.02191019
+1.02563775
+0.99756056
+0.99363524
+0.99725533
+1.00435209
+0.93338352
+0.96922541
+1.02667093
+1.02470839
+1.08814132
+0.99341071
+0.91091126
+0.65910983
+1.14338338
+1.16247129
+1.03110778
+1.10943329
+1.18708825
+1.13490629
+1.09710848
+1.10072649
+1.09387267
+1.05910707
+0.95313549
+0.88688749
+0.81405121
+0.79541177
+0.75914544
+0.45205924
+0.02713810
+0.00979386
+1.11193347
+1.07754469
+0.82534921
+0.84221864
+0.89359093
+0.94023764
+0.93012941
+0.89796722
+0.81913149
+0.60417318
+0.48442689
+0.35158250
+0.35007632
+0.32323009
+0.30332759
+0.46750209
+0.58236378
+1.15599501
+1.43085742
+0.38651422
+0.23409152
+0.17839201
+0.27049863
+0.37235194
+0.39540517
+0.29863971
+0.20866518
+0.13204026
+0.09935433
+0.05170424
+0.16976616
+0.10675678
+0.00000000
+0.00000000
+0.00000000
+0.51121801
+1.44019735
+0.93048561
+0.71225476
+0.84649831
+0.82924330
+0.95137215
+0.95074350
+0.34267995
+0.00000000
+0.00000000
+0.00000000
+0.02854860
+0.00000000
+0.00000000
+0.10223713
+0.24194986
+0.28035119
+0.51724476
+1.39305353
+0.89192694
+0.88519508
+1.03615844
+0.17804225
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.17906351
+0.27415422
+0.41851649
+1.34466648
+0.89863712
+1.71592402
+0.21120881
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.27829331
+0.39834473
+1.27309299
+0.85214353
+0.84370512
+0.02044360
+0.31242815
+0.19270827
+0.00000000
+0.00000000
+0.19954452
+0.00000000
+0.01898736
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.28273052
+0.42744589
+1.27684963
+0.84484881
+0.88714343
+0.66970336
+0.30676973
+0.64492375
+0.67227948
+0.67527103
+0.80353212
+0.63313562
+0.29728273
+0.75323588
+0.59820348
+0.03233666
+0.00000000
+0.00000000
+0.25924048
+0.38850370
+1.23896432
+0.82534128
+0.64161271
+0.76072645
+0.71003610
+0.26976857
+0.20405559
+0.22284000
+0.20094323
+0.32762611
+0.50710249
+0.66179371
+0.38439897
+0.00000000
+0.00000000
+0.22649832
+0.23533545
+0.37822309
+1.17157876
+0.73272437
+0.61205631
+0.64764011
+0.52390486
+0.73318243
+0.56397760
+0.37533224
+0.14249642
+0.17623927
+0.08114968
+0.34561661
+0.00000000
+0.00000000
+0.08196781
+0.13591719
+0.14371754
+0.24298348
+1.10496747
+0.74396974
+0.58733141
+0.55992836
+0.57838774
+0.43932357
+0.47493908
+0.70980579
+0.61961055
+0.44933760
+0.19860363
+0.15570027
+0.12736243
+0.00000000
+0.14951366
+0.04161415
+0.02772591
+0.12998399
+1.11874473
+0.71182179
+0.56169361
+0.61816204
+0.64049160
+0.63725084
+0.53339612
+0.52081275
+0.39452964
+0.34669006
+0.28924623
+0.21812813
+0.22484048
+0.17147575
+0.07203341
+0.00000000
+0.00000000
+0.00000000
+1.07927561
+0.71567923
+0.57254678
+0.62411809
+0.62238169
+0.64808583
+0.58286291
+0.50630307
+0.41146648
+0.34772006
+0.36444873
+0.26941103
+0.13462289
+0.05780037
+0.00000000
+0.00000000
+0.00000000
+0.08939958
+1.01764035
+0.68515176
+0.53504115
+0.58649409
+0.57998389
+0.55693489
+0.55995953
+0.53103650
+0.51117098
+0.38977027
+0.34733754
+0.30003670
+0.13581833
+0.00986097
+0.00000000
+0.00000000
+0.00000000
+0.17179009
+1.15300596
+1.47391677
+1.45131779
+1.42221224
+1.40305269
+1.33881068
+1.31797147
+1.23931515
+1.19305146
+1.21048415
+1.24347150
+1.26005423
+1.12188148
+0.98985517
+0.75570953
+0.58273083
+0.32617411
+0.78245342
+0.30284178
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.05114208
+0.05352940
+0.14138614
+0.07658211
+0.08707973
+0.18832937
+0.06114168
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.02674644
+0.18250363
+0.62585342
+0.97448212
+1.27093363
+0.90470523
+0.68095016
+0.56850857
+0.66305703
+0.34550473
+0.12224919
+0.13921914
+0.08400435
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.56481779
+1.09380603
+0.86015928
+0.86367476
+0.80392522
+1.01752687
+1.13314259
+0.84764344
+1.14863133
+1.03882110
+0.04536279
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.07931740
+0.94054538
+0.84012878
+0.83494782
+1.14862537
+1.24766874
+1.43315017
+1.30680704
+0.92124397
+0.92912787
+0.81251949
+1.08591223
+0.93342376
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.80505598
+1.14930034
+1.23464191
+0.81896770
+0.52673590
+0.59204084
+0.59513062
+0.72309285
+0.91859055
+0.82332623
+0.83542436
+1.39721191
+0.30618402
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.39275229
+0.29452208
+0.48956046
+0.56359941
+0.89803755
+1.24000800
+0.82064652
+1.01219606
+0.92861676
+0.54080522
+0.72703362
+0.48724240
+1.01300120
+0.40690374
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.32972598
+0.69832671
+0.59820819
+0.45627743
+0.17843279
+0.46013588
+0.44013906
+0.74099445
+0.70956904
+0.62974799
+0.27989987
+0.66727459
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.35146278
+0.51166695
+0.62622571
+0.53070575
+0.62579268
+0.62964565
+0.62704289
+0.31981504
+0.44254407
+0.57190728
+0.26885813
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.02005792
+0.28578517
+0.30966741
+0.57848561
+0.65330708
+0.65557778
+0.54639441
+0.47295216
+0.33840397
+0.32821324
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.07896712
+0.02466150
+0.00000000
+0.00000000
+0.04837633
+0.23986024
+0.26321334
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.23168281
+0.28185937
+0.08307523
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.40036753
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.36173806
+0.16604257
+0.00000000
+0.00000000
+0.30378807
+0.38348538
+0.43496770
+0.38304156
+0.36139175
+0.31431010
+0.16856414
+0.17985405
+0.16004039
+0.00000000
+0.13021058
+0.00000000
+0.00000000
+0.00000000
+0.06032591
+0.05980758
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.36238930
+0.68239141
+1.17682695
+0.55328947
+0.20259646
+0.13941316
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.16949739
+0.77575755
+1.61558580
+1.82582092
+1.45136678
+1.50419140
+1.28468275
+1.59454739
+1.02744770
+0.93132704
+0.44636220
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.55814254
+1.24765801
+1.45542347
+1.37273538
+1.32247412
+1.29964733
+1.56828666
+1.68023300
+1.46737587
+1.10151911
+1.13382900
+1.24935567
+0.50267613
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.25959307
+0.48168799
+0.35989368
+0.75911570
+0.58355498
+1.08124995
+0.97169781
+0.62001657
+0.62824315
+0.90665722
+1.04294348
+1.24806905
+1.15020025
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.72364968
+0.37986332
+0.00000000
+0.02601449
+0.28698269
+0.19197235
+0.12909926
+0.19809085
+0.00000000
+0.33420306
+1.05381584
+0.32324308
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.22402446
+1.02077365
+0.98961824
+0.74979377
+0.17777795
+0.23758748
+0.25303921
+0.00000000
+0.00000000
+0.00000000
+0.38937223
+0.36758494
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.14965360
+0.73705894
+0.85564578
+0.82027930
+0.95631349
+0.86861187
+1.03379393
+0.63165820
+0.65283209
+0.27347448
+0.00061051
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.45247275
+0.80486786
+0.84877270
+0.80615777
+0.93850833
+0.52406919
+0.38253456
+0.03709473
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.12390079
+0.07185394
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.40585783
+0.72983706
+0.86429936
+0.86253059
+0.91966504
+1.06370604
+1.53434920
+1.61045897
+1.79318190
+1.53235376
+1.03438294
+1.24504578
+0.92392778
+0.39628747
+0.17792012
+0.25131363
+0.31449446
+0.00000000
+0.20095603
+0.44435513
+0.59595138
+0.91132540
+1.36559010
+1.52110004
+1.47423363
+1.16978788
+0.74341893
+0.49551061
+1.01728225
+0.94879413
+0.53570354
+0.67251736
+0.21815492
+0.00704075
+0.05037257
+0.00000000
+0.21334693
+0.59033513
+0.97337192
+1.10667098
+1.07808447
+0.49751717
+0.20986199
+0.26880831
+0.45383224
+0.65712708
+0.77208316
+0.22075199
+0.23320997
+0.21548660
+0.65227079
+0.14631772
+0.00000000
+0.00000000
+0.10347612
+0.43735144
+0.88196570
+0.47006932
+0.47665420
+0.82934099
+0.87094301
+1.54014981
+1.12128115
+0.87326860
+0.78900188
+0.54407012
+0.45416319
+0.30792391
+0.15259056
+0.40234888
+0.00109819
+0.00000000
+0.12130573
+0.16902812
+0.77586907
+0.45840195
+0.38692954
+0.41323754
+0.43597785
+1.13205028
+0.88916439
+0.51569331
+0.98693001
+0.77982163
+0.62458926
+0.83706707
+0.03845379
+0.36234230
+0.00000000
+0.00000000
+0.15321910
+0.22593082
+0.35258356
+0.55104941
+0.09494250
+0.18136685
+0.49549109
+0.61959541
+0.62326884
+0.82736790
+0.45987347
+0.56671762
+0.70082098
+0.84026945
+0.55727768
+0.20714645
+0.00000000
+0.00000000
+0.14934306
+0.24879621
+0.13326190
+0.71177781
+0.16300201
+0.09020247
+0.07310404
+0.00000000
+0.20331852
+0.16668539
+0.26909742
+0.22499333
+0.08776382
+0.15138447
+0.51523858
+0.00000000
+0.00000000
+0.00000000
+0.12690751
+0.19038081
+0.08104108
+0.28028202
+0.23137866
+0.33329365
+0.38599184
+0.24350359
+0.25884157
+0.08497363
+0.23336661
+0.00000000
+0.00000000
+0.27349365
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.13855034
+0.18215720
+0.09116781
+0.05818829
+0.16892169
+0.07823801
+0.06441160
+0.43419561
+0.27630895
+0.19504590
+0.23693922
+0.08153054
+0.06391729
+0.00474684
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.17559449
+0.15936658
+0.07059549
+0.05128761
+0.10882115
+0.17779656
+0.05226522
+0.10309605
+0.07566673
+0.01646848
+0.01731028
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.17473307
+0.19422576
+0.12797493
+0.22112525
+0.21144930
+0.22397821
+0.17202871
+0.05987306
+0.09267865
+0.04724498
+0.02935651
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.16495095
+0.17794430
+0.23907182
+0.28390175
+0.24798010
+0.28859985
+0.23759857
+0.19024314
+0.22162759
+0.13018872
+0.03976565
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.16650018
+0.85464877
+0.96148539
+0.95248204
+0.90447992
+0.90854073
+0.90634584
+0.83760458
+0.92556369
+0.96324486
+0.84457618
+0.96867973
+0.85903358
+0.61196399
+0.58855790
+0.62123245
+0.64616084
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.38886121
+0.73861670
+0.63707215
+0.26809654
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.27185094
+0.90148872
+0.85100096
+1.17236722
+1.20552361
+1.54352665
+1.70862615
+1.03396904
+0.73228317
+0.68411934
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.49811107
+1.16874528
+1.07922649
+1.40253532
+1.76013577
+1.96750820
+2.24823976
+1.64072883
+1.60219705
+1.51980507
+0.71260917
+0.71552521
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.10395280
+0.99062526
+0.85486275
+1.31132841
+0.97576892
+1.99428236
+1.65987742
+1.41204131
+1.77875507
+1.75867236
+1.70235646
+1.60184205
+0.45315281
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.20207478
+1.02771592
+1.65862155
+1.33376658
+1.35490596
+0.63348973
+0.83158141
+0.87284786
+1.35504365
+1.27655232
+1.13438690
+1.11257160
+0.78000981
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.97322357
+0.95604527
+1.30813599
+1.34013188
+1.18318307
+1.11386442
+1.26858532
+1.04749656
+0.77672398
+1.19755876
+1.15110612
+1.32996917
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+1.09627616
+1.22024047
+1.29770863
+1.53270471
+1.67950118
+1.43343949
+1.52412164
+1.24839818
+0.98215765
+0.95246696
+0.88341486
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+1.11065853
+1.46649313
+1.36085558
+1.30098975
+1.26424384
+1.23531663
+0.99871713
+0.88902676
+1.11406970
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.41544542
+0.87261176
+0.97053194
+0.91875798
+0.83978277
+0.89453727
+0.78052169
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.09959419
+0.18656921
+0.00141420
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.01566640
+0.06896526
+0.07604817
+0.04311128
+0.00987730
+0.02460470
+0.00027217
+0.01793358
+0.02628386
+0.01430489
+0.00000000
+0.00000000
+0.02125844
+0.34903133
+0.11255430
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.09525520
+0.46920297
+0.62539554
+0.48531500
+0.38392550
+0.03124256
+0.28303051
+0.18954015
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.22493324
+0.53226084
+0.78805745
+1.00108325
+1.40051270
+1.56796730
+1.75495100
+1.41405380
+0.93270963
+0.93195647
+0.73943448
+0.13509773
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.42179823
+1.17309010
+1.37798142
+1.72816932
+1.94699419
+2.09611702
+2.01626277
+2.07026863
+1.80976593
+2.06142855
+1.89241493
+1.42554104
+0.67194390
+0.14227490
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.36202708
+1.97882593
+1.77104604
+1.52044225
+1.58035815
+1.76773691
+1.63765073
+1.76410055
+1.67912865
+2.03672028
+2.05092478
+1.72456503
+1.15316427
+0.23322856
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.57138866
+1.90374196
+2.11252475
+1.24955642
+1.15923464
+0.83700168
+0.73242140
+1.37925076
+1.25265050
+1.25543272
+1.67036414
+1.72148192
+1.70006144
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.94160807
+1.92793822
+2.03956366
+1.81060302
+1.56126225
+1.40029144
+1.18778300
+1.06657314
+0.83001828
+1.43760943
+1.47408342
+1.60238290
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+1.19142365
+1.82581425
+1.83108592
+2.01030040
+1.94157135
+1.86434984
+1.95532870
+1.76719606
+2.05656409
+1.67674696
+0.17590728
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.09152190
+1.00734043
+1.50212967
+1.75072145
+1.70518506
+1.76793492
+1.71943486
+1.80463135
+1.63947070
+0.66528195
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.41879806
+0.74430954
+0.98931843
+1.27287340
+1.26489782
+1.24282646
+0.70741457
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.08198310
+0.25720519
+0.23919104
+0.08295478
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
+0.00000000
diff --git a/web_demo/static/favicon.ico b/web_demo/static/favicon.ico
new file mode 100644
index 0000000..63fd3f2
Binary files /dev/null and b/web_demo/static/favicon.ico differ
diff --git a/web_demo/static/icon.png b/web_demo/static/icon.png
new file mode 100644
index 0000000..857b92b
Binary files /dev/null and b/web_demo/static/icon.png differ
diff --git a/web_demo/static/js/DHLiveMini.js b/web_demo/static/js/DHLiveMini.js
new file mode 100644
index 0000000..52075bb
--- /dev/null
+++ b/web_demo/static/js/DHLiveMini.js
@@ -0,0 +1,21 @@
+var Module;
+var createQtAppInstance = (() => {
+ var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined;
+ if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename;
+ return (
+function(createQtAppInstance) {
+ createQtAppInstance = createQtAppInstance || {};
+
+Module=typeof createQtAppInstance!="undefined"?createQtAppInstance:{};var readyPromiseResolve,readyPromiseReject;Module["ready"]=new Promise(function(resolve,reject){readyPromiseResolve=resolve;readyPromiseReject=reject});var moduleOverrides=Object.assign({},Module);var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};var ENVIRONMENT_IS_WEB=typeof window=="object";var ENVIRONMENT_IS_WORKER=typeof importScripts=="function";var ENVIRONMENT_IS_NODE=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string";var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary,setWindowTitle;function logExceptionOnExit(e){if(e instanceof ExitStatus)return;let toLog=e;err("exiting due to exception: "+toLog)}if(ENVIRONMENT_IS_NODE){var fs=require("fs");var nodePath=require("path");if(ENVIRONMENT_IS_WORKER){scriptDirectory=nodePath.dirname(scriptDirectory)+"/"}else{scriptDirectory=__dirname+"/"}read_=(filename,binary)=>{filename=isFileURI(filename)?new URL(filename):nodePath.normalize(filename);return fs.readFileSync(filename,binary?undefined:"utf8")};readBinary=filename=>{var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}return ret};readAsync=(filename,onload,onerror)=>{filename=isFileURI(filename)?new URL(filename):nodePath.normalize(filename);fs.readFile(filename,function(err,data){if(err)onerror(err);else onload(data.buffer)})};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/")}arguments_=process["argv"].slice(2);process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",function(reason){throw reason});quit_=(status,toThrow)=>{if(keepRuntimeAlive()){process["exitCode"]=status;throw toThrow}logExceptionOnExit(toThrow);process["exit"](status)};Module["inspect"]=function(){return"[Emscripten Module object]"}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(typeof document!="undefined"&&document.currentScript){scriptDirectory=document.currentScript.src}if(_scriptDir){scriptDirectory=_scriptDir}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.replace(/[?#].*/,"").lastIndexOf("/")+1)}else{scriptDirectory=""}{read_=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=(url,onload,onerror)=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=()=>{if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}onerror()};xhr.onerror=onerror;xhr.send(null)}}setWindowTitle=title=>document.title=title}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);Object.assign(Module,moduleOverrides);moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var POINTER_SIZE=4;var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime=Module["noExitRuntime"]||true;if(typeof WebAssembly!="object"){abort("no native wasm support detected")}var wasmMemory;var ABORT=false;var EXITSTATUS;function assert(condition,text){if(!condition){abort(text)}}var UTF8Decoder=typeof TextDecoder!="undefined"?new TextDecoder("utf8"):undefined;function UTF8ArrayToString(heapOrArray,idx,maxBytesToRead){var endIdx=idx+maxBytesToRead;var endPtr=idx;while(heapOrArray[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}var str="";while(idx>10,56320|ch&1023)}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function lengthBytesUTF8(str){var len=0;for(var i=0;i=55296&&c<=57343){len+=4;++i}else{len+=3}}return len}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAP64,HEAPU64,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf);Module["HEAP64"]=HEAP64=new BigInt64Array(buf);Module["HEAPU64"]=HEAPU64=new BigUint64Array(buf)}var INITIAL_MEMORY=Module["INITIAL_MEMORY"]||52428800;var wasmTable;var __ATPRERUN__=[];var __ATINIT__=[];var __ATEXIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;function keepRuntimeAlive(){return noExitRuntime}function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;if(!Module["noFSInit"]&&!FS.init.initialized)FS.init();FS.ignorePermissions=false;TTY.init();callRuntimeCallbacks(__ATINIT__)}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnInit(cb){__ATINIT__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function getUniqueRunDependency(id){return id}function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}what="Aborted("+what+")";err(what);ABORT=true;EXITSTATUS=1;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);readyPromiseReject(e);throw e}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return filename.startsWith(dataURIPrefix)}function isFileURI(filename){return filename.startsWith("file://")}var wasmBinaryFile;wasmBinaryFile="DHLiveMini.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile)}function getBinary(file){try{if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}catch(err){abort(err)}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)){if(typeof fetch=="function"&&!isFileURI(wasmBinaryFile)){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw"failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary(wasmBinaryFile)})}else{if(readAsync){return new Promise(function(resolve,reject){readAsync(wasmBinaryFile,function(response){resolve(new Uint8Array(response))},reject)})}}}return Promise.resolve().then(function(){return getBinary(wasmBinaryFile)})}function createWasm(){var info={"env":asmLibraryArg,"wasi_snapshot_preview1":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;wasmMemory=Module["asm"]["memory"];updateGlobalBufferAndViews(wasmMemory.buffer);wasmTable=Module["asm"]["__indirect_function_table"];addOnInit(Module["asm"]["__wasm_call_ctors"]);removeRunDependency("wasm-instantiate")}addRunDependency("wasm-instantiate");function receiveInstantiationResult(result){receiveInstance(result["instance"])}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(function(instance){return instance}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason)})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming=="function"&&!isDataURI(wasmBinaryFile)&&!isFileURI(wasmBinaryFile)&&!ENVIRONMENT_IS_NODE&&typeof fetch=="function"){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiationResult,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");return instantiateArrayBuffer(receiveInstantiationResult)})})}else{return instantiateArrayBuffer(receiveInstantiationResult)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);readyPromiseReject(e)}}instantiateAsync().catch(readyPromiseReject);return{}}var tempDouble;var tempI64;function jsHaveAsyncify(){return typeof Asyncify!=="undefined"}function qt_asyncify_suspend_js(){if(Module.qtSuspendId===undefined)Module.qtSuspendId=0;let sleepFn=wakeUp=>{Module.qtAsyncifyWakeUp=wakeUp};++Module.qtSuspendId;return Asyncify.handleSleep(sleepFn)}function qt_asyncify_resume_js(){let wakeUp=Module.qtAsyncifyWakeUp;if(wakeUp==undefined)return;Module.qtAsyncifyWakeUp=undefined;const suspendId=Module.qtSuspendId;setTimeout(()=>{if(Module.qtSuspendId!==suspendId)return;wakeUp()})}function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status}function callRuntimeCallbacks(callbacks){while(callbacks.length>0){callbacks.shift()(Module)}}var wasmTableMirror=[];function getWasmTableEntry(funcPtr){var func=wasmTableMirror[funcPtr];if(!func){if(funcPtr>=wasmTableMirror.length)wasmTableMirror.length=funcPtr+1;wasmTableMirror[funcPtr]=func=wasmTable.get(funcPtr)}return func}function ___call_sighandler(fp,sig){getWasmTableEntry(fp)(sig)}function ExceptionInfo(excPtr){this.excPtr=excPtr;this.ptr=excPtr-24;this.set_type=function(type){HEAPU32[this.ptr+4>>2]=type};this.get_type=function(){return HEAPU32[this.ptr+4>>2]};this.set_destructor=function(destructor){HEAPU32[this.ptr+8>>2]=destructor};this.get_destructor=function(){return HEAPU32[this.ptr+8>>2]};this.set_refcount=function(refcount){HEAP32[this.ptr>>2]=refcount};this.set_caught=function(caught){caught=caught?1:0;HEAP8[this.ptr+12>>0]=caught};this.get_caught=function(){return HEAP8[this.ptr+12>>0]!=0};this.set_rethrown=function(rethrown){rethrown=rethrown?1:0;HEAP8[this.ptr+13>>0]=rethrown};this.get_rethrown=function(){return HEAP8[this.ptr+13>>0]!=0};this.init=function(type,destructor){this.set_adjusted_ptr(0);this.set_type(type);this.set_destructor(destructor);this.set_refcount(0);this.set_caught(false);this.set_rethrown(false)};this.add_ref=function(){var value=HEAP32[this.ptr>>2];HEAP32[this.ptr>>2]=value+1};this.release_ref=function(){var prev=HEAP32[this.ptr>>2];HEAP32[this.ptr>>2]=prev-1;return prev===1};this.set_adjusted_ptr=function(adjustedPtr){HEAPU32[this.ptr+16>>2]=adjustedPtr};this.get_adjusted_ptr=function(){return HEAPU32[this.ptr+16>>2]};this.get_exception_ptr=function(){var isPointer=___cxa_is_pointer_type(this.get_type());if(isPointer){return HEAPU32[this.excPtr>>2]}var adjusted=this.get_adjusted_ptr();if(adjusted!==0)return adjusted;return this.excPtr}}var exceptionLast=0;var uncaughtExceptionCount=0;function ___cxa_throw(ptr,type,destructor){var info=new ExceptionInfo(ptr);info.init(type,destructor);exceptionLast=ptr;uncaughtExceptionCount++;throw ptr}var PATH={isAbs:path=>path.charAt(0)==="/",splitPath:filename=>{var splitPathRe=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;return splitPathRe.exec(filename).slice(1)},normalizeArray:(parts,allowAboveRoot)=>{var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up;up--){parts.unshift("..")}}return parts},normalize:path=>{var isAbsolute=PATH.isAbs(path),trailingSlash=path.substr(-1)==="/";path=PATH.normalizeArray(path.split("/").filter(p=>!!p),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path},dirname:path=>{var result=PATH.splitPath(path),root=result[0],dir=result[1];if(!root&&!dir){return"."}if(dir){dir=dir.substr(0,dir.length-1)}return root+dir},basename:path=>{if(path==="/")return"/";path=PATH.normalize(path);path=path.replace(/\/$/,"");var lastSlash=path.lastIndexOf("/");if(lastSlash===-1)return path;return path.substr(lastSlash+1)},join:function(){var paths=Array.prototype.slice.call(arguments);return PATH.normalize(paths.join("/"))},join2:(l,r)=>{return PATH.normalize(l+"/"+r)}};function getRandomDevice(){if(typeof crypto=="object"&&typeof crypto["getRandomValues"]=="function"){var randomBuffer=new Uint8Array(1);return()=>{crypto.getRandomValues(randomBuffer);return randomBuffer[0]}}else if(ENVIRONMENT_IS_NODE){try{var crypto_module=require("crypto");return()=>crypto_module["randomBytes"](1)[0]}catch(e){}}return()=>abort("randomDevice")}var PATH_FS={resolve:function(){var resolvedPath="",resolvedAbsolute=false;for(var i=arguments.length-1;i>=-1&&!resolvedAbsolute;i--){var path=i>=0?arguments[i]:FS.cwd();if(typeof path!="string"){throw new TypeError("Arguments to path.resolve must be strings")}else if(!path){return""}resolvedPath=path+"/"+resolvedPath;resolvedAbsolute=PATH.isAbs(path)}resolvedPath=PATH.normalizeArray(resolvedPath.split("/").filter(p=>!!p),!resolvedAbsolute).join("/");return(resolvedAbsolute?"/":"")+resolvedPath||"."},relative:(from,to)=>{from=PATH_FS.resolve(from).substr(1);to=PATH_FS.resolve(to).substr(1);function trim(arr){var start=0;for(;start=0;end--){if(arr[end]!=="")break}if(start>end)return[];return arr.slice(start,end-start+1)}var fromParts=trim(from.split("/"));var toParts=trim(to.split("/"));var length=Math.min(fromParts.length,toParts.length);var samePartsLength=length;for(var i=0;i0?length:lengthBytesUTF8(stringy)+1;var u8array=new Array(len);var numBytesWritten=stringToUTF8Array(stringy,u8array,0,u8array.length);if(dontAddNull)u8array.length=numBytesWritten;return u8array}var TTY={ttys:[],init:function(){},shutdown:function(){},register:function(dev,ops){TTY.ttys[dev]={input:[],output:[],ops:ops};FS.registerDevice(dev,TTY.stream_ops)},stream_ops:{open:function(stream){var tty=TTY.ttys[stream.node.rdev];if(!tty){throw new FS.ErrnoError(43)}stream.tty=tty;stream.seekable=false},close:function(stream){stream.tty.ops.fsync(stream.tty)},fsync:function(stream){stream.tty.ops.fsync(stream.tty)},read:function(stream,buffer,offset,length,pos){if(!stream.tty||!stream.tty.ops.get_char){throw new FS.ErrnoError(60)}var bytesRead=0;for(var i=0;i0){result=buf.slice(0,bytesRead).toString("utf-8")}else{result=null}}else if(typeof window!="undefined"&&typeof window.prompt=="function"){result=window.prompt("Input: ");if(result!==null){result+="\n"}}else if(typeof readline=="function"){result=readline();if(result!==null){result+="\n"}}if(!result){return null}tty.input=intArrayFromString(result,true)}return tty.input.shift()},put_char:function(tty,val){if(val===null||val===10){out(UTF8ArrayToString(tty.output,0));tty.output=[]}else{if(val!=0)tty.output.push(val)}},fsync:function(tty){if(tty.output&&tty.output.length>0){out(UTF8ArrayToString(tty.output,0));tty.output=[]}}},default_tty1_ops:{put_char:function(tty,val){if(val===null||val===10){err(UTF8ArrayToString(tty.output,0));tty.output=[]}else{if(val!=0)tty.output.push(val)}},fsync:function(tty){if(tty.output&&tty.output.length>0){err(UTF8ArrayToString(tty.output,0));tty.output=[]}}}};function zeroMemory(address,size){HEAPU8.fill(0,address,address+size);return address}function alignMemory(size,alignment){return Math.ceil(size/alignment)*alignment}function mmapAlloc(size){size=alignMemory(size,65536);var ptr=_emscripten_builtin_memalign(65536,size);if(!ptr)return 0;return zeroMemory(ptr,size)}var MEMFS={ops_table:null,mount:function(mount){return MEMFS.createNode(null,"/",16384|511,0)},createNode:function(parent,name,mode,dev){if(FS.isBlkdev(mode)||FS.isFIFO(mode)){throw new FS.ErrnoError(63)}if(!MEMFS.ops_table){MEMFS.ops_table={dir:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,lookup:MEMFS.node_ops.lookup,mknod:MEMFS.node_ops.mknod,rename:MEMFS.node_ops.rename,unlink:MEMFS.node_ops.unlink,rmdir:MEMFS.node_ops.rmdir,readdir:MEMFS.node_ops.readdir,symlink:MEMFS.node_ops.symlink},stream:{llseek:MEMFS.stream_ops.llseek}},file:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:{llseek:MEMFS.stream_ops.llseek,read:MEMFS.stream_ops.read,write:MEMFS.stream_ops.write,allocate:MEMFS.stream_ops.allocate,mmap:MEMFS.stream_ops.mmap,msync:MEMFS.stream_ops.msync}},link:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,readlink:MEMFS.node_ops.readlink},stream:{}},chrdev:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:FS.chrdev_stream_ops}}}var node=FS.createNode(parent,name,mode,dev);if(FS.isDir(node.mode)){node.node_ops=MEMFS.ops_table.dir.node;node.stream_ops=MEMFS.ops_table.dir.stream;node.contents={}}else if(FS.isFile(node.mode)){node.node_ops=MEMFS.ops_table.file.node;node.stream_ops=MEMFS.ops_table.file.stream;node.usedBytes=0;node.contents=null}else if(FS.isLink(node.mode)){node.node_ops=MEMFS.ops_table.link.node;node.stream_ops=MEMFS.ops_table.link.stream}else if(FS.isChrdev(node.mode)){node.node_ops=MEMFS.ops_table.chrdev.node;node.stream_ops=MEMFS.ops_table.chrdev.stream}node.timestamp=Date.now();if(parent){parent.contents[name]=node;parent.timestamp=node.timestamp}return node},getFileDataAsTypedArray:function(node){if(!node.contents)return new Uint8Array(0);if(node.contents.subarray)return node.contents.subarray(0,node.usedBytes);return new Uint8Array(node.contents)},expandFileStorage:function(node,newCapacity){var prevCapacity=node.contents?node.contents.length:0;if(prevCapacity>=newCapacity)return;var CAPACITY_DOUBLING_MAX=1024*1024;newCapacity=Math.max(newCapacity,prevCapacity*(prevCapacity>>0);if(prevCapacity!=0)newCapacity=Math.max(newCapacity,256);var oldContents=node.contents;node.contents=new Uint8Array(newCapacity);if(node.usedBytes>0)node.contents.set(oldContents.subarray(0,node.usedBytes),0)},resizeFileStorage:function(node,newSize){if(node.usedBytes==newSize)return;if(newSize==0){node.contents=null;node.usedBytes=0}else{var oldContents=node.contents;node.contents=new Uint8Array(newSize);if(oldContents){node.contents.set(oldContents.subarray(0,Math.min(newSize,node.usedBytes)))}node.usedBytes=newSize}},node_ops:{getattr:function(node){var attr={};attr.dev=FS.isChrdev(node.mode)?node.id:1;attr.ino=node.id;attr.mode=node.mode;attr.nlink=1;attr.uid=0;attr.gid=0;attr.rdev=node.rdev;if(FS.isDir(node.mode)){attr.size=4096}else if(FS.isFile(node.mode)){attr.size=node.usedBytes}else if(FS.isLink(node.mode)){attr.size=node.link.length}else{attr.size=0}attr.atime=new Date(node.timestamp);attr.mtime=new Date(node.timestamp);attr.ctime=new Date(node.timestamp);attr.blksize=4096;attr.blocks=Math.ceil(attr.size/attr.blksize);return attr},setattr:function(node,attr){if(attr.mode!==undefined){node.mode=attr.mode}if(attr.timestamp!==undefined){node.timestamp=attr.timestamp}if(attr.size!==undefined){MEMFS.resizeFileStorage(node,attr.size)}},lookup:function(parent,name){throw FS.genericErrors[44]},mknod:function(parent,name,mode,dev){return MEMFS.createNode(parent,name,mode,dev)},rename:function(old_node,new_dir,new_name){if(FS.isDir(old_node.mode)){var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(new_node){for(var i in new_node.contents){throw new FS.ErrnoError(55)}}}delete old_node.parent.contents[old_node.name];old_node.parent.timestamp=Date.now();old_node.name=new_name;new_dir.contents[new_name]=old_node;new_dir.timestamp=old_node.parent.timestamp;old_node.parent=new_dir},unlink:function(parent,name){delete parent.contents[name];parent.timestamp=Date.now()},rmdir:function(parent,name){var node=FS.lookupNode(parent,name);for(var i in node.contents){throw new FS.ErrnoError(55)}delete parent.contents[name];parent.timestamp=Date.now()},readdir:function(node){var entries=[".",".."];for(var key in node.contents){if(!node.contents.hasOwnProperty(key)){continue}entries.push(key)}return entries},symlink:function(parent,newname,oldpath){var node=MEMFS.createNode(parent,newname,511|40960,0);node.link=oldpath;return node},readlink:function(node){if(!FS.isLink(node.mode)){throw new FS.ErrnoError(28)}return node.link}},stream_ops:{read:function(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=stream.node.usedBytes)return 0;var size=Math.min(stream.node.usedBytes-position,length);if(size>8&&contents.subarray){buffer.set(contents.subarray(position,position+size),offset)}else{for(var i=0;i0||position+length{assert(arrayBuffer,'Loading data file "'+url+'" failed (no arrayBuffer).');onload(new Uint8Array(arrayBuffer));if(dep)removeRunDependency(dep)},event=>{if(onerror){onerror()}else{throw'Loading data file "'+url+'" failed.'}});if(dep)addRunDependency(dep)}var FS={root:null,mounts:[],devices:{},streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:false,ignorePermissions:true,ErrnoError:null,genericErrors:{},filesystems:null,syncFSRequests:0,lookupPath:(path,opts={})=>{path=PATH_FS.resolve(path);if(!path)return{path:"",node:null};var defaults={follow_mount:true,recurse_count:0};opts=Object.assign(defaults,opts);if(opts.recurse_count>8){throw new FS.ErrnoError(32)}var parts=path.split("/").filter(p=>!!p);var current=FS.root;var current_path="/";for(var i=0;i40){throw new FS.ErrnoError(32)}}}}return{path:current_path,node:current}},getPath:node=>{var path;while(true){if(FS.isRoot(node)){var mount=node.mount.mountpoint;if(!path)return mount;return mount[mount.length-1]!=="/"?mount+"/"+path:mount+path}path=path?node.name+"/"+path:node.name;node=node.parent}},hashName:(parentid,name)=>{var hash=0;for(var i=0;i>>0)%FS.nameTable.length},hashAddNode:node=>{var hash=FS.hashName(node.parent.id,node.name);node.name_next=FS.nameTable[hash];FS.nameTable[hash]=node},hashRemoveNode:node=>{var hash=FS.hashName(node.parent.id,node.name);if(FS.nameTable[hash]===node){FS.nameTable[hash]=node.name_next}else{var current=FS.nameTable[hash];while(current){if(current.name_next===node){current.name_next=node.name_next;break}current=current.name_next}}},lookupNode:(parent,name)=>{var errCode=FS.mayLookup(parent);if(errCode){throw new FS.ErrnoError(errCode,parent)}var hash=FS.hashName(parent.id,name);for(var node=FS.nameTable[hash];node;node=node.name_next){var nodeName=node.name;if(node.parent.id===parent.id&&nodeName===name){return node}}return FS.lookup(parent,name)},createNode:(parent,name,mode,rdev)=>{var node=new FS.FSNode(parent,name,mode,rdev);FS.hashAddNode(node);return node},destroyNode:node=>{FS.hashRemoveNode(node)},isRoot:node=>{return node===node.parent},isMountpoint:node=>{return!!node.mounted},isFile:mode=>{return(mode&61440)===32768},isDir:mode=>{return(mode&61440)===16384},isLink:mode=>{return(mode&61440)===40960},isChrdev:mode=>{return(mode&61440)===8192},isBlkdev:mode=>{return(mode&61440)===24576},isFIFO:mode=>{return(mode&61440)===4096},isSocket:mode=>{return(mode&49152)===49152},flagModes:{"r":0,"r+":2,"w":577,"w+":578,"a":1089,"a+":1090},modeStringToFlags:str=>{var flags=FS.flagModes[str];if(typeof flags=="undefined"){throw new Error("Unknown file open mode: "+str)}return flags},flagsToPermissionString:flag=>{var perms=["r","w","rw"][flag&3];if(flag&512){perms+="w"}return perms},nodePermissions:(node,perms)=>{if(FS.ignorePermissions){return 0}if(perms.includes("r")&&!(node.mode&292)){return 2}else if(perms.includes("w")&&!(node.mode&146)){return 2}else if(perms.includes("x")&&!(node.mode&73)){return 2}return 0},mayLookup:dir=>{var errCode=FS.nodePermissions(dir,"x");if(errCode)return errCode;if(!dir.node_ops.lookup)return 2;return 0},mayCreate:(dir,name)=>{try{var node=FS.lookupNode(dir,name);return 20}catch(e){}return FS.nodePermissions(dir,"wx")},mayDelete:(dir,name,isdir)=>{var node;try{node=FS.lookupNode(dir,name)}catch(e){return e.errno}var errCode=FS.nodePermissions(dir,"wx");if(errCode){return errCode}if(isdir){if(!FS.isDir(node.mode)){return 54}if(FS.isRoot(node)||FS.getPath(node)===FS.cwd()){return 10}}else{if(FS.isDir(node.mode)){return 31}}return 0},mayOpen:(node,flags)=>{if(!node){return 44}if(FS.isLink(node.mode)){return 32}else if(FS.isDir(node.mode)){if(FS.flagsToPermissionString(flags)!=="r"||flags&512){return 31}}return FS.nodePermissions(node,FS.flagsToPermissionString(flags))},MAX_OPEN_FDS:4096,nextfd:(fd_start=0,fd_end=FS.MAX_OPEN_FDS)=>{for(var fd=fd_start;fd<=fd_end;fd++){if(!FS.streams[fd]){return fd}}throw new FS.ErrnoError(33)},getStream:fd=>FS.streams[fd],createStream:(stream,fd_start,fd_end)=>{if(!FS.FSStream){FS.FSStream=function(){this.shared={}};FS.FSStream.prototype={};Object.defineProperties(FS.FSStream.prototype,{object:{get:function(){return this.node},set:function(val){this.node=val}},isRead:{get:function(){return(this.flags&2097155)!==1}},isWrite:{get:function(){return(this.flags&2097155)!==0}},isAppend:{get:function(){return this.flags&1024}},flags:{get:function(){return this.shared.flags},set:function(val){this.shared.flags=val}},position:{get:function(){return this.shared.position},set:function(val){this.shared.position=val}}})}stream=Object.assign(new FS.FSStream,stream);var fd=FS.nextfd(fd_start,fd_end);stream.fd=fd;FS.streams[fd]=stream;return stream},closeStream:fd=>{FS.streams[fd]=null},chrdev_stream_ops:{open:stream=>{var device=FS.getDevice(stream.node.rdev);stream.stream_ops=device.stream_ops;if(stream.stream_ops.open){stream.stream_ops.open(stream)}},llseek:()=>{throw new FS.ErrnoError(70)}},major:dev=>dev>>8,minor:dev=>dev&255,makedev:(ma,mi)=>ma<<8|mi,registerDevice:(dev,ops)=>{FS.devices[dev]={stream_ops:ops}},getDevice:dev=>FS.devices[dev],getMounts:mount=>{var mounts=[];var check=[mount];while(check.length){var m=check.pop();mounts.push(m);check.push.apply(check,m.mounts)}return mounts},syncfs:(populate,callback)=>{if(typeof populate=="function"){callback=populate;populate=false}FS.syncFSRequests++;if(FS.syncFSRequests>1){err("warning: "+FS.syncFSRequests+" FS.syncfs operations in flight at once, probably just doing extra work")}var mounts=FS.getMounts(FS.root.mount);var completed=0;function doCallback(errCode){FS.syncFSRequests--;return callback(errCode)}function done(errCode){if(errCode){if(!done.errored){done.errored=true;return doCallback(errCode)}return}if(++completed>=mounts.length){doCallback(null)}}mounts.forEach(mount=>{if(!mount.type.syncfs){return done(null)}mount.type.syncfs(mount,populate,done)})},mount:(type,opts,mountpoint)=>{var root=mountpoint==="/";var pseudo=!mountpoint;var node;if(root&&FS.root){throw new FS.ErrnoError(10)}else if(!root&&!pseudo){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});mountpoint=lookup.path;node=lookup.node;if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}if(!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}}var mount={type:type,opts:opts,mountpoint:mountpoint,mounts:[]};var mountRoot=type.mount(mount);mountRoot.mount=mount;mount.root=mountRoot;if(root){FS.root=mountRoot}else if(node){node.mounted=mount;if(node.mount){node.mount.mounts.push(mount)}}return mountRoot},unmount:mountpoint=>{var lookup=FS.lookupPath(mountpoint,{follow_mount:false});if(!FS.isMountpoint(lookup.node)){throw new FS.ErrnoError(28)}var node=lookup.node;var mount=node.mounted;var mounts=FS.getMounts(mount);Object.keys(FS.nameTable).forEach(hash=>{var current=FS.nameTable[hash];while(current){var next=current.name_next;if(mounts.includes(current.mount)){FS.destroyNode(current)}current=next}});node.mounted=null;var idx=node.mount.mounts.indexOf(mount);node.mount.mounts.splice(idx,1)},lookup:(parent,name)=>{return parent.node_ops.lookup(parent,name)},mknod:(path,mode,dev)=>{var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);if(!name||name==="."||name===".."){throw new FS.ErrnoError(28)}var errCode=FS.mayCreate(parent,name);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.mknod){throw new FS.ErrnoError(63)}return parent.node_ops.mknod(parent,name,mode,dev)},create:(path,mode)=>{mode=mode!==undefined?mode:438;mode&=4095;mode|=32768;return FS.mknod(path,mode,0)},mkdir:(path,mode)=>{mode=mode!==undefined?mode:511;mode&=511|512;mode|=16384;return FS.mknod(path,mode,0)},mkdirTree:(path,mode)=>{var dirs=path.split("/");var d="";for(var i=0;i{if(typeof dev=="undefined"){dev=mode;mode=438}mode|=8192;return FS.mknod(path,mode,dev)},symlink:(oldpath,newpath)=>{if(!PATH_FS.resolve(oldpath)){throw new FS.ErrnoError(44)}var lookup=FS.lookupPath(newpath,{parent:true});var parent=lookup.node;if(!parent){throw new FS.ErrnoError(44)}var newname=PATH.basename(newpath);var errCode=FS.mayCreate(parent,newname);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.symlink){throw new FS.ErrnoError(63)}return parent.node_ops.symlink(parent,newname,oldpath)},rename:(old_path,new_path)=>{var old_dirname=PATH.dirname(old_path);var new_dirname=PATH.dirname(new_path);var old_name=PATH.basename(old_path);var new_name=PATH.basename(new_path);var lookup,old_dir,new_dir;lookup=FS.lookupPath(old_path,{parent:true});old_dir=lookup.node;lookup=FS.lookupPath(new_path,{parent:true});new_dir=lookup.node;if(!old_dir||!new_dir)throw new FS.ErrnoError(44);if(old_dir.mount!==new_dir.mount){throw new FS.ErrnoError(75)}var old_node=FS.lookupNode(old_dir,old_name);var relative=PATH_FS.relative(old_path,new_dirname);if(relative.charAt(0)!=="."){throw new FS.ErrnoError(28)}relative=PATH_FS.relative(new_path,old_dirname);if(relative.charAt(0)!=="."){throw new FS.ErrnoError(55)}var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(old_node===new_node){return}var isdir=FS.isDir(old_node.mode);var errCode=FS.mayDelete(old_dir,old_name,isdir);if(errCode){throw new FS.ErrnoError(errCode)}errCode=new_node?FS.mayDelete(new_dir,new_name,isdir):FS.mayCreate(new_dir,new_name);if(errCode){throw new FS.ErrnoError(errCode)}if(!old_dir.node_ops.rename){throw new FS.ErrnoError(63)}if(FS.isMountpoint(old_node)||new_node&&FS.isMountpoint(new_node)){throw new FS.ErrnoError(10)}if(new_dir!==old_dir){errCode=FS.nodePermissions(old_dir,"w");if(errCode){throw new FS.ErrnoError(errCode)}}FS.hashRemoveNode(old_node);try{old_dir.node_ops.rename(old_node,new_dir,new_name)}catch(e){throw e}finally{FS.hashAddNode(old_node)}},rmdir:path=>{var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);var node=FS.lookupNode(parent,name);var errCode=FS.mayDelete(parent,name,true);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.rmdir){throw new FS.ErrnoError(63)}if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}parent.node_ops.rmdir(parent,name);FS.destroyNode(node)},readdir:path=>{var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;if(!node.node_ops.readdir){throw new FS.ErrnoError(54)}return node.node_ops.readdir(node)},unlink:path=>{var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;if(!parent){throw new FS.ErrnoError(44)}var name=PATH.basename(path);var node=FS.lookupNode(parent,name);var errCode=FS.mayDelete(parent,name,false);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.unlink){throw new FS.ErrnoError(63)}if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}parent.node_ops.unlink(parent,name);FS.destroyNode(node)},readlink:path=>{var lookup=FS.lookupPath(path);var link=lookup.node;if(!link){throw new FS.ErrnoError(44)}if(!link.node_ops.readlink){throw new FS.ErrnoError(28)}return PATH_FS.resolve(FS.getPath(link.parent),link.node_ops.readlink(link))},stat:(path,dontFollow)=>{var lookup=FS.lookupPath(path,{follow:!dontFollow});var node=lookup.node;if(!node){throw new FS.ErrnoError(44)}if(!node.node_ops.getattr){throw new FS.ErrnoError(63)}return node.node_ops.getattr(node)},lstat:path=>{return FS.stat(path,true)},chmod:(path,mode,dontFollow)=>{var node;if(typeof path=="string"){var lookup=FS.lookupPath(path,{follow:!dontFollow});node=lookup.node}else{node=path}if(!node.node_ops.setattr){throw new FS.ErrnoError(63)}node.node_ops.setattr(node,{mode:mode&4095|node.mode&~4095,timestamp:Date.now()})},lchmod:(path,mode)=>{FS.chmod(path,mode,true)},fchmod:(fd,mode)=>{var stream=FS.getStream(fd);if(!stream){throw new FS.ErrnoError(8)}FS.chmod(stream.node,mode)},chown:(path,uid,gid,dontFollow)=>{var node;if(typeof path=="string"){var lookup=FS.lookupPath(path,{follow:!dontFollow});node=lookup.node}else{node=path}if(!node.node_ops.setattr){throw new FS.ErrnoError(63)}node.node_ops.setattr(node,{timestamp:Date.now()})},lchown:(path,uid,gid)=>{FS.chown(path,uid,gid,true)},fchown:(fd,uid,gid)=>{var stream=FS.getStream(fd);if(!stream){throw new FS.ErrnoError(8)}FS.chown(stream.node,uid,gid)},truncate:(path,len)=>{if(len<0){throw new FS.ErrnoError(28)}var node;if(typeof path=="string"){var lookup=FS.lookupPath(path,{follow:true});node=lookup.node}else{node=path}if(!node.node_ops.setattr){throw new FS.ErrnoError(63)}if(FS.isDir(node.mode)){throw new FS.ErrnoError(31)}if(!FS.isFile(node.mode)){throw new FS.ErrnoError(28)}var errCode=FS.nodePermissions(node,"w");if(errCode){throw new FS.ErrnoError(errCode)}node.node_ops.setattr(node,{size:len,timestamp:Date.now()})},ftruncate:(fd,len)=>{var stream=FS.getStream(fd);if(!stream){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(28)}FS.truncate(stream.node,len)},utime:(path,atime,mtime)=>{var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;node.node_ops.setattr(node,{timestamp:Math.max(atime,mtime)})},open:(path,flags,mode)=>{if(path===""){throw new FS.ErrnoError(44)}flags=typeof flags=="string"?FS.modeStringToFlags(flags):flags;mode=typeof mode=="undefined"?438:mode;if(flags&64){mode=mode&4095|32768}else{mode=0}var node;if(typeof path=="object"){node=path}else{path=PATH.normalize(path);try{var lookup=FS.lookupPath(path,{follow:!(flags&131072)});node=lookup.node}catch(e){}}var created=false;if(flags&64){if(node){if(flags&128){throw new FS.ErrnoError(20)}}else{node=FS.mknod(path,mode,0);created=true}}if(!node){throw new FS.ErrnoError(44)}if(FS.isChrdev(node.mode)){flags&=~512}if(flags&65536&&!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}if(!created){var errCode=FS.mayOpen(node,flags);if(errCode){throw new FS.ErrnoError(errCode)}}if(flags&512&&!created){FS.truncate(node,0)}flags&=~(128|512|131072);var stream=FS.createStream({node:node,path:FS.getPath(node),flags:flags,seekable:true,position:0,stream_ops:node.stream_ops,ungotten:[],error:false});if(stream.stream_ops.open){stream.stream_ops.open(stream)}if(Module["logReadFiles"]&&!(flags&1)){if(!FS.readFiles)FS.readFiles={};if(!(path in FS.readFiles)){FS.readFiles[path]=1}}return stream},close:stream=>{if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(stream.getdents)stream.getdents=null;try{if(stream.stream_ops.close){stream.stream_ops.close(stream)}}catch(e){throw e}finally{FS.closeStream(stream.fd)}stream.fd=null},isClosed:stream=>{return stream.fd===null},llseek:(stream,offset,whence)=>{if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(!stream.seekable||!stream.stream_ops.llseek){throw new FS.ErrnoError(70)}if(whence!=0&&whence!=1&&whence!=2){throw new FS.ErrnoError(28)}stream.position=stream.stream_ops.llseek(stream,offset,whence);stream.ungotten=[];return stream.position},read:(stream,buffer,offset,length,position)=>{if(length<0||position<0){throw new FS.ErrnoError(28)}if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(8)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(31)}if(!stream.stream_ops.read){throw new FS.ErrnoError(28)}var seeking=typeof position!="undefined";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(70)}var bytesRead=stream.stream_ops.read(stream,buffer,offset,length,position);if(!seeking)stream.position+=bytesRead;return bytesRead},write:(stream,buffer,offset,length,position,canOwn)=>{if(length<0||position<0){throw new FS.ErrnoError(28)}if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(8)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(31)}if(!stream.stream_ops.write){throw new FS.ErrnoError(28)}if(stream.seekable&&stream.flags&1024){FS.llseek(stream,0,2)}var seeking=typeof position!="undefined";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(70)}var bytesWritten=stream.stream_ops.write(stream,buffer,offset,length,position,canOwn);if(!seeking)stream.position+=bytesWritten;return bytesWritten},allocate:(stream,offset,length)=>{if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(offset<0||length<=0){throw new FS.ErrnoError(28)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(8)}if(!FS.isFile(stream.node.mode)&&!FS.isDir(stream.node.mode)){throw new FS.ErrnoError(43)}if(!stream.stream_ops.allocate){throw new FS.ErrnoError(138)}stream.stream_ops.allocate(stream,offset,length)},mmap:(stream,length,position,prot,flags)=>{if((prot&2)!==0&&(flags&2)===0&&(stream.flags&2097155)!==2){throw new FS.ErrnoError(2)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(2)}if(!stream.stream_ops.mmap){throw new FS.ErrnoError(43)}return stream.stream_ops.mmap(stream,length,position,prot,flags)},msync:(stream,buffer,offset,length,mmapFlags)=>{if(!stream.stream_ops.msync){return 0}return stream.stream_ops.msync(stream,buffer,offset,length,mmapFlags)},munmap:stream=>0,ioctl:(stream,cmd,arg)=>{if(!stream.stream_ops.ioctl){throw new FS.ErrnoError(59)}return stream.stream_ops.ioctl(stream,cmd,arg)},readFile:(path,opts={})=>{opts.flags=opts.flags||0;opts.encoding=opts.encoding||"binary";if(opts.encoding!=="utf8"&&opts.encoding!=="binary"){throw new Error('Invalid encoding type "'+opts.encoding+'"')}var ret;var stream=FS.open(path,opts.flags);var stat=FS.stat(path);var length=stat.size;var buf=new Uint8Array(length);FS.read(stream,buf,0,length,0);if(opts.encoding==="utf8"){ret=UTF8ArrayToString(buf,0)}else if(opts.encoding==="binary"){ret=buf}FS.close(stream);return ret},writeFile:(path,data,opts={})=>{opts.flags=opts.flags||577;var stream=FS.open(path,opts.flags,opts.mode);if(typeof data=="string"){var buf=new Uint8Array(lengthBytesUTF8(data)+1);var actualNumBytes=stringToUTF8Array(data,buf,0,buf.length);FS.write(stream,buf,0,actualNumBytes,undefined,opts.canOwn)}else if(ArrayBuffer.isView(data)){FS.write(stream,data,0,data.byteLength,undefined,opts.canOwn)}else{throw new Error("Unsupported data type")}FS.close(stream)},cwd:()=>FS.currentPath,chdir:path=>{var lookup=FS.lookupPath(path,{follow:true});if(lookup.node===null){throw new FS.ErrnoError(44)}if(!FS.isDir(lookup.node.mode)){throw new FS.ErrnoError(54)}var errCode=FS.nodePermissions(lookup.node,"x");if(errCode){throw new FS.ErrnoError(errCode)}FS.currentPath=lookup.path},createDefaultDirectories:()=>{FS.mkdir("/tmp");FS.mkdir("/home");FS.mkdir("/home/web_user")},createDefaultDevices:()=>{FS.mkdir("/dev");FS.registerDevice(FS.makedev(1,3),{read:()=>0,write:(stream,buffer,offset,length,pos)=>length});FS.mkdev("/dev/null",FS.makedev(1,3));TTY.register(FS.makedev(5,0),TTY.default_tty_ops);TTY.register(FS.makedev(6,0),TTY.default_tty1_ops);FS.mkdev("/dev/tty",FS.makedev(5,0));FS.mkdev("/dev/tty1",FS.makedev(6,0));var random_device=getRandomDevice();FS.createDevice("/dev","random",random_device);FS.createDevice("/dev","urandom",random_device);FS.mkdir("/dev/shm");FS.mkdir("/dev/shm/tmp")},createSpecialDirectories:()=>{FS.mkdir("/proc");var proc_self=FS.mkdir("/proc/self");FS.mkdir("/proc/self/fd");FS.mount({mount:()=>{var node=FS.createNode(proc_self,"fd",16384|511,73);node.node_ops={lookup:(parent,name)=>{var fd=+name;var stream=FS.getStream(fd);if(!stream)throw new FS.ErrnoError(8);var ret={parent:null,mount:{mountpoint:"fake"},node_ops:{readlink:()=>stream.path}};ret.parent=ret;return ret}};return node}},{},"/proc/self/fd")},createStandardStreams:()=>{if(Module["stdin"]){FS.createDevice("/dev","stdin",Module["stdin"])}else{FS.symlink("/dev/tty","/dev/stdin")}if(Module["stdout"]){FS.createDevice("/dev","stdout",null,Module["stdout"])}else{FS.symlink("/dev/tty","/dev/stdout")}if(Module["stderr"]){FS.createDevice("/dev","stderr",null,Module["stderr"])}else{FS.symlink("/dev/tty1","/dev/stderr")}var stdin=FS.open("/dev/stdin",0);var stdout=FS.open("/dev/stdout",1);var stderr=FS.open("/dev/stderr",1)},ensureErrnoError:()=>{if(FS.ErrnoError)return;FS.ErrnoError=function ErrnoError(errno,node){this.node=node;this.setErrno=function(errno){this.errno=errno};this.setErrno(errno);this.message="FS error"};FS.ErrnoError.prototype=new Error;FS.ErrnoError.prototype.constructor=FS.ErrnoError;[44].forEach(code=>{FS.genericErrors[code]=new FS.ErrnoError(code);FS.genericErrors[code].stack=""})},staticInit:()=>{FS.ensureErrnoError();FS.nameTable=new Array(4096);FS.mount(MEMFS,{},"/");FS.createDefaultDirectories();FS.createDefaultDevices();FS.createSpecialDirectories();FS.filesystems={"MEMFS":MEMFS}},init:(input,output,error)=>{FS.init.initialized=true;FS.ensureErrnoError();Module["stdin"]=input||Module["stdin"];Module["stdout"]=output||Module["stdout"];Module["stderr"]=error||Module["stderr"];FS.createStandardStreams()},quit:()=>{FS.init.initialized=false;for(var i=0;i{var mode=0;if(canRead)mode|=292|73;if(canWrite)mode|=146;return mode},findObject:(path,dontResolveLastLink)=>{var ret=FS.analyzePath(path,dontResolveLastLink);if(!ret.exists){return null}return ret.object},analyzePath:(path,dontResolveLastLink)=>{try{var lookup=FS.lookupPath(path,{follow:!dontResolveLastLink});path=lookup.path}catch(e){}var ret={isRoot:false,exists:false,error:0,name:null,path:null,object:null,parentExists:false,parentPath:null,parentObject:null};try{var lookup=FS.lookupPath(path,{parent:true});ret.parentExists=true;ret.parentPath=lookup.path;ret.parentObject=lookup.node;ret.name=PATH.basename(path);lookup=FS.lookupPath(path,{follow:!dontResolveLastLink});ret.exists=true;ret.path=lookup.path;ret.object=lookup.node;ret.name=lookup.node.name;ret.isRoot=lookup.path==="/"}catch(e){ret.error=e.errno}return ret},createPath:(parent,path,canRead,canWrite)=>{parent=typeof parent=="string"?parent:FS.getPath(parent);var parts=path.split("/").reverse();while(parts.length){var part=parts.pop();if(!part)continue;var current=PATH.join2(parent,part);try{FS.mkdir(current)}catch(e){}parent=current}return current},createFile:(parent,name,properties,canRead,canWrite)=>{var path=PATH.join2(typeof parent=="string"?parent:FS.getPath(parent),name);var mode=FS.getMode(canRead,canWrite);return FS.create(path,mode)},createDataFile:(parent,name,data,canRead,canWrite,canOwn)=>{var path=name;if(parent){parent=typeof parent=="string"?parent:FS.getPath(parent);path=name?PATH.join2(parent,name):parent}var mode=FS.getMode(canRead,canWrite);var node=FS.create(path,mode);if(data){if(typeof data=="string"){var arr=new Array(data.length);for(var i=0,len=data.length;i{var path=PATH.join2(typeof parent=="string"?parent:FS.getPath(parent),name);var mode=FS.getMode(!!input,!!output);if(!FS.createDevice.major)FS.createDevice.major=64;var dev=FS.makedev(FS.createDevice.major++,0);FS.registerDevice(dev,{open:stream=>{stream.seekable=false},close:stream=>{if(output&&output.buffer&&output.buffer.length){output(10)}},read:(stream,buffer,offset,length,pos)=>{var bytesRead=0;for(var i=0;i{for(var i=0;i{if(obj.isDevice||obj.isFolder||obj.link||obj.contents)return true;if(typeof XMLHttpRequest!="undefined"){throw new Error("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread.")}else if(read_){try{obj.contents=intArrayFromString(read_(obj.url),true);obj.usedBytes=obj.contents.length}catch(e){throw new FS.ErrnoError(29)}}else{throw new Error("Cannot load without read() or XMLHttpRequest.")}},createLazyFile:(parent,name,url,canRead,canWrite)=>{function LazyUint8Array(){this.lengthKnown=false;this.chunks=[]}LazyUint8Array.prototype.get=function LazyUint8Array_get(idx){if(idx>this.length-1||idx<0){return undefined}var chunkOffset=idx%this.chunkSize;var chunkNum=idx/this.chunkSize|0;return this.getter(chunkNum)[chunkOffset]};LazyUint8Array.prototype.setDataGetter=function LazyUint8Array_setDataGetter(getter){this.getter=getter};LazyUint8Array.prototype.cacheLength=function LazyUint8Array_cacheLength(){var xhr=new XMLHttpRequest;xhr.open("HEAD",url,false);xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);var datalength=Number(xhr.getResponseHeader("Content-length"));var header;var hasByteServing=(header=xhr.getResponseHeader("Accept-Ranges"))&&header==="bytes";var usesGzip=(header=xhr.getResponseHeader("Content-Encoding"))&&header==="gzip";var chunkSize=1024*1024;if(!hasByteServing)chunkSize=datalength;var doXHR=(from,to)=>{if(from>to)throw new Error("invalid range ("+from+", "+to+") or no bytes requested!");if(to>datalength-1)throw new Error("only "+datalength+" bytes available! programmer error!");var xhr=new XMLHttpRequest;xhr.open("GET",url,false);if(datalength!==chunkSize)xhr.setRequestHeader("Range","bytes="+from+"-"+to);xhr.responseType="arraybuffer";if(xhr.overrideMimeType){xhr.overrideMimeType("text/plain; charset=x-user-defined")}xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);if(xhr.response!==undefined){return new Uint8Array(xhr.response||[])}return intArrayFromString(xhr.responseText||"",true)};var lazyArray=this;lazyArray.setDataGetter(chunkNum=>{var start=chunkNum*chunkSize;var end=(chunkNum+1)*chunkSize-1;end=Math.min(end,datalength-1);if(typeof lazyArray.chunks[chunkNum]=="undefined"){lazyArray.chunks[chunkNum]=doXHR(start,end)}if(typeof lazyArray.chunks[chunkNum]=="undefined")throw new Error("doXHR failed!");return lazyArray.chunks[chunkNum]});if(usesGzip||!datalength){chunkSize=datalength=1;datalength=this.getter(0).length;chunkSize=datalength;out("LazyFiles on gzip forces download of the whole file when length is accessed")}this._length=datalength;this._chunkSize=chunkSize;this.lengthKnown=true};if(typeof XMLHttpRequest!="undefined"){if(!ENVIRONMENT_IS_WORKER)throw"Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc";var lazyArray=new LazyUint8Array;Object.defineProperties(lazyArray,{length:{get:function(){if(!this.lengthKnown){this.cacheLength()}return this._length}},chunkSize:{get:function(){if(!this.lengthKnown){this.cacheLength()}return this._chunkSize}}});var properties={isDevice:false,contents:lazyArray}}else{var properties={isDevice:false,url:url}}var node=FS.createFile(parent,name,properties,canRead,canWrite);if(properties.contents){node.contents=properties.contents}else if(properties.url){node.contents=null;node.url=properties.url}Object.defineProperties(node,{usedBytes:{get:function(){return this.contents.length}}});var stream_ops={};var keys=Object.keys(node.stream_ops);keys.forEach(key=>{var fn=node.stream_ops[key];stream_ops[key]=function forceLoadLazyFile(){FS.forceLoadFile(node);return fn.apply(null,arguments)}});function writeChunks(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=contents.length)return 0;var size=Math.min(contents.length-position,length);if(contents.slice){for(var i=0;i{FS.forceLoadFile(node);return writeChunks(stream,buffer,offset,length,position)};stream_ops.mmap=(stream,length,position,prot,flags)=>{FS.forceLoadFile(node);var ptr=mmapAlloc(length);if(!ptr){throw new FS.ErrnoError(48)}writeChunks(stream,HEAP8,ptr,length,position);return{ptr:ptr,allocated:true}};node.stream_ops=stream_ops;return node},createPreloadedFile:(parent,name,url,canRead,canWrite,onload,onerror,dontCreateFile,canOwn,preFinish)=>{var fullname=name?PATH_FS.resolve(PATH.join2(parent,name)):parent;var dep=getUniqueRunDependency("cp "+fullname);function processData(byteArray){function finish(byteArray){if(preFinish)preFinish();if(!dontCreateFile){FS.createDataFile(parent,name,byteArray,canRead,canWrite,canOwn)}if(onload)onload();removeRunDependency(dep)}if(Browser.handledByPreloadPlugin(byteArray,fullname,finish,()=>{if(onerror)onerror();removeRunDependency(dep)})){return}finish(byteArray)}addRunDependency(dep);if(typeof url=="string"){asyncLoad(url,byteArray=>processData(byteArray),onerror)}else{processData(url)}},indexedDB:()=>{return window.indexedDB||window.mozIndexedDB||window.webkitIndexedDB||window.msIndexedDB},DB_NAME:()=>{return"EM_FS_"+window.location.pathname},DB_VERSION:20,DB_STORE_NAME:"FILE_DATA",saveFilesToDB:(paths,onload,onerror)=>{onload=onload||(()=>{});onerror=onerror||(()=>{});var indexedDB=FS.indexedDB();try{var openRequest=indexedDB.open(FS.DB_NAME(),FS.DB_VERSION)}catch(e){return onerror(e)}openRequest.onupgradeneeded=()=>{out("creating db");var db=openRequest.result;db.createObjectStore(FS.DB_STORE_NAME)};openRequest.onsuccess=()=>{var db=openRequest.result;var transaction=db.transaction([FS.DB_STORE_NAME],"readwrite");var files=transaction.objectStore(FS.DB_STORE_NAME);var ok=0,fail=0,total=paths.length;function finish(){if(fail==0)onload();else onerror()}paths.forEach(path=>{var putRequest=files.put(FS.analyzePath(path).object.contents,path);putRequest.onsuccess=()=>{ok++;if(ok+fail==total)finish()};putRequest.onerror=()=>{fail++;if(ok+fail==total)finish()}});transaction.onerror=onerror};openRequest.onerror=onerror},loadFilesFromDB:(paths,onload,onerror)=>{onload=onload||(()=>{});onerror=onerror||(()=>{});var indexedDB=FS.indexedDB();try{var openRequest=indexedDB.open(FS.DB_NAME(),FS.DB_VERSION)}catch(e){return onerror(e)}openRequest.onupgradeneeded=onerror;openRequest.onsuccess=()=>{var db=openRequest.result;try{var transaction=db.transaction([FS.DB_STORE_NAME],"readonly")}catch(e){onerror(e);return}var files=transaction.objectStore(FS.DB_STORE_NAME);var ok=0,fail=0,total=paths.length;function finish(){if(fail==0)onload();else onerror()}paths.forEach(path=>{var getRequest=files.get(path);getRequest.onsuccess=()=>{if(FS.analyzePath(path).exists){FS.unlink(path)}FS.createDataFile(PATH.dirname(path),PATH.basename(path),getRequest.result,true,true,true);ok++;if(ok+fail==total)finish()};getRequest.onerror=()=>{fail++;if(ok+fail==total)finish()}});transaction.onerror=onerror};openRequest.onerror=onerror}};var SYSCALLS={DEFAULT_POLLMASK:5,calculateAt:function(dirfd,path,allowEmpty){if(PATH.isAbs(path)){return path}var dir;if(dirfd===-100){dir=FS.cwd()}else{var dirstream=SYSCALLS.getStreamFromFD(dirfd);dir=dirstream.path}if(path.length==0){if(!allowEmpty){throw new FS.ErrnoError(44)}return dir}return PATH.join2(dir,path)},doStat:function(func,path,buf){try{var stat=func(path)}catch(e){if(e&&e.node&&PATH.normalize(path)!==PATH.normalize(FS.getPath(e.node))){return-54}throw e}HEAP32[buf>>2]=stat.dev;HEAP32[buf+8>>2]=stat.ino;HEAP32[buf+12>>2]=stat.mode;HEAPU32[buf+16>>2]=stat.nlink;HEAP32[buf+20>>2]=stat.uid;HEAP32[buf+24>>2]=stat.gid;HEAP32[buf+28>>2]=stat.rdev;tempI64=[stat.size>>>0,(tempDouble=stat.size,+Math.abs(tempDouble)>=1?tempDouble>0?(Math.min(+Math.floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+40>>2]=tempI64[0],HEAP32[buf+44>>2]=tempI64[1];HEAP32[buf+48>>2]=4096;HEAP32[buf+52>>2]=stat.blocks;var atime=stat.atime.getTime();var mtime=stat.mtime.getTime();var ctime=stat.ctime.getTime();tempI64=[Math.floor(atime/1e3)>>>0,(tempDouble=Math.floor(atime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?(Math.min(+Math.floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+56>>2]=tempI64[0],HEAP32[buf+60>>2]=tempI64[1];HEAPU32[buf+64>>2]=atime%1e3*1e3;tempI64=[Math.floor(mtime/1e3)>>>0,(tempDouble=Math.floor(mtime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?(Math.min(+Math.floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+72>>2]=tempI64[0],HEAP32[buf+76>>2]=tempI64[1];HEAPU32[buf+80>>2]=mtime%1e3*1e3;tempI64=[Math.floor(ctime/1e3)>>>0,(tempDouble=Math.floor(ctime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?(Math.min(+Math.floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+88>>2]=tempI64[0],HEAP32[buf+92>>2]=tempI64[1];HEAPU32[buf+96>>2]=ctime%1e3*1e3;tempI64=[stat.ino>>>0,(tempDouble=stat.ino,+Math.abs(tempDouble)>=1?tempDouble>0?(Math.min(+Math.floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+104>>2]=tempI64[0],HEAP32[buf+108>>2]=tempI64[1];return 0},doMsync:function(addr,stream,len,flags,offset){if(!FS.isFile(stream.node.mode)){throw new FS.ErrnoError(43)}if(flags&2){return 0}var buffer=HEAPU8.slice(addr,addr+len);FS.msync(stream,buffer,offset,len,flags)},varargs:undefined,get:function(){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},getStreamFromFD:function(fd){var stream=FS.getStream(fd);if(!stream)throw new FS.ErrnoError(8);return stream}};function ___syscall_chmod(path,mode){try{path=SYSCALLS.getStr(path);FS.chmod(path,mode);return 0}catch(e){if(typeof FS=="undefined"||!(e instanceof FS.ErrnoError))throw e;return-e.errno}}function ___syscall_faccessat(dirfd,path,amode,flags){try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);if(amode&~7){return-28}var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;if(!node){return-44}var perms="";if(amode&4)perms+="r";if(amode&2)perms+="w";if(amode&1)perms+="x";if(perms&&FS.nodePermissions(node,perms)){return-2}return 0}catch(e){if(typeof FS=="undefined"||!(e instanceof FS.ErrnoError))throw e;return-e.errno}}function ___syscall_fchmod(fd,mode){try{FS.fchmod(fd,mode);return 0}catch(e){if(typeof FS=="undefined"||!(e instanceof FS.ErrnoError))throw e;return-e.errno}}function setErrNo(value){HEAP32[___errno_location()>>2]=value;return value}function ___syscall_fcntl64(fd,cmd,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(cmd){case 0:{var arg=SYSCALLS.get();if(arg<0){return-28}var newStream;newStream=FS.createStream(stream,arg);return newStream.fd}case 1:case 2:return 0;case 3:return stream.flags;case 4:{var arg=SYSCALLS.get();stream.flags|=arg;return 0}case 5:{var arg=SYSCALLS.get();var offset=0;HEAP16[arg+offset>>1]=2;return 0}case 6:case 7:return 0;case 16:case 8:return-28;case 9:setErrNo(28);return-1;default:{return-28}}}catch(e){if(typeof FS=="undefined"||!(e instanceof FS.ErrnoError))throw e;return-e.errno}}function ___syscall_fstat64(fd,buf){try{var stream=SYSCALLS.getStreamFromFD(fd);return SYSCALLS.doStat(FS.stat,stream.path,buf)}catch(e){if(typeof FS=="undefined"||!(e instanceof FS.ErrnoError))throw e;return-e.errno}}var MAX_INT53=9007199254740992;var MIN_INT53=-9007199254740992;function bigintToI53Checked(num){return numMAX_INT53?NaN:Number(num)}function ___syscall_ftruncate64(fd,length){try{length=bigintToI53Checked(length);if(isNaN(length))return-61;FS.ftruncate(fd,length);return 0}catch(e){if(typeof FS=="undefined"||!(e instanceof FS.ErrnoError))throw e;return-e.errno}}function ___syscall_getcwd(buf,size){try{if(size===0)return-28;var cwd=FS.cwd();var cwdLengthInBytes=lengthBytesUTF8(cwd)+1;if(size>>0,(tempDouble=id,+Math.abs(tempDouble)>=1?tempDouble>0?(Math.min(+Math.floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[dirp+pos>>2]=tempI64[0],HEAP32[dirp+pos+4>>2]=tempI64[1];tempI64=[(idx+1)*struct_size>>>0,(tempDouble=(idx+1)*struct_size,+Math.abs(tempDouble)>=1?tempDouble>0?(Math.min(+Math.floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[dirp+pos+8>>2]=tempI64[0],HEAP32[dirp+pos+12>>2]=tempI64[1];HEAP16[dirp+pos+16>>1]=280;HEAP8[dirp+pos+18>>0]=type;stringToUTF8(name,dirp+pos+19,256);pos+=struct_size;idx+=1}FS.llseek(stream,idx*struct_size,0);return pos}catch(e){if(typeof FS=="undefined"||!(e instanceof FS.ErrnoError))throw e;return-e.errno}}function ___syscall_lstat64(path,buf){try{path=SYSCALLS.getStr(path);return SYSCALLS.doStat(FS.lstat,path,buf)}catch(e){if(typeof FS=="undefined"||!(e instanceof FS.ErrnoError))throw e;return-e.errno}}function ___syscall_mkdirat(dirfd,path,mode){try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);path=PATH.normalize(path);if(path[path.length-1]==="/")path=path.substr(0,path.length-1);FS.mkdir(path,mode,0);return 0}catch(e){if(typeof FS=="undefined"||!(e instanceof FS.ErrnoError))throw e;return-e.errno}}function ___syscall_newfstatat(dirfd,path,buf,flags){try{path=SYSCALLS.getStr(path);var nofollow=flags&256;var allowEmpty=flags&4096;flags=flags&~6400;path=SYSCALLS.calculateAt(dirfd,path,allowEmpty);return SYSCALLS.doStat(nofollow?FS.lstat:FS.stat,path,buf)}catch(e){if(typeof FS=="undefined"||!(e instanceof FS.ErrnoError))throw e;return-e.errno}}function ___syscall_openat(dirfd,path,flags,varargs){SYSCALLS.varargs=varargs;try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);var mode=varargs?SYSCALLS.get():0;return FS.open(path,flags,mode).fd}catch(e){if(typeof FS=="undefined"||!(e instanceof FS.ErrnoError))throw e;return-e.errno}}function ___syscall_readlinkat(dirfd,path,buf,bufsize){try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);if(bufsize<=0)return-28;var ret=FS.readlink(path);var len=Math.min(bufsize,lengthBytesUTF8(ret));var endChar=HEAP8[buf+len];stringToUTF8(ret,buf,bufsize+1);HEAP8[buf+len]=endChar;return len}catch(e){if(typeof FS=="undefined"||!(e instanceof FS.ErrnoError))throw e;return-e.errno}}function ___syscall_renameat(olddirfd,oldpath,newdirfd,newpath){try{oldpath=SYSCALLS.getStr(oldpath);newpath=SYSCALLS.getStr(newpath);oldpath=SYSCALLS.calculateAt(olddirfd,oldpath);newpath=SYSCALLS.calculateAt(newdirfd,newpath);FS.rename(oldpath,newpath);return 0}catch(e){if(typeof FS=="undefined"||!(e instanceof FS.ErrnoError))throw e;return-e.errno}}function ___syscall_rmdir(path){try{path=SYSCALLS.getStr(path);FS.rmdir(path);return 0}catch(e){if(typeof FS=="undefined"||!(e instanceof FS.ErrnoError))throw e;return-e.errno}}function ___syscall_stat64(path,buf){try{path=SYSCALLS.getStr(path);return SYSCALLS.doStat(FS.stat,path,buf)}catch(e){if(typeof FS=="undefined"||!(e instanceof FS.ErrnoError))throw e;return-e.errno}}function ___syscall_symlink(target,linkpath){try{target=SYSCALLS.getStr(target);linkpath=SYSCALLS.getStr(linkpath);FS.symlink(target,linkpath);return 0}catch(e){if(typeof FS=="undefined"||!(e instanceof FS.ErrnoError))throw e;return-e.errno}}function ___syscall_truncate64(path,length){try{length=bigintToI53Checked(length);if(isNaN(length))return-61;path=SYSCALLS.getStr(path);FS.truncate(path,length);return 0}catch(e){if(typeof FS=="undefined"||!(e instanceof FS.ErrnoError))throw e;return-e.errno}}function ___syscall_unlinkat(dirfd,path,flags){try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);if(flags===0){FS.unlink(path)}else if(flags===512){FS.rmdir(path)}else{abort("Invalid flags passed to unlinkat")}return 0}catch(e){if(typeof FS=="undefined"||!(e instanceof FS.ErrnoError))throw e;return-e.errno}}function readI53FromI64(ptr){return HEAPU32[ptr>>2]+HEAP32[ptr+4>>2]*4294967296}function ___syscall_utimensat(dirfd,path,times,flags){try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path,true);if(!times){var atime=Date.now();var mtime=atime}else{var seconds=readI53FromI64(times);var nanoseconds=HEAP32[times+8>>2];atime=seconds*1e3+nanoseconds/(1e3*1e3);times+=16;seconds=readI53FromI64(times);nanoseconds=HEAP32[times+8>>2];mtime=seconds*1e3+nanoseconds/(1e3*1e3)}FS.utime(path,atime,mtime);return 0}catch(e){if(typeof FS=="undefined"||!(e instanceof FS.ErrnoError))throw e;return-e.errno}}function embindRepr(v){if(v===null){return"null"}var t=typeof v;if(t==="object"||t==="array"||t==="function"){return v.toString()}else{return""+v}}function embind_init_charCodes(){var codes=new Array(256);for(var i=0;i<256;++i){codes[i]=String.fromCharCode(i)}embind_charCodes=codes}var embind_charCodes=undefined;function readLatin1String(ptr){var ret="";var c=ptr;while(HEAPU8[c]){ret+=embind_charCodes[HEAPU8[c++]]}return ret}var awaitingDependencies={};var registeredTypes={};var typeDependencies={};var char_0=48;var char_9=57;function makeLegalFunctionName(name){if(undefined===name){return"_unknown"}name=name.replace(/[^a-zA-Z0-9_]/g,"$");var f=name.charCodeAt(0);if(f>=char_0&&f<=char_9){return"_"+name}return name}function createNamedFunction(name,body){name=makeLegalFunctionName(name);return new Function("body","return function "+name+"() {\n"+' "use strict";'+" return body.apply(this, arguments);\n"+"};\n")(body)}function extendError(baseErrorType,errorName){var errorClass=createNamedFunction(errorName,function(message){this.name=errorName;this.message=message;var stack=new Error(message).stack;if(stack!==undefined){this.stack=this.toString()+"\n"+stack.replace(/^Error(:[^\n]*)?\n/,"")}});errorClass.prototype=Object.create(baseErrorType.prototype);errorClass.prototype.constructor=errorClass;errorClass.prototype.toString=function(){if(this.message===undefined){return this.name}else{return this.name+": "+this.message}};return errorClass}var BindingError=undefined;function throwBindingError(message){throw new BindingError(message)}var InternalError=undefined;function throwInternalError(message){throw new InternalError(message)}function whenDependentTypesAreResolved(myTypes,dependentTypes,getTypeConverters){myTypes.forEach(function(type){typeDependencies[type]=dependentTypes});function onComplete(typeConverters){var myTypeConverters=getTypeConverters(typeConverters);if(myTypeConverters.length!==myTypes.length){throwInternalError("Mismatched type converter count")}for(var i=0;i{if(registeredTypes.hasOwnProperty(dt)){typeConverters[i]=registeredTypes[dt]}else{unregisteredTypes.push(dt);if(!awaitingDependencies.hasOwnProperty(dt)){awaitingDependencies[dt]=[]}awaitingDependencies[dt].push(()=>{typeConverters[i]=registeredTypes[dt];++registered;if(registered===unregisteredTypes.length){onComplete(typeConverters)}})}});if(0===unregisteredTypes.length){onComplete(typeConverters)}}function registerType(rawType,registeredInstance,options={}){if(!("argPackAdvance"in registeredInstance)){throw new TypeError("registerType registeredInstance requires argPackAdvance")}var name=registeredInstance.name;if(!rawType){throwBindingError('type "'+name+'" must have a positive integer typeid pointer')}if(registeredTypes.hasOwnProperty(rawType)){if(options.ignoreDuplicateRegistrations){return}else{throwBindingError("Cannot register type '"+name+"' twice")}}registeredTypes[rawType]=registeredInstance;delete typeDependencies[rawType];if(awaitingDependencies.hasOwnProperty(rawType)){var callbacks=awaitingDependencies[rawType];delete awaitingDependencies[rawType];callbacks.forEach(cb=>cb())}}function integerReadValueFromPointer(name,shift,signed){switch(shift){case 0:return signed?function readS8FromPointer(pointer){return HEAP8[pointer]}:function readU8FromPointer(pointer){return HEAPU8[pointer]};case 1:return signed?function readS16FromPointer(pointer){return HEAP16[pointer>>1]}:function readU16FromPointer(pointer){return HEAPU16[pointer>>1]};case 2:return signed?function readS32FromPointer(pointer){return HEAP32[pointer>>2]}:function readU32FromPointer(pointer){return HEAPU32[pointer>>2]};case 3:return signed?function readS64FromPointer(pointer){return HEAP64[pointer>>3]}:function readU64FromPointer(pointer){return HEAPU64[pointer>>3]};default:throw new TypeError("Unknown integer type: "+name)}}function __embind_register_bigint(primitiveType,name,size,minRange,maxRange){name=readLatin1String(name);var shift=getShiftFromSize(size);var isUnsignedType=name.indexOf("u")!=-1;if(isUnsignedType){maxRange=(1n<<64n)-1n}registerType(primitiveType,{name:name,"fromWireType":function(value){return value},"toWireType":function(destructors,value){if(typeof value!="bigint"&&typeof value!="number"){throw new TypeError('Cannot convert "'+embindRepr(value)+'" to '+this.name)}if(valuemaxRange){throw new TypeError('Passing a number "'+embindRepr(value)+'" from JS side to C/C++ side to an argument of type "'+name+'", which is outside the valid range ['+minRange+", "+maxRange+"]!")}return value},"argPackAdvance":8,"readValueFromPointer":integerReadValueFromPointer(name,shift,!isUnsignedType),destructorFunction:null})}function getShiftFromSize(size){switch(size){case 1:return 0;case 2:return 1;case 4:return 2;case 8:return 3;default:throw new TypeError("Unknown type size: "+size)}}function __embind_register_bool(rawType,name,size,trueValue,falseValue){var shift=getShiftFromSize(size);name=readLatin1String(name);registerType(rawType,{name:name,"fromWireType":function(wt){return!!wt},"toWireType":function(destructors,o){return o?trueValue:falseValue},"argPackAdvance":8,"readValueFromPointer":function(pointer){var heap;if(size===1){heap=HEAP8}else if(size===2){heap=HEAP16}else if(size===4){heap=HEAP32}else{throw new TypeError("Unknown boolean type size: "+name)}return this["fromWireType"](heap[pointer>>shift])},destructorFunction:null})}var emval_free_list=[];var emval_handle_array=[{},{value:undefined},{value:null},{value:true},{value:false}];function __emval_decref(handle){if(handle>4&&0===--emval_handle_array[handle].refcount){emval_handle_array[handle]=undefined;emval_free_list.push(handle)}}function count_emval_handles(){var count=0;for(var i=5;i{if(!handle){throwBindingError("Cannot use deleted val. handle = "+handle)}return emval_handle_array[handle].value},toHandle:value=>{switch(value){case undefined:return 1;case null:return 2;case true:return 3;case false:return 4;default:{var handle=emval_free_list.length?emval_free_list.pop():emval_handle_array.length;emval_handle_array[handle]={refcount:1,value:value};return handle}}}};function simpleReadValueFromPointer(pointer){return this["fromWireType"](HEAP32[pointer>>2])}function __embind_register_emval(rawType,name){name=readLatin1String(name);registerType(rawType,{name:name,"fromWireType":function(handle){var rv=Emval.toValue(handle);__emval_decref(handle);return rv},"toWireType":function(destructors,value){return Emval.toHandle(value)},"argPackAdvance":8,"readValueFromPointer":simpleReadValueFromPointer,destructorFunction:null})}function floatReadValueFromPointer(name,shift){switch(shift){case 2:return function(pointer){return this["fromWireType"](HEAPF32[pointer>>2])};case 3:return function(pointer){return this["fromWireType"](HEAPF64[pointer>>3])};default:throw new TypeError("Unknown float type: "+name)}}function __embind_register_float(rawType,name,size){var shift=getShiftFromSize(size);name=readLatin1String(name);registerType(rawType,{name:name,"fromWireType":function(value){return value},"toWireType":function(destructors,value){return value},"argPackAdvance":8,"readValueFromPointer":floatReadValueFromPointer(name,shift),destructorFunction:null})}function new_(constructor,argumentList){if(!(constructor instanceof Function)){throw new TypeError("new_ called with constructor type "+typeof constructor+" which is not a function")}var dummy=createNamedFunction(constructor.name||"unknownFunctionName",function(){});dummy.prototype=constructor.prototype;var obj=new dummy;var r=constructor.apply(obj,argumentList);return r instanceof Object?r:obj}function runDestructors(destructors){while(destructors.length){var ptr=destructors.pop();var del=destructors.pop();del(ptr)}}function craftInvokerFunction(humanName,argTypes,classType,cppInvokerFunc,cppTargetFunc){var argCount=argTypes.length;if(argCount<2){throwBindingError("argTypes array size mismatch! Must at least get return value and 'this' types!")}var isClassMethodFunc=argTypes[1]!==null&&classType!==null;var needsDestructorStack=false;for(var i=1;i0?", ":"")+argsListWired}invokerFnBody+=(returns?"var rv = ":"")+"invoker(fn"+(argsListWired.length>0?", ":"")+argsListWired+");\n";if(needsDestructorStack){invokerFnBody+="runDestructors(destructors);\n"}else{for(var i=isClassMethodFunc?1:2;i>2])}return array}function replacePublicSymbol(name,value,numArguments){if(!Module.hasOwnProperty(name)){throwInternalError("Replacing nonexistant public symbol")}if(undefined!==Module[name].overloadTable&&undefined!==numArguments){Module[name].overloadTable[numArguments]=value}else{Module[name]=value;Module[name].argCount=numArguments}}function embind__requireFunction(signature,rawFunction){signature=readLatin1String(signature);function makeDynCaller(){return getWasmTableEntry(rawFunction)}var fp=makeDynCaller();if(typeof fp!="function"){throwBindingError("unknown function pointer with signature "+signature+": "+rawFunction)}return fp}var UnboundTypeError=undefined;function getTypeName(type){var ptr=___getTypeName(type);var rv=readLatin1String(ptr);_free(ptr);return rv}function throwUnboundTypeError(message,types){var unboundTypes=[];var seen={};function visit(type){if(seen[type]){return}if(registeredTypes[type]){return}if(typeDependencies[type]){typeDependencies[type].forEach(visit);return}unboundTypes.push(type);seen[type]=true}types.forEach(visit);throw new UnboundTypeError(message+": "+unboundTypes.map(getTypeName).join([", "]))}function __embind_register_function(name,argCount,rawArgTypesAddr,signature,rawInvoker,fn){var argTypes=heap32VectorToArray(argCount,rawArgTypesAddr);name=readLatin1String(name);rawInvoker=embind__requireFunction(signature,rawInvoker);exposePublicSymbol(name,function(){throwUnboundTypeError("Cannot call "+name+" due to unbound types",argTypes)},argCount-1);whenDependentTypesAreResolved([],argTypes,function(argTypes){var invokerArgsArray=[argTypes[0],null].concat(argTypes.slice(1));replacePublicSymbol(name,craftInvokerFunction(name,invokerArgsArray,null,rawInvoker,fn),argCount-1);return[]})}function __embind_register_integer(primitiveType,name,size,minRange,maxRange){name=readLatin1String(name);if(maxRange===-1){maxRange=4294967295}var shift=getShiftFromSize(size);var fromWireType=value=>value;if(minRange===0){var bitshift=32-8*size;fromWireType=value=>value<>>bitshift}var isUnsignedType=name.includes("unsigned");var checkAssertions=(value,toTypeName)=>{};var toWireType;if(isUnsignedType){toWireType=function(destructors,value){checkAssertions(value,this.name);return value>>>0}}else{toWireType=function(destructors,value){checkAssertions(value,this.name);return value}}registerType(primitiveType,{name:name,"fromWireType":fromWireType,"toWireType":toWireType,"argPackAdvance":8,"readValueFromPointer":integerReadValueFromPointer(name,shift,minRange!==0),destructorFunction:null})}function __embind_register_memory_view(rawType,dataTypeIndex,name){var typeMapping=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array,BigInt64Array,BigUint64Array];var TA=typeMapping[dataTypeIndex];function decodeMemoryView(handle){handle=handle>>2;var heap=HEAPU32;var size=heap[handle];var data=heap[handle+1];return new TA(buffer,data,size)}name=readLatin1String(name);registerType(rawType,{name:name,"fromWireType":decodeMemoryView,"argPackAdvance":8,"readValueFromPointer":decodeMemoryView},{ignoreDuplicateRegistrations:true})}function __embind_register_std_string(rawType,name){name=readLatin1String(name);var stdStringIsUTF8=name==="std::string";registerType(rawType,{name:name,"fromWireType":function(value){var length=HEAPU32[value>>2];var payload=value+4;var str;if(stdStringIsUTF8){var decodeStartPtr=payload;for(var i=0;i<=length;++i){var currentBytePtr=payload+i;if(i==length||HEAPU8[currentBytePtr]==0){var maxRead=currentBytePtr-decodeStartPtr;var stringSegment=UTF8ToString(decodeStartPtr,maxRead);if(str===undefined){str=stringSegment}else{str+=String.fromCharCode(0);str+=stringSegment}decodeStartPtr=currentBytePtr+1}}}else{var a=new Array(length);for(var i=0;i>2]=length;if(stdStringIsUTF8&&valueIsOfTypeString){stringToUTF8(value,ptr,length+1)}else{if(valueIsOfTypeString){for(var i=0;i255){_free(ptr);throwBindingError("String has UTF-16 code units that do not fit in 8 bits")}HEAPU8[ptr+i]=charCode}}else{for(var i=0;i>1;var maxIdx=idx+maxBytesToRead/2;while(!(idx>=maxIdx)&&HEAPU16[idx])++idx;endPtr=idx<<1;if(endPtr-ptr>32&&UTF16Decoder)return UTF16Decoder.decode(HEAPU8.subarray(ptr,endPtr));var str="";for(var i=0;!(i>=maxBytesToRead/2);++i){var codeUnit=HEAP16[ptr+i*2>>1];if(codeUnit==0)break;str+=String.fromCharCode(codeUnit)}return str}function stringToUTF16(str,outPtr,maxBytesToWrite){if(maxBytesToWrite===undefined){maxBytesToWrite=2147483647}if(maxBytesToWrite<2)return 0;maxBytesToWrite-=2;var startPtr=outPtr;var numCharsToWrite=maxBytesToWrite>1]=codeUnit;outPtr+=2}HEAP16[outPtr>>1]=0;return outPtr-startPtr}function lengthBytesUTF16(str){return str.length*2}function UTF32ToString(ptr,maxBytesToRead){var i=0;var str="";while(!(i>=maxBytesToRead/4)){var utf32=HEAP32[ptr+i*4>>2];if(utf32==0)break;++i;if(utf32>=65536){var ch=utf32-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}else{str+=String.fromCharCode(utf32)}}return str}function stringToUTF32(str,outPtr,maxBytesToWrite){if(maxBytesToWrite===undefined){maxBytesToWrite=2147483647}if(maxBytesToWrite<4)return 0;var startPtr=outPtr;var endPtr=startPtr+maxBytesToWrite-4;for(var i=0;i=55296&&codeUnit<=57343){var trailSurrogate=str.charCodeAt(++i);codeUnit=65536+((codeUnit&1023)<<10)|trailSurrogate&1023}HEAP32[outPtr>>2]=codeUnit;outPtr+=4;if(outPtr+4>endPtr)break}HEAP32[outPtr>>2]=0;return outPtr-startPtr}function lengthBytesUTF32(str){var len=0;for(var i=0;i=55296&&codeUnit<=57343)++i;len+=4}return len}function __embind_register_std_wstring(rawType,charSize,name){name=readLatin1String(name);var decodeString,encodeString,getHeap,lengthBytesUTF,shift;if(charSize===2){decodeString=UTF16ToString;encodeString=stringToUTF16;lengthBytesUTF=lengthBytesUTF16;getHeap=()=>HEAPU16;shift=1}else if(charSize===4){decodeString=UTF32ToString;encodeString=stringToUTF32;lengthBytesUTF=lengthBytesUTF32;getHeap=()=>HEAPU32;shift=2}registerType(rawType,{name:name,"fromWireType":function(value){var length=HEAPU32[value>>2];var HEAP=getHeap();var str;var decodeStartPtr=value+4;for(var i=0;i<=length;++i){var currentBytePtr=value+4+i*charSize;if(i==length||HEAP[currentBytePtr>>shift]==0){var maxReadBytes=currentBytePtr-decodeStartPtr;var stringSegment=decodeString(decodeStartPtr,maxReadBytes);if(str===undefined){str=stringSegment}else{str+=String.fromCharCode(0);str+=stringSegment}decodeStartPtr=currentBytePtr+charSize}}_free(value);return str},"toWireType":function(destructors,value){if(!(typeof value=="string")){throwBindingError("Cannot pass non-string to C++ string type "+name)}var length=lengthBytesUTF(value);var ptr=_malloc(4+length+charSize);HEAPU32[ptr>>2]=length>>shift;encodeString(value,ptr+4,length+charSize);if(destructors!==null){destructors.push(_free,ptr)}return ptr},"argPackAdvance":8,"readValueFromPointer":simpleReadValueFromPointer,destructorFunction:function(ptr){_free(ptr)}})}function __embind_register_void(rawType,name){name=readLatin1String(name);registerType(rawType,{isVoid:true,name:name,"argPackAdvance":0,"fromWireType":function(){return undefined},"toWireType":function(destructors,o){return undefined}})}var nowIsMonotonic=true;function __emscripten_get_now_is_monotonic(){return nowIsMonotonic}function requireRegisteredType(rawType,humanName){var impl=registeredTypes[rawType];if(undefined===impl){throwBindingError(humanName+" has unknown type "+getTypeName(rawType))}return impl}function __emval_as(handle,returnType,destructorsRef){handle=Emval.toValue(handle);returnType=requireRegisteredType(returnType,"emval::as");var destructors=[];var rd=Emval.toHandle(destructors);HEAPU32[destructorsRef>>2]=rd;return returnType["toWireType"](destructors,handle)}function emval_allocateDestructors(destructorsRef){var destructors=[];HEAPU32[destructorsRef>>2]=Emval.toHandle(destructors);return destructors}var emval_symbols={};function getStringOrSymbol(address){var symbol=emval_symbols[address];if(symbol===undefined){return readLatin1String(address)}return symbol}var emval_methodCallers=[];function __emval_call_method(caller,handle,methodName,destructorsRef,args){caller=emval_methodCallers[caller];handle=Emval.toValue(handle);methodName=getStringOrSymbol(methodName);return caller(handle,methodName,emval_allocateDestructors(destructorsRef),args)}function __emval_call_void_method(caller,handle,methodName,args){caller=emval_methodCallers[caller];handle=Emval.toValue(handle);methodName=getStringOrSymbol(methodName);caller(handle,methodName,null,args)}function emval_get_global(){if(typeof globalThis=="object"){return globalThis}return function(){return Function}()("return this")()}function __emval_get_global(name){if(name===0){return Emval.toHandle(emval_get_global())}else{name=getStringOrSymbol(name);return Emval.toHandle(emval_get_global()[name])}}function emval_addMethodCaller(caller){var id=emval_methodCallers.length;emval_methodCallers.push(caller);return id}function emval_lookupTypes(argCount,argTypes){var a=new Array(argCount);for(var i=0;i>2],"parameter "+i)}return a}var emval_registeredMethods=[];function __emval_get_method_caller(argCount,argTypes){var types=emval_lookupTypes(argCount,argTypes);var retType=types[0];var signatureName=retType.name+"_$"+types.slice(1).map(function(t){return t.name}).join("_")+"$";var returnId=emval_registeredMethods[signatureName];if(returnId!==undefined){return returnId}var params=["retType"];var args=[retType];var argsList="";for(var i=0;i4){emval_handle_array[handle].refcount+=1}}function __emval_new_cstring(v){return Emval.toHandle(getStringOrSymbol(v))}function __emval_new_object(){return Emval.toHandle({})}function __emval_run_destructors(handle){var destructors=Emval.toValue(handle);runDestructors(destructors);__emval_decref(handle)}function __emval_set_property(handle,key,value){handle=Emval.toValue(handle);key=Emval.toValue(key);value=Emval.toValue(value);handle[key]=value}function __emval_take_value(type,arg){type=requireRegisteredType(type,"_emval_take_value");var v=type["readValueFromPointer"](arg);return Emval.toHandle(v)}function __isLeapYear(year){return year%4===0&&(year%100!==0||year%400===0)}var __MONTH_DAYS_LEAP_CUMULATIVE=[0,31,60,91,121,152,182,213,244,274,305,335];var __MONTH_DAYS_REGULAR_CUMULATIVE=[0,31,59,90,120,151,181,212,243,273,304,334];function __yday_from_date(date){var isLeapYear=__isLeapYear(date.getFullYear());var monthDaysCumulative=isLeapYear?__MONTH_DAYS_LEAP_CUMULATIVE:__MONTH_DAYS_REGULAR_CUMULATIVE;var yday=monthDaysCumulative[date.getMonth()]+date.getDate()-1;return yday}function __localtime_js(time,tmPtr){var date=new Date(readI53FromI64(time)*1e3);HEAP32[tmPtr>>2]=date.getSeconds();HEAP32[tmPtr+4>>2]=date.getMinutes();HEAP32[tmPtr+8>>2]=date.getHours();HEAP32[tmPtr+12>>2]=date.getDate();HEAP32[tmPtr+16>>2]=date.getMonth();HEAP32[tmPtr+20>>2]=date.getFullYear()-1900;HEAP32[tmPtr+24>>2]=date.getDay();var yday=__yday_from_date(date)|0;HEAP32[tmPtr+28>>2]=yday;HEAP32[tmPtr+36>>2]=-(date.getTimezoneOffset()*60);var start=new Date(date.getFullYear(),0,1);var summerOffset=new Date(date.getFullYear(),6,1).getTimezoneOffset();var winterOffset=start.getTimezoneOffset();var dst=(summerOffset!=winterOffset&&date.getTimezoneOffset()==Math.min(winterOffset,summerOffset))|0;HEAP32[tmPtr+32>>2]=dst}function __mktime_js(tmPtr){var date=new Date(HEAP32[tmPtr+20>>2]+1900,HEAP32[tmPtr+16>>2],HEAP32[tmPtr+12>>2],HEAP32[tmPtr+8>>2],HEAP32[tmPtr+4>>2],HEAP32[tmPtr>>2],0);var dst=HEAP32[tmPtr+32>>2];var guessedOffset=date.getTimezoneOffset();var start=new Date(date.getFullYear(),0,1);var summerOffset=new Date(date.getFullYear(),6,1).getTimezoneOffset();var winterOffset=start.getTimezoneOffset();var dstOffset=Math.min(winterOffset,summerOffset);if(dst<0){HEAP32[tmPtr+32>>2]=Number(summerOffset!=winterOffset&&dstOffset==guessedOffset)}else if(dst>0!=(dstOffset==guessedOffset)){var nonDstOffset=Math.max(winterOffset,summerOffset);var trueOffset=dst>0?dstOffset:nonDstOffset;date.setTime(date.getTime()+(trueOffset-guessedOffset)*6e4)}HEAP32[tmPtr+24>>2]=date.getDay();var yday=__yday_from_date(date)|0;HEAP32[tmPtr+28>>2]=yday;HEAP32[tmPtr>>2]=date.getSeconds();HEAP32[tmPtr+4>>2]=date.getMinutes();HEAP32[tmPtr+8>>2]=date.getHours();HEAP32[tmPtr+12>>2]=date.getDate();HEAP32[tmPtr+16>>2]=date.getMonth();HEAP32[tmPtr+20>>2]=date.getYear();return date.getTime()/1e3|0}function __mmap_js(len,prot,flags,fd,off,allocated,addr){try{var stream=SYSCALLS.getStreamFromFD(fd);var res=FS.mmap(stream,len,off,prot,flags);var ptr=res.ptr;HEAP32[allocated>>2]=res.allocated;HEAPU32[addr>>2]=ptr;return 0}catch(e){if(typeof FS=="undefined"||!(e instanceof FS.ErrnoError))throw e;return-e.errno}}function __munmap_js(addr,len,prot,flags,fd,offset){try{var stream=SYSCALLS.getStreamFromFD(fd);if(prot&2){SYSCALLS.doMsync(addr,stream,len,flags,offset)}FS.munmap(stream)}catch(e){if(typeof FS=="undefined"||!(e instanceof FS.ErrnoError))throw e;return-e.errno}}function allocateUTF8(str){var size=lengthBytesUTF8(str)+1;var ret=_malloc(size);if(ret)stringToUTF8Array(str,HEAP8,ret,size);return ret}function __tzset_js(timezone,daylight,tzname){var currentYear=(new Date).getFullYear();var winter=new Date(currentYear,0,1);var summer=new Date(currentYear,6,1);var winterOffset=winter.getTimezoneOffset();var summerOffset=summer.getTimezoneOffset();var stdTimezoneOffset=Math.max(winterOffset,summerOffset);HEAPU32[timezone>>2]=stdTimezoneOffset*60;HEAP32[daylight>>2]=Number(winterOffset!=summerOffset);function extractZone(date){var match=date.toTimeString().match(/\(([A-Za-z ]+)\)$/);return match?match[1]:"GMT"}var winterName=extractZone(winter);var summerName=extractZone(summer);var winterNamePtr=allocateUTF8(winterName);var summerNamePtr=allocateUTF8(summerName);if(summerOffset>2]=winterNamePtr;HEAPU32[tzname+4>>2]=summerNamePtr}else{HEAPU32[tzname>>2]=summerNamePtr;HEAPU32[tzname+4>>2]=winterNamePtr}}function _abort(){abort("")}function _emscripten_date_now(){return Date.now()}var _emscripten_get_now;if(ENVIRONMENT_IS_NODE){_emscripten_get_now=()=>{var t=process["hrtime"]();return t[0]*1e3+t[1]/1e6}}else _emscripten_get_now=()=>performance.now();var IDBStore={indexedDB:function(){if(typeof indexedDB!="undefined")return indexedDB;var ret=null;if(typeof window=="object")ret=window.indexedDB||window.mozIndexedDB||window.webkitIndexedDB||window.msIndexedDB;assert(ret,"IDBStore used, but indexedDB not supported");return ret},DB_VERSION:22,DB_STORE_NAME:"FILE_DATA",dbs:{},blobs:[0],getDB:function(name,callback){var db=IDBStore.dbs[name];if(db){return callback(null,db)}var req;try{req=IDBStore.indexedDB().open(name,IDBStore.DB_VERSION)}catch(e){return callback(e)}req.onupgradeneeded=function(e){var db=e.target.result;var transaction=e.target.transaction;var fileStore;if(db.objectStoreNames.contains(IDBStore.DB_STORE_NAME)){fileStore=transaction.objectStore(IDBStore.DB_STORE_NAME)}else{fileStore=db.createObjectStore(IDBStore.DB_STORE_NAME)}};req.onsuccess=function(){db=req.result;IDBStore.dbs[name]=db;callback(null,db)};req.onerror=function(e){callback(this.error);e.preventDefault()}},getStore:function(dbName,type,callback){IDBStore.getDB(dbName,function(error,db){if(error)return callback(error);var transaction=db.transaction([IDBStore.DB_STORE_NAME],type);transaction.onerror=function(e){callback(this.error||"unknown error");e.preventDefault()};var store=transaction.objectStore(IDBStore.DB_STORE_NAME);callback(null,store)})},getFile:function(dbName,id,callback){IDBStore.getStore(dbName,"readonly",function(err,store){if(err)return callback(err);var req=store.get(id);req.onsuccess=function(event){var result=event.target.result;if(!result){return callback("file "+id+" not found")}return callback(null,result)};req.onerror=function(error){callback(error)}})},setFile:function(dbName,id,data,callback){IDBStore.getStore(dbName,"readwrite",function(err,store){if(err)return callback(err);var req=store.put(data,id);req.onsuccess=function(event){callback()};req.onerror=function(error){callback(error)}})},deleteFile:function(dbName,id,callback){IDBStore.getStore(dbName,"readwrite",function(err,store){if(err)return callback(err);var req=store.delete(id);req.onsuccess=function(event){callback()};req.onerror=function(error){callback(error)}})},existsFile:function(dbName,id,callback){IDBStore.getStore(dbName,"readonly",function(err,store){if(err)return callback(err);var req=store.count(id);req.onsuccess=function(event){callback(null,event.target.result>0)};req.onerror=function(error){callback(error)}})}};function _emscripten_idb_async_delete(db,id,arg,ondelete,onerror){IDBStore.deleteFile(UTF8ToString(db),UTF8ToString(id),function(error){if(error){if(onerror)getWasmTableEntry(onerror)(arg);return}if(ondelete)getWasmTableEntry(ondelete)(arg)})}function _emscripten_idb_async_exists(db,id,arg,oncheck,onerror){IDBStore.existsFile(UTF8ToString(db),UTF8ToString(id),function(error,exists){if(error){if(onerror)getWasmTableEntry(onerror)(arg);return}if(oncheck)getWasmTableEntry(oncheck)(arg,exists)})}function _emscripten_idb_async_load(db,id,arg,onload,onerror){IDBStore.getFile(UTF8ToString(db),UTF8ToString(id),function(error,byteArray){if(error){if(onerror)getWasmTableEntry(onerror)(arg);return}var buffer=_malloc(byteArray.length);HEAPU8.set(byteArray,buffer);getWasmTableEntry(onload)(arg,buffer,byteArray.length);_free(buffer)})}function _emscripten_idb_async_store(db,id,ptr,num,arg,onstore,onerror){IDBStore.setFile(UTF8ToString(db),UTF8ToString(id),new Uint8Array(HEAPU8.subarray(ptr,ptr+num)),function(error){if(error){if(onerror)getWasmTableEntry(onerror)(arg);return}if(onstore)getWasmTableEntry(onstore)(arg)})}function reallyNegative(x){return x<0||x===0&&1/x===-Infinity}function convertI32PairToI53(lo,hi){return(lo>>>0)+hi*4294967296}function convertU32PairToI53(lo,hi){return(lo>>>0)+(hi>>>0)*4294967296}function reSign(value,bits){if(value<=0){return value}var half=bits<=32?Math.abs(1<=half&&(bits<=32||value>half)){value=-2*half+value}return value}function unSign(value,bits){if(value>=0){return value}return bits<=32?2*Math.abs(1<>3];argIndex+=8}else if(type=="i64"){ret=[HEAP32[argIndex>>2],HEAP32[argIndex+4>>2]];argIndex+=8}else{type="i32";ret=HEAP32[argIndex>>2];argIndex+=4}return ret}var ret=[];var curr,next,currArg;while(1){var startTextIndex=textIndex;curr=HEAP8[textIndex>>0];if(curr===0)break;next=HEAP8[textIndex+1>>0];if(curr==37){var flagAlwaysSigned=false;var flagLeftAlign=false;var flagAlternative=false;var flagZeroPad=false;var flagPadSign=false;flagsLoop:while(1){switch(next){case 43:flagAlwaysSigned=true;break;case 45:flagLeftAlign=true;break;case 35:flagAlternative=true;break;case 48:if(flagZeroPad){break flagsLoop}else{flagZeroPad=true;break}case 32:flagPadSign=true;break;default:break flagsLoop}textIndex++;next=HEAP8[textIndex+1>>0]}var width=0;if(next==42){width=getNextArg("i32");textIndex++;next=HEAP8[textIndex+1>>0]}else{while(next>=48&&next<=57){width=width*10+(next-48);textIndex++;next=HEAP8[textIndex+1>>0]}}var precisionSet=false,precision=-1;if(next==46){precision=0;precisionSet=true;textIndex++;next=HEAP8[textIndex+1>>0];if(next==42){precision=getNextArg("i32");textIndex++}else{while(1){var precisionChr=HEAP8[textIndex+1>>0];if(precisionChr<48||precisionChr>57)break;precision=precision*10+(precisionChr-48);textIndex++}}next=HEAP8[textIndex+1>>0]}if(precision<0){precision=6;precisionSet=false}var argSize;switch(String.fromCharCode(next)){case"h":var nextNext=HEAP8[textIndex+2>>0];if(nextNext==104){textIndex++;argSize=1}else{argSize=2}break;case"l":var nextNext=HEAP8[textIndex+2>>0];if(nextNext==108){textIndex++;argSize=8}else{argSize=4}break;case"L":case"q":case"j":argSize=8;break;case"z":case"t":case"I":argSize=4;break;default:argSize=null}if(argSize)textIndex++;next=HEAP8[textIndex+1>>0];switch(String.fromCharCode(next)){case"d":case"i":case"u":case"o":case"x":case"X":case"p":{var signed=next==100||next==105;argSize=argSize||4;currArg=getNextArg("i"+argSize*8);var argText;if(argSize==8){currArg=next==117?convertU32PairToI53(currArg[0],currArg[1]):convertI32PairToI53(currArg[0],currArg[1])}if(argSize<=4){var limit=Math.pow(256,argSize)-1;currArg=(signed?reSign:unSign)(currArg&limit,argSize*8)}var currAbsArg=Math.abs(currArg);var prefix="";if(next==100||next==105){argText=reSign(currArg,8*argSize).toString(10)}else if(next==117){argText=unSign(currArg,8*argSize).toString(10);currArg=Math.abs(currArg)}else if(next==111){argText=(flagAlternative?"0":"")+currAbsArg.toString(8)}else if(next==120||next==88){prefix=flagAlternative&&currArg!=0?"0x":"";if(currArg<0){currArg=-currArg;argText=(currAbsArg-1).toString(16);var buffer=[];for(var i=0;i=0){if(flagAlwaysSigned){prefix="+"+prefix}else if(flagPadSign){prefix=" "+prefix}}if(argText.charAt(0)=="-"){prefix="-"+prefix;argText=argText.substr(1)}while(prefix.length+argText.lengthexponent&&exponent>=-4){next=(next==103?"f":"F").charCodeAt(0);precision-=exponent+1}else{next=(next==103?"e":"E").charCodeAt(0);precision--}effectivePrecision=Math.min(precision,20)}if(next==101||next==69){argText=currArg.toExponential(effectivePrecision);if(/[eE][-+]\d$/.test(argText)){argText=argText.slice(0,-1)+"0"+argText.slice(-1)}}else if(next==102||next==70){argText=currArg.toFixed(effectivePrecision);if(currArg===0&&reallyNegative(currArg)){argText="-"+argText}}var parts=argText.split("e");if(isGeneral&&!flagAlternative){while(parts[0].length>1&&parts[0].includes(".")&&(parts[0].slice(-1)=="0"||parts[0].slice(-1)==".")){parts[0]=parts[0].slice(0,-1)}}else{if(flagAlternative&&argText.indexOf(".")==-1)parts[0]+=".";while(precision>effectivePrecision++)parts[0]+="0"}argText=parts[0]+(parts.length>1?"e"+parts[1]:"");if(next==69)argText=argText.toUpperCase();if(currArg>=0){if(flagAlwaysSigned){argText="+"+argText}else if(flagPadSign){argText=" "+argText}}}while(argText.length>0])}}else{ret=ret.concat(intArrayFromString("(null)".substr(0,argLength),true))}if(flagLeftAlign){while(argLength0){ret.push(32)}if(!flagLeftAlign)ret.push(getNextArg("i8"));break}case"n":{var ptr=getNextArg("i32*");HEAP32[ptr>>2]=ret.length;break}case"%":{ret.push(curr);break}default:{for(var i=startTextIndex;i>0])}}}textIndex+=2}else{ret.push(curr);textIndex+=1}}return ret}function traverseStack(args){if(!args||!args.callee||!args.callee.name){return[null,"",""]}var funstr=args.callee.toString();var funcname=args.callee.name;var str="(";var first=true;for(var i in args){var a=args[i];if(!first){str+=", "}first=false;if(typeof a=="number"||typeof a=="string"){str+=a}else{str+="("+typeof a+")"}}str+=")";var caller=args.callee.caller;args=caller?caller.arguments:[];if(first)str="";return[args,funcname,str]}function jsStackTrace(){var error=new Error;if(!error.stack){try{throw new Error}catch(e){error=e}if(!error.stack){return"(no stack trace available)"}}return error.stack.toString()}function warnOnce(text){if(!warnOnce.shown)warnOnce.shown={};if(!warnOnce.shown[text]){warnOnce.shown[text]=1;if(ENVIRONMENT_IS_NODE)text="warning: "+text;err(text)}}function _emscripten_get_callstack_js(flags){var callstack=jsStackTrace();var iThisFunc=callstack.lastIndexOf("_emscripten_log");var iThisFunc2=callstack.lastIndexOf("_emscripten_get_callstack");var iNextLine=callstack.indexOf("\n",Math.max(iThisFunc,iThisFunc2))+1;callstack=callstack.slice(iNextLine);if(flags&32){warnOnce("EM_LOG_DEMANGLE is deprecated; ignoring")}if(flags&8&&typeof emscripten_source_map=="undefined"){warnOnce('Source map information is not available, emscripten_log with EM_LOG_C_STACK will be ignored. Build with "--pre-js $EMSCRIPTEN/src/emscripten-source-map.min.js" linker flag to add source map loading to code.');flags^=8;flags|=16}var stack_args=null;if(flags&128){stack_args=traverseStack(arguments);while(stack_args[1].includes("_emscripten_"))stack_args=traverseStack(stack_args[0])}var lines=callstack.split("\n");callstack="";var newFirefoxRe=new RegExp("\\s*(.*?)@(.*?):([0-9]+):([0-9]+)");var firefoxRe=new RegExp("\\s*(.*?)@(.*):(.*)(:(.*))?");var chromeRe=new RegExp("\\s*at (.*?) \\((.*):(.*):(.*)\\)");for(var l in lines){var line=lines[l];var symbolName="";var file="";var lineno=0;var column=0;var parts=chromeRe.exec(line);if(parts&&parts.length==5){symbolName=parts[1];file=parts[2];lineno=parts[3];column=parts[4]}else{parts=newFirefoxRe.exec(line);if(!parts)parts=firefoxRe.exec(line);if(parts&&parts.length>=4){symbolName=parts[1];file=parts[2];lineno=parts[3];column=parts[4]|0}else{callstack+=line+"\n";continue}}var haveSourceMap=false;if(flags&8){var orig=emscripten_source_map.originalPositionFor({line:lineno,column:column});haveSourceMap=orig&&orig.source;if(haveSourceMap){if(flags&64){orig.source=orig.source.substring(orig.source.replace(/\\/g,"/").lastIndexOf("/")+1)}callstack+=" at "+symbolName+" ("+orig.source+":"+orig.line+":"+orig.column+")\n"}}if(flags&16||!haveSourceMap){if(flags&64){file=file.substring(file.replace(/\\/g,"/").lastIndexOf("/")+1)}callstack+=(haveSourceMap?" = "+symbolName:" at "+symbolName)+" ("+file+":"+lineno+":"+column+")\n"}if(flags&128&&stack_args[0]){if(stack_args[1]==symbolName&&stack_args[2].length>0){callstack=callstack.replace(/\s+$/,"");callstack+=" with values: "+stack_args[1]+stack_args[2]+"\n"}stack_args=traverseStack(stack_args[0])}}callstack=callstack.replace(/\s+$/,"");return callstack}function _emscripten_log_js(flags,str){if(flags&24){str=str.replace(/\s+$/,"");str+=(str.length>0?"\n":"")+_emscripten_get_callstack_js(flags)}if(flags&1){if(flags&4){console.error(str)}else if(flags&2){console.warn(str)}else if(flags&512){console.info(str)}else if(flags&256){console.debug(str)}else{console.log(str)}}else if(flags&6){err(str)}else{out(str)}}function _emscripten_log(flags,format,varargs){var result=formatString(format,varargs);var str=UTF8ArrayToString(result,0);_emscripten_log_js(flags,str)}function _emscripten_memcpy_big(dest,src,num){HEAPU8.copyWithin(dest,src,src+num)}function getHeapMax(){return 2147483648}function emscripten_realloc_buffer(size){try{wasmMemory.grow(size-buffer.byteLength+65535>>>16);updateGlobalBufferAndViews(wasmMemory.buffer);return 1}catch(e){}}function _emscripten_resize_heap(requestedSize){var oldSize=HEAPU8.length;requestedSize=requestedSize>>>0;var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){return false}let alignUp=(x,multiple)=>x+(multiple-x%multiple)%multiple;for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignUp(Math.max(requestedSize,overGrownHeapSize),65536));var replacement=emscripten_realloc_buffer(newSize);if(replacement){return true}}return false}var JSEvents={inEventHandler:0,removeAllEventListeners:function(){for(var i=JSEvents.eventHandlers.length-1;i>=0;--i){JSEvents._removeHandler(i)}JSEvents.eventHandlers=[];JSEvents.deferredCalls=[]},registerRemoveEventListeners:function(){if(!JSEvents.removeEventListenersRegistered){__ATEXIT__.push(JSEvents.removeAllEventListeners);JSEvents.removeEventListenersRegistered=true}},deferredCalls:[],deferCall:function(targetFunction,precedence,argsList){function arraysHaveEqualContent(arrA,arrB){if(arrA.length!=arrB.length)return false;for(var i in arrA){if(arrA[i]!=arrB[i])return false}return true}for(var i in JSEvents.deferredCalls){var call=JSEvents.deferredCalls[i];if(call.targetFunction==targetFunction&&arraysHaveEqualContent(call.argsList,argsList)){return}}JSEvents.deferredCalls.push({targetFunction:targetFunction,precedence:precedence,argsList:argsList});JSEvents.deferredCalls.sort(function(x,y){return x.precedence>3]=e.timeStamp;var idx=eventStruct>>2;HEAP32[idx+2]=e.screenX;HEAP32[idx+3]=e.screenY;HEAP32[idx+4]=e.clientX;HEAP32[idx+5]=e.clientY;HEAP32[idx+6]=e.ctrlKey;HEAP32[idx+7]=e.shiftKey;HEAP32[idx+8]=e.altKey;HEAP32[idx+9]=e.metaKey;HEAP16[idx*2+20]=e.button;HEAP16[idx*2+21]=e.buttons;HEAP32[idx+11]=e["movementX"];HEAP32[idx+12]=e["movementY"];var rect=getBoundingClientRect(target);HEAP32[idx+13]=e.clientX-rect.left;HEAP32[idx+14]=e.clientY-rect.top}function maybeCStringToJsString(cString){return cString>2?UTF8ToString(cString):cString}function findEventTarget(target){target=maybeCStringToJsString(target);var domElement=specialHTMLTargets[target]||(typeof document!="undefined"?document.querySelector(target):undefined);return domElement}function registerWheelEventCallback(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread){if(!JSEvents.wheelEvent)JSEvents.wheelEvent=_malloc(104);var wheelHandlerFunc=function(ev){var e=ev||event;var wheelEvent=JSEvents.wheelEvent;fillMouseEventData(wheelEvent,e,target);HEAPF64[wheelEvent+72>>3]=e["deltaX"];HEAPF64[wheelEvent+80>>3]=e["deltaY"];HEAPF64[wheelEvent+88>>3]=e["deltaZ"];HEAP32[wheelEvent+96>>2]=e["deltaMode"];if(getWasmTableEntry(callbackfunc)(eventTypeId,wheelEvent,userData))e.preventDefault()};var eventHandler={target:target,allowsDeferredCalls:true,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:wheelHandlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}function _emscripten_set_wheel_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){target=findEventTarget(target);if(typeof target.onwheel!="undefined"){registerWheelEventCallback(target,userData,useCapture,callbackfunc,9,"wheel",targetThread);return 0}else{return-1}}var ENV={};function getExecutableName(){return thisProgram||"./this.program"}function getEnvStrings(){if(!getEnvStrings.strings){var lang=(typeof navigator=="object"&&navigator.languages&&navigator.languages[0]||"C").replace("-","_")+".UTF-8";var env={"USER":"web_user","LOGNAME":"web_user","PATH":"/","PWD":"/","HOME":"/home/web_user","LANG":lang,"_":getExecutableName()};for(var x in ENV){if(ENV[x]===undefined)delete env[x];else env[x]=ENV[x]}var strings=[];for(var x in env){strings.push(x+"="+env[x])}getEnvStrings.strings=strings}return getEnvStrings.strings}function writeAsciiToMemory(str,buffer,dontAddNull){for(var i=0;i>0]=str.charCodeAt(i)}if(!dontAddNull)HEAP8[buffer>>0]=0}function _environ_get(__environ,environ_buf){var bufSize=0;getEnvStrings().forEach(function(string,i){var ptr=environ_buf+bufSize;HEAPU32[__environ+i*4>>2]=ptr;writeAsciiToMemory(string,ptr);bufSize+=string.length+1});return 0}function _environ_sizes_get(penviron_count,penviron_buf_size){var strings=getEnvStrings();HEAPU32[penviron_count>>2]=strings.length;var bufSize=0;strings.forEach(function(string){bufSize+=string.length+1});HEAPU32[penviron_buf_size>>2]=bufSize;return 0}function _proc_exit(code){EXITSTATUS=code;if(!keepRuntimeAlive()){if(Module["onExit"])Module["onExit"](code);ABORT=true}quit_(code,new ExitStatus(code))}function exitJS(status,implicit){EXITSTATUS=status;_proc_exit(status)}var _exit=exitJS;function _fd_close(fd){try{var stream=SYSCALLS.getStreamFromFD(fd);FS.close(stream);return 0}catch(e){if(typeof FS=="undefined"||!(e instanceof FS.ErrnoError))throw e;return e.errno}}function _fd_fdstat_get(fd,pbuf){try{var stream=SYSCALLS.getStreamFromFD(fd);var type=stream.tty?2:FS.isDir(stream.mode)?3:FS.isLink(stream.mode)?7:4;HEAP8[pbuf>>0]=type;return 0}catch(e){if(typeof FS=="undefined"||!(e instanceof FS.ErrnoError))throw e;return e.errno}}function doReadv(stream,iov,iovcnt,offset){var ret=0;for(var i=0;i>2];var len=HEAPU32[iov+4>>2];iov+=8;var curr=FS.read(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(curr>2]=num;return 0}catch(e){if(typeof FS=="undefined"||!(e instanceof FS.ErrnoError))throw e;return e.errno}}function _fd_seek(fd,offset,whence,newOffset){try{offset=bigintToI53Checked(offset);if(isNaN(offset))return 61;var stream=SYSCALLS.getStreamFromFD(fd);FS.llseek(stream,offset,whence);tempI64=[stream.position>>>0,(tempDouble=stream.position,+Math.abs(tempDouble)>=1?tempDouble>0?(Math.min(+Math.floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[newOffset>>2]=tempI64[0],HEAP32[newOffset+4>>2]=tempI64[1];if(stream.getdents&&offset===0&&whence===0)stream.getdents=null;return 0}catch(e){if(typeof FS=="undefined"||!(e instanceof FS.ErrnoError))throw e;return e.errno}}function _fd_sync(fd){try{var stream=SYSCALLS.getStreamFromFD(fd);if(stream.stream_ops&&stream.stream_ops.fsync){return stream.stream_ops.fsync(stream)}return 0}catch(e){if(typeof FS=="undefined"||!(e instanceof FS.ErrnoError))throw e;return e.errno}}function doWritev(stream,iov,iovcnt,offset){var ret=0;for(var i=0;i>2];var len=HEAPU32[iov+4>>2];iov+=8;var curr=FS.write(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr}return ret}function _fd_write(fd,iov,iovcnt,pnum){try{var stream=SYSCALLS.getStreamFromFD(fd);var num=doWritev(stream,iov,iovcnt);HEAPU32[pnum>>2]=num;return 0}catch(e){if(typeof FS=="undefined"||!(e instanceof FS.ErrnoError))throw e;return e.errno}}function _getentropy(buffer,size){if(!_getentropy.randomDevice){_getentropy.randomDevice=getRandomDevice()}for(var i=0;i>0]=_getentropy.randomDevice()}return 0}function __arraySum(array,index){var sum=0;for(var i=0;i<=index;sum+=array[i++]){}return sum}var __MONTH_DAYS_LEAP=[31,29,31,30,31,30,31,31,30,31,30,31];var __MONTH_DAYS_REGULAR=[31,28,31,30,31,30,31,31,30,31,30,31];function __addDays(date,days){var newDate=new Date(date.getTime());while(days>0){var leap=__isLeapYear(newDate.getFullYear());var currentMonth=newDate.getMonth();var daysInCurrentMonth=(leap?__MONTH_DAYS_LEAP:__MONTH_DAYS_REGULAR)[currentMonth];if(days>daysInCurrentMonth-newDate.getDate()){days-=daysInCurrentMonth-newDate.getDate()+1;newDate.setDate(1);if(currentMonth<11){newDate.setMonth(currentMonth+1)}else{newDate.setMonth(0);newDate.setFullYear(newDate.getFullYear()+1)}}else{newDate.setDate(newDate.getDate()+days);return newDate}}return newDate}function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer)}function _strftime(s,maxsize,format,tm){var tm_zone=HEAP32[tm+40>>2];var date={tm_sec:HEAP32[tm>>2],tm_min:HEAP32[tm+4>>2],tm_hour:HEAP32[tm+8>>2],tm_mday:HEAP32[tm+12>>2],tm_mon:HEAP32[tm+16>>2],tm_year:HEAP32[tm+20>>2],tm_wday:HEAP32[tm+24>>2],tm_yday:HEAP32[tm+28>>2],tm_isdst:HEAP32[tm+32>>2],tm_gmtoff:HEAP32[tm+36>>2],tm_zone:tm_zone?UTF8ToString(tm_zone):""};var pattern=UTF8ToString(format);var EXPANSION_RULES_1={"%c":"%a %b %d %H:%M:%S %Y","%D":"%m/%d/%y","%F":"%Y-%m-%d","%h":"%b","%r":"%I:%M:%S %p","%R":"%H:%M","%T":"%H:%M:%S","%x":"%m/%d/%y","%X":"%H:%M:%S","%Ec":"%c","%EC":"%C","%Ex":"%m/%d/%y","%EX":"%H:%M:%S","%Ey":"%y","%EY":"%Y","%Od":"%d","%Oe":"%e","%OH":"%H","%OI":"%I","%Om":"%m","%OM":"%M","%OS":"%S","%Ou":"%u","%OU":"%U","%OV":"%V","%Ow":"%w","%OW":"%W","%Oy":"%y"};for(var rule in EXPANSION_RULES_1){pattern=pattern.replace(new RegExp(rule,"g"),EXPANSION_RULES_1[rule])}var WEEKDAYS=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];var MONTHS=["January","February","March","April","May","June","July","August","September","October","November","December"];function leadingSomething(value,digits,character){var str=typeof value=="number"?value.toString():value||"";while(str.length0?1:0}var compare;if((compare=sgn(date1.getFullYear()-date2.getFullYear()))===0){if((compare=sgn(date1.getMonth()-date2.getMonth()))===0){compare=sgn(date1.getDate()-date2.getDate())}}return compare}function getFirstWeekStartDate(janFourth){switch(janFourth.getDay()){case 0:return new Date(janFourth.getFullYear()-1,11,29);case 1:return janFourth;case 2:return new Date(janFourth.getFullYear(),0,3);case 3:return new Date(janFourth.getFullYear(),0,2);case 4:return new Date(janFourth.getFullYear(),0,1);case 5:return new Date(janFourth.getFullYear()-1,11,31);case 6:return new Date(janFourth.getFullYear()-1,11,30)}}function getWeekBasedYear(date){var thisDate=__addDays(new Date(date.tm_year+1900,0,1),date.tm_yday);var janFourthThisYear=new Date(thisDate.getFullYear(),0,4);var janFourthNextYear=new Date(thisDate.getFullYear()+1,0,4);var firstWeekStartThisYear=getFirstWeekStartDate(janFourthThisYear);var firstWeekStartNextYear=getFirstWeekStartDate(janFourthNextYear);if(compareByDay(firstWeekStartThisYear,thisDate)<=0){if(compareByDay(firstWeekStartNextYear,thisDate)<=0){return thisDate.getFullYear()+1}return thisDate.getFullYear()}return thisDate.getFullYear()-1}var EXPANSION_RULES_2={"%a":function(date){return WEEKDAYS[date.tm_wday].substring(0,3)},"%A":function(date){return WEEKDAYS[date.tm_wday]},"%b":function(date){return MONTHS[date.tm_mon].substring(0,3)},"%B":function(date){return MONTHS[date.tm_mon]},"%C":function(date){var year=date.tm_year+1900;return leadingNulls(year/100|0,2)},"%d":function(date){return leadingNulls(date.tm_mday,2)},"%e":function(date){return leadingSomething(date.tm_mday,2," ")},"%g":function(date){return getWeekBasedYear(date).toString().substring(2)},"%G":function(date){return getWeekBasedYear(date)},"%H":function(date){return leadingNulls(date.tm_hour,2)},"%I":function(date){var twelveHour=date.tm_hour;if(twelveHour==0)twelveHour=12;else if(twelveHour>12)twelveHour-=12;return leadingNulls(twelveHour,2)},"%j":function(date){return leadingNulls(date.tm_mday+__arraySum(__isLeapYear(date.tm_year+1900)?__MONTH_DAYS_LEAP:__MONTH_DAYS_REGULAR,date.tm_mon-1),3)},"%m":function(date){return leadingNulls(date.tm_mon+1,2)},"%M":function(date){return leadingNulls(date.tm_min,2)},"%n":function(){return"\n"},"%p":function(date){if(date.tm_hour>=0&&date.tm_hour<12){return"AM"}return"PM"},"%S":function(date){return leadingNulls(date.tm_sec,2)},"%t":function(){return"\t"},"%u":function(date){return date.tm_wday||7},"%U":function(date){var days=date.tm_yday+7-date.tm_wday;return leadingNulls(Math.floor(days/7),2)},"%V":function(date){var val=Math.floor((date.tm_yday+7-(date.tm_wday+6)%7)/7);if((date.tm_wday+371-date.tm_yday-2)%7<=2){val++}if(!val){val=52;var dec31=(date.tm_wday+7-date.tm_yday-1)%7;if(dec31==4||dec31==5&&__isLeapYear(date.tm_year%400-1)){val++}}else if(val==53){var jan1=(date.tm_wday+371-date.tm_yday)%7;if(jan1!=4&&(jan1!=3||!__isLeapYear(date.tm_year)))val=1}return leadingNulls(val,2)},"%w":function(date){return date.tm_wday},"%W":function(date){var days=date.tm_yday+7-(date.tm_wday+6)%7;return leadingNulls(Math.floor(days/7),2)},"%y":function(date){return(date.tm_year+1900).toString().substring(2)},"%Y":function(date){return date.tm_year+1900},"%z":function(date){var off=date.tm_gmtoff;var ahead=off>=0;off=Math.abs(off)/60;off=off/60*100+off%60;return(ahead?"+":"-")+String("0000"+off).slice(-4)},"%Z":function(date){return date.tm_zone},"%%":function(){return"%"}};pattern=pattern.replace(/%%/g,"\0\0");for(var rule in EXPANSION_RULES_2){if(pattern.includes(rule)){pattern=pattern.replace(new RegExp(rule,"g"),EXPANSION_RULES_2[rule](date))}}pattern=pattern.replace(/\0\0/g,"%");var bytes=intArrayFromString(pattern,false);if(bytes.length>maxsize){return 0}writeArrayToMemory(bytes,s);return bytes.length-1}function _strftime_l(s,maxsize,format,tm,loc){return _strftime(s,maxsize,format,tm)}var FSNode=function(parent,name,mode,rdev){if(!parent){parent=this}this.parent=parent;this.mount=parent.mount;this.mounted=null;this.id=FS.nextInode++;this.name=name;this.mode=mode;this.node_ops={};this.stream_ops={};this.rdev=rdev};var readMode=292|73;var writeMode=146;Object.defineProperties(FSNode.prototype,{read:{get:function(){return(this.mode&readMode)===readMode},set:function(val){val?this.mode|=readMode:this.mode&=~readMode}},write:{get:function(){return(this.mode&writeMode)===writeMode},set:function(val){val?this.mode|=writeMode:this.mode&=~writeMode}},isFolder:{get:function(){return FS.isDir(this.mode)}},isDevice:{get:function(){return FS.isChrdev(this.mode)}}});FS.FSNode=FSNode;FS.staticInit();embind_init_charCodes();BindingError=Module["BindingError"]=extendError(Error,"BindingError");InternalError=Module["InternalError"]=extendError(Error,"InternalError");init_emval();UnboundTypeError=Module["UnboundTypeError"]=extendError(Error,"UnboundTypeError");var asmLibraryArg={"__call_sighandler":___call_sighandler,"__cxa_throw":___cxa_throw,"__syscall_chmod":___syscall_chmod,"__syscall_faccessat":___syscall_faccessat,"__syscall_fchmod":___syscall_fchmod,"__syscall_fcntl64":___syscall_fcntl64,"__syscall_fstat64":___syscall_fstat64,"__syscall_ftruncate64":___syscall_ftruncate64,"__syscall_getcwd":___syscall_getcwd,"__syscall_getdents64":___syscall_getdents64,"__syscall_lstat64":___syscall_lstat64,"__syscall_mkdirat":___syscall_mkdirat,"__syscall_newfstatat":___syscall_newfstatat,"__syscall_openat":___syscall_openat,"__syscall_readlinkat":___syscall_readlinkat,"__syscall_renameat":___syscall_renameat,"__syscall_rmdir":___syscall_rmdir,"__syscall_stat64":___syscall_stat64,"__syscall_symlink":___syscall_symlink,"__syscall_truncate64":___syscall_truncate64,"__syscall_unlinkat":___syscall_unlinkat,"__syscall_utimensat":___syscall_utimensat,"_embind_register_bigint":__embind_register_bigint,"_embind_register_bool":__embind_register_bool,"_embind_register_emval":__embind_register_emval,"_embind_register_float":__embind_register_float,"_embind_register_function":__embind_register_function,"_embind_register_integer":__embind_register_integer,"_embind_register_memory_view":__embind_register_memory_view,"_embind_register_std_string":__embind_register_std_string,"_embind_register_std_wstring":__embind_register_std_wstring,"_embind_register_void":__embind_register_void,"_emscripten_get_now_is_monotonic":__emscripten_get_now_is_monotonic,"_emval_as":__emval_as,"_emval_call_method":__emval_call_method,"_emval_call_void_method":__emval_call_void_method,"_emval_decref":__emval_decref,"_emval_get_global":__emval_get_global,"_emval_get_method_caller":__emval_get_method_caller,"_emval_get_module_property":__emval_get_module_property,"_emval_get_property":__emval_get_property,"_emval_incref":__emval_incref,"_emval_new_cstring":__emval_new_cstring,"_emval_new_object":__emval_new_object,"_emval_run_destructors":__emval_run_destructors,"_emval_set_property":__emval_set_property,"_emval_take_value":__emval_take_value,"_localtime_js":__localtime_js,"_mktime_js":__mktime_js,"_mmap_js":__mmap_js,"_munmap_js":__munmap_js,"_tzset_js":__tzset_js,"abort":_abort,"emscripten_date_now":_emscripten_date_now,"emscripten_get_now":_emscripten_get_now,"emscripten_idb_async_delete":_emscripten_idb_async_delete,"emscripten_idb_async_exists":_emscripten_idb_async_exists,"emscripten_idb_async_load":_emscripten_idb_async_load,"emscripten_idb_async_store":_emscripten_idb_async_store,"emscripten_log":_emscripten_log,"emscripten_memcpy_big":_emscripten_memcpy_big,"emscripten_resize_heap":_emscripten_resize_heap,"emscripten_set_wheel_callback_on_thread":_emscripten_set_wheel_callback_on_thread,"environ_get":_environ_get,"environ_sizes_get":_environ_sizes_get,"exit":_exit,"fd_close":_fd_close,"fd_fdstat_get":_fd_fdstat_get,"fd_read":_fd_read,"fd_seek":_fd_seek,"fd_sync":_fd_sync,"fd_write":_fd_write,"getentropy":_getentropy,"jsHaveAsyncify":jsHaveAsyncify,"qt_asyncify_resume_js":qt_asyncify_resume_js,"qt_asyncify_suspend_js":qt_asyncify_suspend_js,"strftime_l":_strftime_l};var asm=createWasm();var ___wasm_call_ctors=Module["___wasm_call_ctors"]=function(){return(___wasm_call_ctors=Module["___wasm_call_ctors"]=Module["asm"]["__wasm_call_ctors"]).apply(null,arguments)};var _processImage=Module["_processImage"]=function(){return(_processImage=Module["_processImage"]=Module["asm"]["processImage"]).apply(null,arguments)};var _setRefData=Module["_setRefData"]=function(){return(_setRefData=Module["_setRefData"]=Module["asm"]["setRefData"]).apply(null,arguments)};var _setAudioBuffer=Module["_setAudioBuffer"]=function(){return(_setAudioBuffer=Module["_setAudioBuffer"]=Module["asm"]["setAudioBuffer"]).apply(null,arguments)};var _free=Module["_free"]=function(){return(_free=Module["_free"]=Module["asm"]["free"]).apply(null,arguments)};var _updateBlendShape=Module["_updateBlendShape"]=function(){return(_updateBlendShape=Module["_updateBlendShape"]=Module["asm"]["updateBlendShape"]).apply(null,arguments)};var _malloc=Module["_malloc"]=function(){return(_malloc=Module["_malloc"]=Module["asm"]["malloc"]).apply(null,arguments)};var ___errno_location=Module["___errno_location"]=function(){return(___errno_location=Module["___errno_location"]=Module["asm"]["__errno_location"]).apply(null,arguments)};var ___getTypeName=Module["___getTypeName"]=function(){return(___getTypeName=Module["___getTypeName"]=Module["asm"]["__getTypeName"]).apply(null,arguments)};var __embind_initialize_bindings=Module["__embind_initialize_bindings"]=function(){return(__embind_initialize_bindings=Module["__embind_initialize_bindings"]=Module["asm"]["_embind_initialize_bindings"]).apply(null,arguments)};var ___dl_seterr=Module["___dl_seterr"]=function(){return(___dl_seterr=Module["___dl_seterr"]=Module["asm"]["__dl_seterr"]).apply(null,arguments)};var _emscripten_builtin_memalign=Module["_emscripten_builtin_memalign"]=function(){return(_emscripten_builtin_memalign=Module["_emscripten_builtin_memalign"]=Module["asm"]["emscripten_builtin_memalign"]).apply(null,arguments)};var stackSave=Module["stackSave"]=function(){return(stackSave=Module["stackSave"]=Module["asm"]["stackSave"]).apply(null,arguments)};var stackRestore=Module["stackRestore"]=function(){return(stackRestore=Module["stackRestore"]=Module["asm"]["stackRestore"]).apply(null,arguments)};var stackAlloc=Module["stackAlloc"]=function(){return(stackAlloc=Module["stackAlloc"]=Module["asm"]["stackAlloc"]).apply(null,arguments)};var ___cxa_is_pointer_type=Module["___cxa_is_pointer_type"]=function(){return(___cxa_is_pointer_type=Module["___cxa_is_pointer_type"]=Module["asm"]["__cxa_is_pointer_type"]).apply(null,arguments)};var ___start_em_js=Module["___start_em_js"]=2701236;var ___stop_em_js=Module["___stop_em_js"]=2701718;Module["UTF16ToString"]=UTF16ToString;Module["stringToUTF16"]=stringToUTF16;Module["JSEvents"]=JSEvents;Module["specialHTMLTargets"]=specialHTMLTargets;Module["FS"]=FS;var calledRun;dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function run(args){args=args||arguments_;if(runDependencies>0){return}preRun();if(runDependencies>0){return}function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();readyPromiseResolve(Module);if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}run();
+
+
+ return createQtAppInstance.ready
+}
+);
+})();
+if (typeof exports === 'object' && typeof module === 'object')
+ module.exports = createQtAppInstance;
+else if (typeof define === 'function' && define['amd'])
+ define([], function() { return createQtAppInstance; });
+else if (typeof exports === 'object')
+ exports["createQtAppInstance"] = createQtAppInstance;
diff --git a/web_demo/static/js/MiniLive2.js b/web_demo/static/js/MiniLive2.js
new file mode 100644
index 0000000..fbeb7be
--- /dev/null
+++ b/web_demo/static/js/MiniLive2.js
@@ -0,0 +1,565 @@
+const audioSource = document.getElementById('audioSource');
+const audio = document.getElementById('audio');
+
+ const video = document.getElementById('video');
+ const canvas_gl = document.getElementById('canvas_gl');
+ const gl = canvas_gl.getContext('webgl2',{ antialias: false });
+
+ const canvas_video = document.getElementById('canvas_video');
+ const ctx_video = canvas_video.getContext('2d');
+
+ // 缩放到128x128
+ const resizedCanvas = document.createElement('canvas');
+ const resizedCtx = resizedCanvas.getContext('2d', {willReadFrequently: true});
+
+ // 创建一个像素缓冲区来存储读取的像素数据
+ const pixels_fbo = new Uint8Array(128 * 128 * 4);
+
+
+ let objData;
+ let dataSets = [];
+
+ let program;
+ let indexBuffer;
+ const texture_bs = gl.createTexture();;
+ var bs_array = new Float32Array(12);
+
+ const mat4 = glMatrix.mat4;
+
+document.getElementById('playButton').addEventListener('click', function() {
+ video.play();
+// document.getElementById('startMessage').style.display = 'none';
+});
+
+video.addEventListener('loadedmetadata', () => {
+// resizeCanvas();
+ video.addEventListener('play', processVideoFrames);
+// resizeCanvas();
+ console.log("loadedmetadata", video.videoWidth, video.videoHeight)
+ canvas_video.width = video.videoWidth;
+ canvas_video.height = video.videoHeight;
+});
+
+
+async function loadRefData() {
+ const response = await fetch('assets/ref_data.txt');
+ if (!response.ok) {
+ throw new Error('Network response was not ok ' + response.statusText);
+ }
+ const fileContent = await response.text();
+ var refData = fileContent.split('\n').map(line => parseFloat(line.trim()));
+ const expectedSize = 18 * 14 * 20;
+ refData = refData.slice(0, expectedSize);
+ const refDataSize = refData.length;
+ if (refDataSize !== expectedSize) {
+ throw new Error(`Invalid refData size: expected ${expectedSize}, got ${refData.length}`);
+ }
+ console.log(refData.length, refData)
+ // Convert refData to Float32Array
+ const floatArray = new Float32Array(refData);
+ const floatArrayBytes = floatArray.byteLength;
+
+ var refDataPtr = Module._malloc(floatArrayBytes);
+ Module.HEAPF32.set(floatArray, refDataPtr / 4);
+ Module._setRefData(refDataPtr, floatArrayBytes);
+// Module._free(refDataPtr);
+}
+
+ // 加载JSON数据
+async function loadJsonData() {
+ try {
+ const response = await fetch('assets/json_data.json');
+ if (!response.ok) {
+ throw new Error('Network response was not ok ' + response.statusText);
+ }
+ dataSets = await response.json();
+ console.log('Data loaded successfully:', dataSets.length, 'sets.');
+ } catch (error) {
+ console.error('Error loading the file:', error);
+ }
+}
+
+
+// 加载OBJ文件
+async function loadObjFile(url) {
+ const response = await fetch(url);
+ if (!response.ok) {
+ throw new Error('Network response was not ok ' + response.statusText);
+ }
+ const text = await response.text();
+ const { vertices, faces } = parseObjFile(text);
+ return { vertices, faces };
+}
+
+ // 解析OBJ文件
+function parseObjFile(text) {
+ const vertices = [];
+ const vt = [];
+ const faces = [];
+ const lines = text.split('\n');
+
+ lines.forEach(line => {
+// console.log(line)
+ const parts = line.trim().split(/\s+/);
+ if (parts[0] === 'v') {
+ vertices.push(parseFloat(parts[1]), parseFloat(parts[2]), parseFloat(parts[3]),
+ parseFloat(parts[4]), parseFloat(parts[5]));
+// vertices.push(parseFloat(parts[1]), parseFloat(parts[2]), parseFloat(parts[3]));
+ } else if (parts[0] === 'f') {
+ const face = parts.slice(1).map(part => {
+ const indices = part.split('/').map(index => parseInt(index, 10) - 1);
+ return indices[0];
+ });
+ faces.push(...face);
+ }
+ });
+
+ return { vertices, faces };
+}
+
+
+
+async function init_gl() {
+ loadJsonData();
+ loadRefData();
+ objData = await loadObjFile('assets/face3D.obj');
+
+ {
+ // WebGL Shaders
+ const vertexShaderSource = `#version 300 es
+ layout(location = 0) in vec3 a_position;
+ layout(location = 1) in vec2 a_texture;
+ uniform float bsVec[12];
+ uniform mat4 gProjection;
+ uniform mat4 gWorld0;
+ uniform sampler2D texture_bs;
+ uniform vec2 vertBuffer[209];
+ out vec2 v_texture;
+ out vec2 v_bias;
+
+ vec4 calculateMorphPosition(vec3 position, vec2 textureCoord) {
+ vec4 tmp_Position2 = vec4(position, 1.0);
+ if (textureCoord.x < 3.0 && textureCoord.x >= 0.0) {
+ vec3 morphSum = vec3(0.0);
+ for (int i = 0; i < 6; i++) {
+ ivec2 coord = ivec2(int(textureCoord.y), i);
+ vec3 morph = texelFetch(texture_bs, coord, 0).xyz * 2.0 - 1.0;
+ morphSum += bsVec[i] * morph;
+ }
+ tmp_Position2.xyz += morphSum;
+ }
+ else if (textureCoord.x == 4.0)
+ {
+ // lower teeth
+ vec3 morphSum = vec3(0.0, (bsVec[0] + bsVec[1])/ 2.7 + 6.0, 0.0);
+ tmp_Position2.xyz += morphSum;
+ }
+ return tmp_Position2;
+}
+
+ void main() {
+ mat4 gWorld = gWorld0;
+
+ vec4 tmp_Position2 = calculateMorphPosition(a_position, a_texture);
+ vec4 tmp_Position = gWorld * tmp_Position2;
+
+ v_bias = vec2(0.0, 0.0);
+ if (a_texture.x == -1.0f)
+ {
+ v_bias = vec2(0.0, 0.0);
+ }
+ else if (a_texture.y < 209.0f)
+ {
+ vec4 vert_new = gProjection * vec4(tmp_Position.x, tmp_Position.y, tmp_Position.z, 1.0);
+ v_bias = vert_new.xy - (vertBuffer[int(a_texture.y)].xy/128.0 * 2.0 - 1.0);
+ }
+
+ if (a_texture.x >= 3.0f)
+ {
+ gl_Position = gProjection * vec4(tmp_Position.x, tmp_Position.y, 500.0, 1.0);
+ }
+ else
+ {
+ gl_Position = gProjection * vec4(tmp_Position.x, tmp_Position.y, tmp_Position.z, 1.0);
+ }
+
+ v_texture = a_texture;
+ }
+
+ `;
+
+ const fragmentShaderSource = `#version 300 es
+ precision mediump float;
+ in mediump vec2 v_texture;
+ in mediump vec2 v_bias;
+ out vec4 out_color;
+void main()
+{
+ if (v_texture.x == 2.0f)
+ {
+ out_color = vec4(1.0, 0.0, 0.0, 1.0);
+ }
+ else if (v_texture.x > 2.0f && v_texture.x < 2.1f)
+ {
+ out_color = vec4(0.5f, 0.0, 0.0, 1.0);
+ }
+ else if (v_texture.x == 3.0f)
+ {
+ out_color = vec4(0.0, 1.0, 0.0, 1.0);
+ }
+ else if (v_texture.x == 4.0f)
+ {
+ out_color = vec4(0.0, 0.0, 1.0, 1.0);
+ }
+ else if (v_texture.x > 3.0f && v_texture.x < 4.0f)
+ {
+ out_color = vec4(0.0, 0.0, 0.0, 1.0);
+ }
+ else
+ {
+ vec2 wrap = (v_bias.xy + 1.0)/2.0;
+ out_color = vec4(wrap.xy, 0.5, 1.0);
+ }
+}
+ `;
+
+ // Compile shaders and link program
+ const vertexShader = gl.createShader(gl.VERTEX_SHADER);
+ gl.shaderSource(vertexShader, vertexShaderSource);
+ gl.compileShader(vertexShader);
+
+ const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
+ gl.shaderSource(fragmentShader, fragmentShaderSource);
+ gl.compileShader(fragmentShader);
+
+ program = gl.createProgram();
+ gl.attachShader(program, vertexShader);
+ gl.attachShader(program, fragmentShader);
+ gl.linkProgram(program);
+ gl.useProgram(program);
+
+ // Set up vertex data
+ const positionLocation = gl.getAttribLocation(program, "a_position");
+ const positionBuffer = gl.createBuffer();
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(objData.vertices), gl.STATIC_DRAW);
+ // 启用顶点属性数组
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 20, 0);
+
+ // 启用纹理坐标属性数组
+ gl.enableVertexAttribArray(1);
+ gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 20, 12);
+// gl.enableVertexAttribArray(positionLocation);
+// gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 0, 0);
+
+
+ indexBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(objData.faces), gl.STATIC_DRAW);
+
+
+ // 假设已经有了WebGL上下文gl
+
+var image = new Image();
+image.onload = function() {
+ gl.bindTexture(gl.TEXTURE_2D, texture_bs);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ gl.bindTexture(gl.TEXTURE_2D, null);
+};
+image.src = 'assets/bs_texture_halfFace.png';
+
+ }
+}
+//init();
+
+
+
+ function render(mat_world, subPoints, bsArray) {
+// console.log("render")
+ gl.useProgram(program);
+ const worldMatUniformLocation = gl.getUniformLocation(program, "gWorld0");
+ gl.uniformMatrix4fv(worldMatUniformLocation, false, mat_world);
+
+ gl.uniform2fv(gl.getUniformLocation(program, "vertBuffer"), subPoints);
+ gl.uniform1fv(gl.getUniformLocation(program, "bsVec"), bsArray);
+
+ // 获取着色器程序中uniform变量的位置
+ const projectionUniformLocation = gl.getUniformLocation(program, "gProjection");
+
+ // 使用 gl-matrix 创建正交投影矩阵
+ const orthoMatrix = mat4.create();
+
+ mat4.ortho(orthoMatrix, 0, 128, 0, 128, 1000, -1000);
+ // console.log(orthoMatrix)
+ // 将正交投影矩阵传递给着色器
+ gl.uniformMatrix4fv(projectionUniformLocation, false, orthoMatrix);
+
+ gl.enable(gl.DEPTH_TEST);
+ // 启用混合
+ gl.enable(gl.BLEND);
+ gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
+ // 启用面剔除
+ gl.enable(gl.CULL_FACE);
+ gl.cullFace(gl.BACK); // 剔除背面
+ gl.frontFace(gl.CW); // 通常顶点顺序是顺时针
+ // 设置清屏颜色
+ gl.clearColor(0.5, 0.5, 0.5, 0);
+ // 清屏
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+ gl.activeTexture(gl.TEXTURE0);
+ gl.bindTexture(gl.TEXTURE_2D, texture_bs);
+ gl.uniform1i(gl.getUniformLocation(program, 'texture_bs'), 0);
+
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
+
+ // Render to canvas
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+
+ const width = gl.drawingBufferWidth;
+ const height = gl.drawingBufferHeight;
+ gl.drawElements(gl.TRIANGLES, objData.faces.length, gl.UNSIGNED_SHORT, 0);
+
+ // 读取像素数据
+ gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixels_fbo);
+ }
+
+function resizeCanvas() {
+ const screenWidth = window.innerWidth;
+ const screenHeight = window.innerHeight;
+
+ const videoWidth = video.videoWidth;
+ const videoHeight = video.videoHeight;
+ const videoAspectRatio = videoWidth / videoHeight;
+
+ let canvasWidth = screenWidth;
+ let canvasHeight = screenWidth / videoAspectRatio;
+
+ if (canvasHeight > screenHeight) {
+ canvasHeight = screenHeight;
+ canvasWidth = screenHeight * videoAspectRatio;
+ }
+
+ canvas_video.width = canvasWidth;
+ canvas_video.height = canvasHeight;
+
+ // Center the canvas
+ canvas_video.style.position = 'absolute';
+ canvas_video.style.left = (screenWidth - canvasWidth) / 2 + 'px';
+ canvas_video.style.top = (screenHeight - canvasHeight) / 2 + 'px';
+ }
+
+
+
+async function processVideoFrames() {
+ let lastDataSetIndex = -1; // 初始化为一个不可能的索引值
+ let isProcessing = false; // 标志位
+
+ let lastVideoTime = 0; // 初始化为一个不可能的索引值
+
+ const frameCallback = async (currentTime) => {
+ if (!video.paused && !video.ended && !isProcessing) {
+ isProcessing = true;
+
+ try {
+ // 计算当前数据集索引
+ const currentDataSetIndex = Math.floor(video.currentTime * 25);
+
+// console.log("currentDataSetIndex", currentDataSetIndex, video.currentTime, video.currentTime - lastVideoTime)
+ lastVideoTime = video.currentTime
+ if (lastDataSetIndex !== currentDataSetIndex && currentDataSetIndex < dataSets.length - 1) {
+ lastDataSetIndex = currentDataSetIndex;
+// console.log("currentDataSetIndex", currentDataSetIndex, lastDataSetIndex, video.currentTime, video.currentTime - lastVideoTime)
+ // 清除画布并绘制当前视频帧到canvas
+ ctx_video.clearRect(0, 0, canvas_video.width, canvas_video.height);
+ ctx_video.drawImage(video, 0, 0, canvas_video.width, canvas_video.height);
+ // 处理当前数据集
+ if (currentDataSetIndex < dataSets.length - 1) {
+
+ // 创建一个ArrayBuffer来存储浮点数
+ const floatArraySize = 12;
+ const floatArrayBytes = floatArraySize * 4; // 每个浮点数占用4个字节
+
+ var bsPtr = Module._malloc(floatArrayBytes);
+ Module._updateBlendShape(bsPtr, floatArrayBytes);
+ // 从Wasm内存中取出数据
+ var bsArray = new Float32Array(Module.HEAPU8.buffer, bsPtr, floatArraySize);
+// console.log("bs", bsArray);
+
+
+
+ const dataSet = dataSets[currentDataSetIndex];
+ const rect = dataSet.rect;
+
+ const currentTimeStamp = 0.04 * currentDataSetIndex;
+ const nextTimeStamp = 0.04 * (currentDataSetIndex + 1);
+ const currentpoints = dataSets[currentDataSetIndex].points;
+ const nextpoints = dataSets[currentDataSetIndex + 1].points;
+
+// console.log("rect", rect)
+
+ // 线性插值计算
+ const t = (video.currentTime - currentTimeStamp) / (nextTimeStamp - currentTimeStamp);
+ let points = currentpoints.map((xi, index) => (1-t) * xi + t * nextpoints[index]);
+ // 创建一个新的 mat4 对象
+ let matrix = mat4.create();
+
+ mat4.set(matrix,
+ points[0], points[1], points[2], points[3],
+ points[4], points[5], points[6], points[7],
+ points[8], points[9], points[10], points[11],
+ points[12], points[13], points[14], points[15]
+ );
+// console.log(matrix);
+ const subPoints = points.slice(16);
+ render(matrix, subPoints, bsArray);
+
+ // 创建临时画布用于裁剪、缩放和绘点
+ const tempCanvas = document.createElement('canvas');
+ const tempCtx = tempCanvas.getContext('2d');
+
+ // 获取rect区域图像数据并绘制到临时画布
+ tempCanvas.width = rect[2] - rect[0];
+ tempCanvas.height = rect[3] - rect[1];
+ tempCtx.drawImage(
+ video,
+ rect[0],
+ rect[1],
+ rect[2] - rect[0],
+ rect[3] - rect[1],
+ 0,
+ 0,
+ tempCanvas.width,
+ tempCanvas.height
+ );
+
+ // 缩放到128x128
+ resizedCanvas.width = 128;
+ resizedCanvas.height = 128;
+ resizedCtx.drawImage(tempCanvas, 0, 0, 128, 128);
+
+ // 获取128x128图像数据并处理
+ const imageData = resizedCtx.getImageData(0, 0, 128, 128);
+
+
+ var data = imageData.data;
+ var imageDataPtr = Module._malloc(data.length);
+ Module.HEAPU8.set(data, imageDataPtr);
+
+
+ var imageDataGlPtr = Module._malloc(pixels_fbo.length);
+ Module.HEAPU8.set(pixels_fbo, imageDataGlPtr);
+ const processedData = Module._processImage(imageDataPtr, 128, 128, imageDataGlPtr, 128, 128);
+ var result = Module.HEAPU8.subarray(imageDataPtr, imageDataPtr + data.length);
+ imageData.data.set(result);
+
+ // 更新 canvas 上的图像显示
+ resizedCtx.putImageData(imageData, 0, 0);
+ // 恢复图像到原始尺寸
+ tempCtx.clearRect(0, 0, tempCanvas.width, tempCanvas.height);
+ tempCtx.drawImage(resizedCanvas, 0, 0, tempCanvas.width, tempCanvas.height);
+
+ // 将临时画布的内容放回原画布
+ ctx_video.drawImage(tempCanvas, rect[0], rect[1]);
+
+ // 释放分配的内存
+ Module._free(imageDataPtr);
+ imageDataPtr = null;
+ Module._free(imageDataGlPtr);
+
+ Module._free(bsPtr);
+ }
+ }
+
+ isProcessing = false; // 处理完成后将标志位置为false
+ } catch (error) {
+ console.error('Error processing frame:', error);
+ isProcessing = false; // 即使出错也要将标志位置为false
+ }
+
+ requestAnimationFrame(frameCallback);
+ }
+ };
+
+ requestAnimationFrame(frameCallback);
+ }
+
+document.getElementById('uploadButton').addEventListener('click', function() {
+ document.getElementById('fileInput').click();
+});
+
+document.getElementById('fileInput').addEventListener('change', function(event) {
+ const file = event.target.files[0];
+ if (file) {
+ readWavFile(file);
+ }
+});
+
+function readWavFile(file) {
+ const reader = new FileReader();
+
+ reader.onload = function(event) {
+ const arrayBuffer = event.target.result;
+ const dataView = new DataView(arrayBuffer);
+
+ // Check if the file is a valid WAV file
+ if (dataView.getUint32(0, true) !== 0x46464952 || dataView.getUint32(8, true) !== 0x45564157) {
+ alert('Not a valid WAV file');
+ return;
+ }
+
+ // Get the PCM data chunk
+ const chunkSize = dataView.getUint32(4, true);
+ const format = dataView.getUint32(12, true);
+ const subChunk1Size = dataView.getUint32(16, true);
+ const audioFormat = dataView.getUint16(20, true);
+ const numChannels = dataView.getUint16(22, true);
+ const sampleRate = dataView.getUint32(24, true);
+ const byteRate = dataView.getUint32(28, true);
+ const blockAlign = dataView.getUint16(32, true);
+ const bitsPerSample = dataView.getUint16(34, true);
+
+ // Find the data chunk
+ let dataOffset = 36;
+ while (dataOffset < arrayBuffer.byteLength) {
+ const chunkId = dataView.getUint32(dataOffset, true);
+ const chunkSize = dataView.getUint32(dataOffset + 4, true);
+ if (chunkId === 0x61746164) { // "data" chunk
+ const data = new Uint16Array(arrayBuffer, dataOffset + 8, chunkSize / 2);
+ console.log('PCM Data:', data);
+ // Convert PCM data to Uint8Array
+ const view = new Uint8Array(arrayBuffer);
+
+ // Allocate memory in WebAssembly heap
+ const arrayBufferPtr = Module._malloc(arrayBuffer.byteLength);
+
+ // Copy data to WebAssembly heap
+ Module.HEAPU8.set(view, arrayBufferPtr);
+
+ // Call WebAssembly module's C function
+ console.log("buffer.byteLength", arrayBuffer.byteLength);
+ Module._setAudioBuffer(arrayBufferPtr, arrayBuffer.byteLength);
+
+ // Free the allocated memory
+ Module._free(arrayBufferPtr);
+
+ // Set the audio source and play it when the video starts
+
+ audioSource.src = URL.createObjectURL(new Blob([arrayBuffer], { type: 'audio/wav' }));
+ audio.load();
+ audio.play();
+
+ break;
+ }
+ dataOffset += 8 + chunkSize;
+ }
+ };
+
+ reader.readAsArrayBuffer(file);
+}
\ No newline at end of file
diff --git a/web_demo/static/js/MiniMateLoader.js b/web_demo/static/js/MiniMateLoader.js
new file mode 100644
index 0000000..8a79d45
--- /dev/null
+++ b/web_demo/static/js/MiniMateLoader.js
@@ -0,0 +1,232 @@
+document.addEventListener('DOMContentLoaded', function () {
+ init();
+});
+
+async function init()
+{
+ const spinner = document.querySelector('#loadingSpinner');
+ const screen = document.querySelector('#screen');
+ const showUi = () => {
+ spinner.style.display = 'none';
+ screen.style.display = 'block';
+ }
+ const instance = await qtLoad({
+ qt: {
+ onLoaded: () => showUi(),
+ entryFunction: window.createQtAppInstance,
+ containerElements: [screen],
+ }
+ });
+ await init_gl();
+}
+
+async function qtLoad(config)
+{
+ const throwIfEnvUsedButNotExported = (instance, config) =>
+ {
+ const environment = config.environment;
+ if (!environment || Object.keys(environment).length === 0)
+ return;
+ const isEnvExported = typeof instance.ENV === 'object';
+ if (!isEnvExported)
+ throw new Error('ENV must be exported if environment variables are passed');
+ };
+
+ const throwIfFsUsedButNotExported = (instance, config) =>
+ {
+ const environment = config.environment;
+ if (!environment || Object.keys(environment).length === 0)
+ return;
+ const isFsExported = typeof instance.FS === 'object';
+ if (!isFsExported)
+ throw new Error('FS must be exported if preload is used');
+ };
+
+ if (typeof config !== 'object')
+ throw new Error('config is required, expected an object');
+ if (typeof config.qt !== 'object')
+ throw new Error('config.qt is required, expected an object');
+ if (typeof config.qt.entryFunction !== 'function')
+ config.qt.entryFunction = window.createQtAppInstance;
+
+ config.qt.qtdir ??= 'qt';
+ config.qt.preload ??= [];
+
+ config.qtContainerElements = config.qt.containerElements;
+ delete config.qt.containerElements;
+ config.qtFontDpi = config.qt.fontDpi;
+ delete config.qt.fontDpi;
+
+ // Used for rejecting a failed load's promise where emscripten itself does not allow it,
+ // like in instantiateWasm below. This allows us to throw in case of a load error instead of
+ // hanging on a promise to entry function, which emscripten unfortunately does.
+ let circuitBreakerReject;
+ const circuitBreaker = new Promise((_, reject) => { circuitBreakerReject = reject; });
+
+ // If module async getter is present, use it so that module reuse is possible.
+ if (config.qt.module) {
+ config.instantiateWasm = async (imports, successCallback) =>
+ {
+ try {
+ const module = await config.qt.module;
+ successCallback(
+ await WebAssembly.instantiate(module, imports), module);
+ } catch (e) {
+ circuitBreakerReject(e);
+ }
+ }
+ }
+
+ const qtPreRun = (instance) => {
+ // Copy qt.environment to instance.ENV
+ throwIfEnvUsedButNotExported(instance, config);
+ for (const [name, value] of Object.entries(config.qt.environment ?? {}))
+ instance.ENV[name] = value;
+
+ // Copy self.preloadData to MEMFS
+ const makeDirs = (FS, filePath) => {
+ const parts = filePath.split("/");
+ let path = "/";
+ for (let i = 0; i < parts.length - 1; ++i) {
+ const part = parts[i];
+ if (part == "")
+ continue;
+ path += part + "/";
+ try {
+ FS.mkdir(path);
+ } catch (error) {
+ const EEXIST = 20;
+ if (error.errno != EEXIST)
+ throw error;
+ }
+ }
+ }
+ throwIfFsUsedButNotExported(instance, config);
+ for ({destination, data} of self.preloadData) {
+ makeDirs(instance.FS, destination);
+ instance.FS.writeFile(destination, new Uint8Array(data));
+ }
+ }
+
+ if (!config.preRun)
+ config.preRun = [];
+ config.preRun.push(qtPreRun);
+
+ config.onRuntimeInitialized = () => config.qt.onLoaded?.();
+
+ const originalLocateFile = config.locateFile;
+ config.locateFile = filename =>
+ {
+ const originalLocatedFilename = originalLocateFile ? originalLocateFile(filename) : filename;
+ if (originalLocatedFilename.startsWith('libQt6'))
+ return `${config.qt.qtdir}/lib/${originalLocatedFilename}`;
+ return originalLocatedFilename;
+ }
+
+ const originalOnExit = config.onExit;
+ config.onExit = code => {
+ originalOnExit?.();
+ config.qt.onExit?.({
+ code,
+ crashed: false
+ });
+ }
+
+ const originalOnAbort = config.onAbort;
+ config.onAbort = text =>
+ {
+ originalOnAbort?.();
+
+ aborted = true;
+ config.qt.onExit?.({
+ text,
+ crashed: true
+ });
+ };
+
+ const fetchPreloadFiles = async () => {
+ const fetchJson = async path => (await fetch(path)).json();
+ const fetchArrayBuffer = async path => (await fetch(path)).arrayBuffer();
+ const loadFiles = async (paths) => {
+ const source = paths['source'].replace('$QTDIR', config.qt.qtdir);
+ return {
+ destination: paths['destination'],
+ data: await fetchArrayBuffer(source)
+ };
+ }
+ const fileList = (await Promise.all(config.qt.preload.map(fetchJson))).flat();
+ self.preloadData = (await Promise.all(fileList.map(loadFiles))).flat();
+ }
+
+ await fetchPreloadFiles();
+
+ // Call app/emscripten module entry function. It may either come from the emscripten
+ // runtime script or be customized as needed.
+ let instance;
+ try {
+ instance = await Promise.race(
+ [circuitBreaker, config.qt.entryFunction(config)]);
+ } catch (e) {
+ config.qt.onExit?.({
+ text: e.message,
+ crashed: true
+ });
+ throw e;
+ }
+
+ return instance;
+}
+
+// Compatibility API. This API is deprecated,
+// and will be removed in a future version of Qt.
+function QtLoader(qtConfig) {
+
+ const warning = 'Warning: The QtLoader API is deprecated and will be removed in ' +
+ 'a future version of Qt. Please port to the new qtLoad() API.';
+ console.warn(warning);
+
+ let emscriptenConfig = qtConfig.moduleConfig || {}
+ qtConfig.moduleConfig = undefined;
+ const showLoader = qtConfig.showLoader;
+ qtConfig.showLoader = undefined;
+ const showError = qtConfig.showError;
+ qtConfig.showError = undefined;
+ const showExit = qtConfig.showExit;
+ qtConfig.showExit = undefined;
+ const showCanvas = qtConfig.showCanvas;
+ qtConfig.showCanvas = undefined;
+ if (qtConfig.canvasElements) {
+ qtConfig.containerElements = qtConfig.canvasElements
+ qtConfig.canvasElements = undefined;
+ } else {
+ qtConfig.containerElements = qtConfig.containerElements;
+ qtConfig.containerElements = undefined;
+ }
+ emscriptenConfig.qt = qtConfig;
+
+ let qtloader = {
+ exitCode: undefined,
+ exitText: "",
+ loadEmscriptenModule: _name => {
+ try {
+ qtLoad(emscriptenConfig);
+ } catch (e) {
+ showError?.(e.message);
+ }
+ }
+ }
+
+ qtConfig.onLoaded = () => {
+ showCanvas?.();
+ }
+
+ qtConfig.onExit = exit => {
+ qtloader.exitCode = exit.code
+ qtloader.exitText = exit.text;
+ showExit?.();
+ }
+
+ showLoader?.("Loading");
+
+ return qtloader;
+};
diff --git a/web_demo/static/js/gl-matrix-min.js b/web_demo/static/js/gl-matrix-min.js
new file mode 100644
index 0000000..7571ca0
--- /dev/null
+++ b/web_demo/static/js/gl-matrix-min.js
@@ -0,0 +1,28 @@
+/*!
+@fileoverview gl-matrix - High performance matrix and vector operations
+@author Brandon Jones
+@author Colin MacKenzie IV
+@version 3.4.1
+
+Copyright (c) 2015-2021, Brandon Jones, Colin MacKenzie IV.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+*/
+!function(t,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((t="undefined"!=typeof globalThis?globalThis:t||self).glMatrix={})}(this,(function(t){"use strict";var n=1e-6,a="undefined"!=typeof Float32Array?Float32Array:Array,r=Math.random;var u=Math.PI/180;Math.hypot||(Math.hypot=function(){for(var t=0,n=arguments.length;n--;)t+=arguments[n]*arguments[n];return Math.sqrt(t)});var e=Object.freeze({__proto__:null,EPSILON:n,get ARRAY_TYPE(){return a},RANDOM:r,ANGLE_ORDER:"zyx",setMatrixArrayType:function(t){a=t},toRadian:function(t){return t*u},equals:function(t,a){return Math.abs(t-a)<=n*Math.max(1,Math.abs(t),Math.abs(a))}});function o(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=a[0],h=a[1],c=a[2],s=a[3];return t[0]=r*i+e*h,t[1]=u*i+o*h,t[2]=r*c+e*s,t[3]=u*c+o*s,t}function i(t,n,a){return t[0]=n[0]-a[0],t[1]=n[1]-a[1],t[2]=n[2]-a[2],t[3]=n[3]-a[3],t}var h=o,c=i,s=Object.freeze({__proto__:null,create:function(){var t=new a(4);return a!=Float32Array&&(t[1]=0,t[2]=0),t[0]=1,t[3]=1,t},clone:function(t){var n=new a(4);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n},copy:function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t},identity:function(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t},fromValues:function(t,n,r,u){var e=new a(4);return e[0]=t,e[1]=n,e[2]=r,e[3]=u,e},set:function(t,n,a,r,u){return t[0]=n,t[1]=a,t[2]=r,t[3]=u,t},transpose:function(t,n){if(t===n){var a=n[1];t[1]=n[2],t[2]=a}else t[0]=n[0],t[1]=n[2],t[2]=n[1],t[3]=n[3];return t},invert:function(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=a*e-u*r;return o?(o=1/o,t[0]=e*o,t[1]=-r*o,t[2]=-u*o,t[3]=a*o,t):null},adjoint:function(t,n){var a=n[0];return t[0]=n[3],t[1]=-n[1],t[2]=-n[2],t[3]=a,t},determinant:function(t){return t[0]*t[3]-t[2]*t[1]},multiply:o,rotate:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=Math.sin(a),h=Math.cos(a);return t[0]=r*h+e*i,t[1]=u*h+o*i,t[2]=r*-i+e*h,t[3]=u*-i+o*h,t},scale:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=a[0],h=a[1];return t[0]=r*i,t[1]=u*i,t[2]=e*h,t[3]=o*h,t},fromRotation:function(t,n){var a=Math.sin(n),r=Math.cos(n);return t[0]=r,t[1]=a,t[2]=-a,t[3]=r,t},fromScaling:function(t,n){return t[0]=n[0],t[1]=0,t[2]=0,t[3]=n[1],t},str:function(t){return"mat2("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+")"},frob:function(t){return Math.hypot(t[0],t[1],t[2],t[3])},LDU:function(t,n,a,r){return t[2]=r[2]/r[0],a[0]=r[0],a[1]=r[1],a[3]=r[3]-t[2]*a[1],[t,n,a]},add:function(t,n,a){return t[0]=n[0]+a[0],t[1]=n[1]+a[1],t[2]=n[2]+a[2],t[3]=n[3]+a[3],t},subtract:i,exactEquals:function(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]&&t[3]===n[3]},equals:function(t,a){var r=t[0],u=t[1],e=t[2],o=t[3],i=a[0],h=a[1],c=a[2],s=a[3];return Math.abs(r-i)<=n*Math.max(1,Math.abs(r),Math.abs(i))&&Math.abs(u-h)<=n*Math.max(1,Math.abs(u),Math.abs(h))&&Math.abs(e-c)<=n*Math.max(1,Math.abs(e),Math.abs(c))&&Math.abs(o-s)<=n*Math.max(1,Math.abs(o),Math.abs(s))},multiplyScalar:function(t,n,a){return t[0]=n[0]*a,t[1]=n[1]*a,t[2]=n[2]*a,t[3]=n[3]*a,t},multiplyScalarAndAdd:function(t,n,a,r){return t[0]=n[0]+a[0]*r,t[1]=n[1]+a[1]*r,t[2]=n[2]+a[2]*r,t[3]=n[3]+a[3]*r,t},mul:h,sub:c});function M(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],h=n[5],c=a[0],s=a[1],M=a[2],f=a[3],l=a[4],v=a[5];return t[0]=r*c+e*s,t[1]=u*c+o*s,t[2]=r*M+e*f,t[3]=u*M+o*f,t[4]=r*l+e*v+i,t[5]=u*l+o*v+h,t}function f(t,n,a){return t[0]=n[0]-a[0],t[1]=n[1]-a[1],t[2]=n[2]-a[2],t[3]=n[3]-a[3],t[4]=n[4]-a[4],t[5]=n[5]-a[5],t}var l=M,v=f,b=Object.freeze({__proto__:null,create:function(){var t=new a(6);return a!=Float32Array&&(t[1]=0,t[2]=0,t[4]=0,t[5]=0),t[0]=1,t[3]=1,t},clone:function(t){var n=new a(6);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n[4]=t[4],n[5]=t[5],n},copy:function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t},identity:function(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t[4]=0,t[5]=0,t},fromValues:function(t,n,r,u,e,o){var i=new a(6);return i[0]=t,i[1]=n,i[2]=r,i[3]=u,i[4]=e,i[5]=o,i},set:function(t,n,a,r,u,e,o){return t[0]=n,t[1]=a,t[2]=r,t[3]=u,t[4]=e,t[5]=o,t},invert:function(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=n[4],i=n[5],h=a*e-r*u;return h?(h=1/h,t[0]=e*h,t[1]=-r*h,t[2]=-u*h,t[3]=a*h,t[4]=(u*i-e*o)*h,t[5]=(r*o-a*i)*h,t):null},determinant:function(t){return t[0]*t[3]-t[1]*t[2]},multiply:M,rotate:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],h=n[5],c=Math.sin(a),s=Math.cos(a);return t[0]=r*s+e*c,t[1]=u*s+o*c,t[2]=r*-c+e*s,t[3]=u*-c+o*s,t[4]=i,t[5]=h,t},scale:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],h=n[5],c=a[0],s=a[1];return t[0]=r*c,t[1]=u*c,t[2]=e*s,t[3]=o*s,t[4]=i,t[5]=h,t},translate:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],h=n[5],c=a[0],s=a[1];return t[0]=r,t[1]=u,t[2]=e,t[3]=o,t[4]=r*c+e*s+i,t[5]=u*c+o*s+h,t},fromRotation:function(t,n){var a=Math.sin(n),r=Math.cos(n);return t[0]=r,t[1]=a,t[2]=-a,t[3]=r,t[4]=0,t[5]=0,t},fromScaling:function(t,n){return t[0]=n[0],t[1]=0,t[2]=0,t[3]=n[1],t[4]=0,t[5]=0,t},fromTranslation:function(t,n){return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t[4]=n[0],t[5]=n[1],t},str:function(t){return"mat2d("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+", "+t[4]+", "+t[5]+")"},frob:function(t){return Math.hypot(t[0],t[1],t[2],t[3],t[4],t[5],1)},add:function(t,n,a){return t[0]=n[0]+a[0],t[1]=n[1]+a[1],t[2]=n[2]+a[2],t[3]=n[3]+a[3],t[4]=n[4]+a[4],t[5]=n[5]+a[5],t},subtract:f,multiplyScalar:function(t,n,a){return t[0]=n[0]*a,t[1]=n[1]*a,t[2]=n[2]*a,t[3]=n[3]*a,t[4]=n[4]*a,t[5]=n[5]*a,t},multiplyScalarAndAdd:function(t,n,a,r){return t[0]=n[0]+a[0]*r,t[1]=n[1]+a[1]*r,t[2]=n[2]+a[2]*r,t[3]=n[3]+a[3]*r,t[4]=n[4]+a[4]*r,t[5]=n[5]+a[5]*r,t},exactEquals:function(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]&&t[3]===n[3]&&t[4]===n[4]&&t[5]===n[5]},equals:function(t,a){var r=t[0],u=t[1],e=t[2],o=t[3],i=t[4],h=t[5],c=a[0],s=a[1],M=a[2],f=a[3],l=a[4],v=a[5];return Math.abs(r-c)<=n*Math.max(1,Math.abs(r),Math.abs(c))&&Math.abs(u-s)<=n*Math.max(1,Math.abs(u),Math.abs(s))&&Math.abs(e-M)<=n*Math.max(1,Math.abs(e),Math.abs(M))&&Math.abs(o-f)<=n*Math.max(1,Math.abs(o),Math.abs(f))&&Math.abs(i-l)<=n*Math.max(1,Math.abs(i),Math.abs(l))&&Math.abs(h-v)<=n*Math.max(1,Math.abs(h),Math.abs(v))},mul:l,sub:v});function m(){var t=new a(9);return a!=Float32Array&&(t[1]=0,t[2]=0,t[3]=0,t[5]=0,t[6]=0,t[7]=0),t[0]=1,t[4]=1,t[8]=1,t}function d(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],h=n[5],c=n[6],s=n[7],M=n[8],f=a[0],l=a[1],v=a[2],b=a[3],m=a[4],d=a[5],p=a[6],x=a[7],y=a[8];return t[0]=f*r+l*o+v*c,t[1]=f*u+l*i+v*s,t[2]=f*e+l*h+v*M,t[3]=b*r+m*o+d*c,t[4]=b*u+m*i+d*s,t[5]=b*e+m*h+d*M,t[6]=p*r+x*o+y*c,t[7]=p*u+x*i+y*s,t[8]=p*e+x*h+y*M,t}function p(t,n,a){return t[0]=n[0]-a[0],t[1]=n[1]-a[1],t[2]=n[2]-a[2],t[3]=n[3]-a[3],t[4]=n[4]-a[4],t[5]=n[5]-a[5],t[6]=n[6]-a[6],t[7]=n[7]-a[7],t[8]=n[8]-a[8],t}var x=d,y=p,q=Object.freeze({__proto__:null,create:m,fromMat4:function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[4],t[4]=n[5],t[5]=n[6],t[6]=n[8],t[7]=n[9],t[8]=n[10],t},clone:function(t){var n=new a(9);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n[4]=t[4],n[5]=t[5],n[6]=t[6],n[7]=t[7],n[8]=t[8],n},copy:function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],t},fromValues:function(t,n,r,u,e,o,i,h,c){var s=new a(9);return s[0]=t,s[1]=n,s[2]=r,s[3]=u,s[4]=e,s[5]=o,s[6]=i,s[7]=h,s[8]=c,s},set:function(t,n,a,r,u,e,o,i,h,c){return t[0]=n,t[1]=a,t[2]=r,t[3]=u,t[4]=e,t[5]=o,t[6]=i,t[7]=h,t[8]=c,t},identity:function(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=1,t[5]=0,t[6]=0,t[7]=0,t[8]=1,t},transpose:function(t,n){if(t===n){var a=n[1],r=n[2],u=n[5];t[1]=n[3],t[2]=n[6],t[3]=a,t[5]=n[7],t[6]=r,t[7]=u}else t[0]=n[0],t[1]=n[3],t[2]=n[6],t[3]=n[1],t[4]=n[4],t[5]=n[7],t[6]=n[2],t[7]=n[5],t[8]=n[8];return t},invert:function(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=n[4],i=n[5],h=n[6],c=n[7],s=n[8],M=s*o-i*c,f=-s*e+i*h,l=c*e-o*h,v=a*M+r*f+u*l;return v?(v=1/v,t[0]=M*v,t[1]=(-s*r+u*c)*v,t[2]=(i*r-u*o)*v,t[3]=f*v,t[4]=(s*a-u*h)*v,t[5]=(-i*a+u*e)*v,t[6]=l*v,t[7]=(-c*a+r*h)*v,t[8]=(o*a-r*e)*v,t):null},adjoint:function(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=n[4],i=n[5],h=n[6],c=n[7],s=n[8];return t[0]=o*s-i*c,t[1]=u*c-r*s,t[2]=r*i-u*o,t[3]=i*h-e*s,t[4]=a*s-u*h,t[5]=u*e-a*i,t[6]=e*c-o*h,t[7]=r*h-a*c,t[8]=a*o-r*e,t},determinant:function(t){var n=t[0],a=t[1],r=t[2],u=t[3],e=t[4],o=t[5],i=t[6],h=t[7],c=t[8];return n*(c*e-o*h)+a*(-c*u+o*i)+r*(h*u-e*i)},multiply:d,translate:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],h=n[5],c=n[6],s=n[7],M=n[8],f=a[0],l=a[1];return t[0]=r,t[1]=u,t[2]=e,t[3]=o,t[4]=i,t[5]=h,t[6]=f*r+l*o+c,t[7]=f*u+l*i+s,t[8]=f*e+l*h+M,t},rotate:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],h=n[5],c=n[6],s=n[7],M=n[8],f=Math.sin(a),l=Math.cos(a);return t[0]=l*r+f*o,t[1]=l*u+f*i,t[2]=l*e+f*h,t[3]=l*o-f*r,t[4]=l*i-f*u,t[5]=l*h-f*e,t[6]=c,t[7]=s,t[8]=M,t},scale:function(t,n,a){var r=a[0],u=a[1];return t[0]=r*n[0],t[1]=r*n[1],t[2]=r*n[2],t[3]=u*n[3],t[4]=u*n[4],t[5]=u*n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],t},fromTranslation:function(t,n){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=1,t[5]=0,t[6]=n[0],t[7]=n[1],t[8]=1,t},fromRotation:function(t,n){var a=Math.sin(n),r=Math.cos(n);return t[0]=r,t[1]=a,t[2]=0,t[3]=-a,t[4]=r,t[5]=0,t[6]=0,t[7]=0,t[8]=1,t},fromScaling:function(t,n){return t[0]=n[0],t[1]=0,t[2]=0,t[3]=0,t[4]=n[1],t[5]=0,t[6]=0,t[7]=0,t[8]=1,t},fromMat2d:function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=0,t[3]=n[2],t[4]=n[3],t[5]=0,t[6]=n[4],t[7]=n[5],t[8]=1,t},fromQuat:function(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=a+a,i=r+r,h=u+u,c=a*o,s=r*o,M=r*i,f=u*o,l=u*i,v=u*h,b=e*o,m=e*i,d=e*h;return t[0]=1-M-v,t[3]=s-d,t[6]=f+m,t[1]=s+d,t[4]=1-c-v,t[7]=l-b,t[2]=f-m,t[5]=l+b,t[8]=1-c-M,t},normalFromMat4:function(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=n[4],i=n[5],h=n[6],c=n[7],s=n[8],M=n[9],f=n[10],l=n[11],v=n[12],b=n[13],m=n[14],d=n[15],p=a*i-r*o,x=a*h-u*o,y=a*c-e*o,q=r*h-u*i,g=r*c-e*i,_=u*c-e*h,A=s*b-M*v,w=s*m-f*v,z=s*d-l*v,R=M*m-f*b,O=M*d-l*b,j=f*d-l*m,E=p*j-x*O+y*R+q*z-g*w+_*A;return E?(E=1/E,t[0]=(i*j-h*O+c*R)*E,t[1]=(h*z-o*j-c*w)*E,t[2]=(o*O-i*z+c*A)*E,t[3]=(u*O-r*j-e*R)*E,t[4]=(a*j-u*z+e*w)*E,t[5]=(r*z-a*O-e*A)*E,t[6]=(b*_-m*g+d*q)*E,t[7]=(m*y-v*_-d*x)*E,t[8]=(v*g-b*y+d*p)*E,t):null},projection:function(t,n,a){return t[0]=2/n,t[1]=0,t[2]=0,t[3]=0,t[4]=-2/a,t[5]=0,t[6]=-1,t[7]=1,t[8]=1,t},str:function(t){return"mat3("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+", "+t[4]+", "+t[5]+", "+t[6]+", "+t[7]+", "+t[8]+")"},frob:function(t){return Math.hypot(t[0],t[1],t[2],t[3],t[4],t[5],t[6],t[7],t[8])},add:function(t,n,a){return t[0]=n[0]+a[0],t[1]=n[1]+a[1],t[2]=n[2]+a[2],t[3]=n[3]+a[3],t[4]=n[4]+a[4],t[5]=n[5]+a[5],t[6]=n[6]+a[6],t[7]=n[7]+a[7],t[8]=n[8]+a[8],t},subtract:p,multiplyScalar:function(t,n,a){return t[0]=n[0]*a,t[1]=n[1]*a,t[2]=n[2]*a,t[3]=n[3]*a,t[4]=n[4]*a,t[5]=n[5]*a,t[6]=n[6]*a,t[7]=n[7]*a,t[8]=n[8]*a,t},multiplyScalarAndAdd:function(t,n,a,r){return t[0]=n[0]+a[0]*r,t[1]=n[1]+a[1]*r,t[2]=n[2]+a[2]*r,t[3]=n[3]+a[3]*r,t[4]=n[4]+a[4]*r,t[5]=n[5]+a[5]*r,t[6]=n[6]+a[6]*r,t[7]=n[7]+a[7]*r,t[8]=n[8]+a[8]*r,t},exactEquals:function(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]&&t[3]===n[3]&&t[4]===n[4]&&t[5]===n[5]&&t[6]===n[6]&&t[7]===n[7]&&t[8]===n[8]},equals:function(t,a){var r=t[0],u=t[1],e=t[2],o=t[3],i=t[4],h=t[5],c=t[6],s=t[7],M=t[8],f=a[0],l=a[1],v=a[2],b=a[3],m=a[4],d=a[5],p=a[6],x=a[7],y=a[8];return Math.abs(r-f)<=n*Math.max(1,Math.abs(r),Math.abs(f))&&Math.abs(u-l)<=n*Math.max(1,Math.abs(u),Math.abs(l))&&Math.abs(e-v)<=n*Math.max(1,Math.abs(e),Math.abs(v))&&Math.abs(o-b)<=n*Math.max(1,Math.abs(o),Math.abs(b))&&Math.abs(i-m)<=n*Math.max(1,Math.abs(i),Math.abs(m))&&Math.abs(h-d)<=n*Math.max(1,Math.abs(h),Math.abs(d))&&Math.abs(c-p)<=n*Math.max(1,Math.abs(c),Math.abs(p))&&Math.abs(s-x)<=n*Math.max(1,Math.abs(s),Math.abs(x))&&Math.abs(M-y)<=n*Math.max(1,Math.abs(M),Math.abs(y))},mul:x,sub:y});function g(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=1,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=1,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t}function _(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],h=n[5],c=n[6],s=n[7],M=n[8],f=n[9],l=n[10],v=n[11],b=n[12],m=n[13],d=n[14],p=n[15],x=a[0],y=a[1],q=a[2],g=a[3];return t[0]=x*r+y*i+q*M+g*b,t[1]=x*u+y*h+q*f+g*m,t[2]=x*e+y*c+q*l+g*d,t[3]=x*o+y*s+q*v+g*p,x=a[4],y=a[5],q=a[6],g=a[7],t[4]=x*r+y*i+q*M+g*b,t[5]=x*u+y*h+q*f+g*m,t[6]=x*e+y*c+q*l+g*d,t[7]=x*o+y*s+q*v+g*p,x=a[8],y=a[9],q=a[10],g=a[11],t[8]=x*r+y*i+q*M+g*b,t[9]=x*u+y*h+q*f+g*m,t[10]=x*e+y*c+q*l+g*d,t[11]=x*o+y*s+q*v+g*p,x=a[12],y=a[13],q=a[14],g=a[15],t[12]=x*r+y*i+q*M+g*b,t[13]=x*u+y*h+q*f+g*m,t[14]=x*e+y*c+q*l+g*d,t[15]=x*o+y*s+q*v+g*p,t}function A(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=r+r,h=u+u,c=e+e,s=r*i,M=r*h,f=r*c,l=u*h,v=u*c,b=e*c,m=o*i,d=o*h,p=o*c;return t[0]=1-(l+b),t[1]=M+p,t[2]=f-d,t[3]=0,t[4]=M-p,t[5]=1-(s+b),t[6]=v+m,t[7]=0,t[8]=f+d,t[9]=v-m,t[10]=1-(s+l),t[11]=0,t[12]=a[0],t[13]=a[1],t[14]=a[2],t[15]=1,t}function w(t,n){return t[0]=n[12],t[1]=n[13],t[2]=n[14],t}function z(t,n){var a=n[0],r=n[1],u=n[2],e=n[4],o=n[5],i=n[6],h=n[8],c=n[9],s=n[10];return t[0]=Math.hypot(a,r,u),t[1]=Math.hypot(e,o,i),t[2]=Math.hypot(h,c,s),t}function R(t,n){var r=new a(3);z(r,n);var u=1/r[0],e=1/r[1],o=1/r[2],i=n[0]*u,h=n[1]*e,c=n[2]*o,s=n[4]*u,M=n[5]*e,f=n[6]*o,l=n[8]*u,v=n[9]*e,b=n[10]*o,m=i+M+b,d=0;return m>0?(d=2*Math.sqrt(m+1),t[3]=.25*d,t[0]=(f-v)/d,t[1]=(l-c)/d,t[2]=(h-s)/d):i>M&&i>b?(d=2*Math.sqrt(1+i-M-b),t[3]=(f-v)/d,t[0]=.25*d,t[1]=(h+s)/d,t[2]=(l+c)/d):M>b?(d=2*Math.sqrt(1+M-i-b),t[3]=(l-c)/d,t[0]=(h+s)/d,t[1]=.25*d,t[2]=(f+v)/d):(d=2*Math.sqrt(1+b-i-M),t[3]=(h-s)/d,t[0]=(l+c)/d,t[1]=(f+v)/d,t[2]=.25*d),t}function O(t,n,a,r,u){var e=1/Math.tan(n/2);if(t[0]=e/a,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=e,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[11]=-1,t[12]=0,t[13]=0,t[15]=0,null!=u&&u!==1/0){var o=1/(r-u);t[10]=(u+r)*o,t[14]=2*u*r*o}else t[10]=-1,t[14]=-2*r;return t}var j=O;function E(t,n,a,r,u,e,o){var i=1/(n-a),h=1/(r-u),c=1/(e-o);return t[0]=-2*i,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=-2*h,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=2*c,t[11]=0,t[12]=(n+a)*i,t[13]=(u+r)*h,t[14]=(o+e)*c,t[15]=1,t}var P=E;function T(t,n,a){return t[0]=n[0]-a[0],t[1]=n[1]-a[1],t[2]=n[2]-a[2],t[3]=n[3]-a[3],t[4]=n[4]-a[4],t[5]=n[5]-a[5],t[6]=n[6]-a[6],t[7]=n[7]-a[7],t[8]=n[8]-a[8],t[9]=n[9]-a[9],t[10]=n[10]-a[10],t[11]=n[11]-a[11],t[12]=n[12]-a[12],t[13]=n[13]-a[13],t[14]=n[14]-a[14],t[15]=n[15]-a[15],t}var S=_,D=T,F=Object.freeze({__proto__:null,create:function(){var t=new a(16);return a!=Float32Array&&(t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[11]=0,t[12]=0,t[13]=0,t[14]=0),t[0]=1,t[5]=1,t[10]=1,t[15]=1,t},clone:function(t){var n=new a(16);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n[4]=t[4],n[5]=t[5],n[6]=t[6],n[7]=t[7],n[8]=t[8],n[9]=t[9],n[10]=t[10],n[11]=t[11],n[12]=t[12],n[13]=t[13],n[14]=t[14],n[15]=t[15],n},copy:function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],t[9]=n[9],t[10]=n[10],t[11]=n[11],t[12]=n[12],t[13]=n[13],t[14]=n[14],t[15]=n[15],t},fromValues:function(t,n,r,u,e,o,i,h,c,s,M,f,l,v,b,m){var d=new a(16);return d[0]=t,d[1]=n,d[2]=r,d[3]=u,d[4]=e,d[5]=o,d[6]=i,d[7]=h,d[8]=c,d[9]=s,d[10]=M,d[11]=f,d[12]=l,d[13]=v,d[14]=b,d[15]=m,d},set:function(t,n,a,r,u,e,o,i,h,c,s,M,f,l,v,b,m){return t[0]=n,t[1]=a,t[2]=r,t[3]=u,t[4]=e,t[5]=o,t[6]=i,t[7]=h,t[8]=c,t[9]=s,t[10]=M,t[11]=f,t[12]=l,t[13]=v,t[14]=b,t[15]=m,t},identity:g,transpose:function(t,n){if(t===n){var a=n[1],r=n[2],u=n[3],e=n[6],o=n[7],i=n[11];t[1]=n[4],t[2]=n[8],t[3]=n[12],t[4]=a,t[6]=n[9],t[7]=n[13],t[8]=r,t[9]=e,t[11]=n[14],t[12]=u,t[13]=o,t[14]=i}else t[0]=n[0],t[1]=n[4],t[2]=n[8],t[3]=n[12],t[4]=n[1],t[5]=n[5],t[6]=n[9],t[7]=n[13],t[8]=n[2],t[9]=n[6],t[10]=n[10],t[11]=n[14],t[12]=n[3],t[13]=n[7],t[14]=n[11],t[15]=n[15];return t},invert:function(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=n[4],i=n[5],h=n[6],c=n[7],s=n[8],M=n[9],f=n[10],l=n[11],v=n[12],b=n[13],m=n[14],d=n[15],p=a*i-r*o,x=a*h-u*o,y=a*c-e*o,q=r*h-u*i,g=r*c-e*i,_=u*c-e*h,A=s*b-M*v,w=s*m-f*v,z=s*d-l*v,R=M*m-f*b,O=M*d-l*b,j=f*d-l*m,E=p*j-x*O+y*R+q*z-g*w+_*A;return E?(E=1/E,t[0]=(i*j-h*O+c*R)*E,t[1]=(u*O-r*j-e*R)*E,t[2]=(b*_-m*g+d*q)*E,t[3]=(f*g-M*_-l*q)*E,t[4]=(h*z-o*j-c*w)*E,t[5]=(a*j-u*z+e*w)*E,t[6]=(m*y-v*_-d*x)*E,t[7]=(s*_-f*y+l*x)*E,t[8]=(o*O-i*z+c*A)*E,t[9]=(r*z-a*O-e*A)*E,t[10]=(v*g-b*y+d*p)*E,t[11]=(M*y-s*g-l*p)*E,t[12]=(i*w-o*R-h*A)*E,t[13]=(a*R-r*w+u*A)*E,t[14]=(b*x-v*q-m*p)*E,t[15]=(s*q-M*x+f*p)*E,t):null},adjoint:function(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=n[4],i=n[5],h=n[6],c=n[7],s=n[8],M=n[9],f=n[10],l=n[11],v=n[12],b=n[13],m=n[14],d=n[15],p=a*i-r*o,x=a*h-u*o,y=a*c-e*o,q=r*h-u*i,g=r*c-e*i,_=u*c-e*h,A=s*b-M*v,w=s*m-f*v,z=s*d-l*v,R=M*m-f*b,O=M*d-l*b,j=f*d-l*m;return t[0]=i*j-h*O+c*R,t[1]=u*O-r*j-e*R,t[2]=b*_-m*g+d*q,t[3]=f*g-M*_-l*q,t[4]=h*z-o*j-c*w,t[5]=a*j-u*z+e*w,t[6]=m*y-v*_-d*x,t[7]=s*_-f*y+l*x,t[8]=o*O-i*z+c*A,t[9]=r*z-a*O-e*A,t[10]=v*g-b*y+d*p,t[11]=M*y-s*g-l*p,t[12]=i*w-o*R-h*A,t[13]=a*R-r*w+u*A,t[14]=b*x-v*q-m*p,t[15]=s*q-M*x+f*p,t},determinant:function(t){var n=t[0],a=t[1],r=t[2],u=t[3],e=t[4],o=t[5],i=t[6],h=t[7],c=t[8],s=t[9],M=t[10],f=t[11],l=t[12],v=t[13],b=t[14],m=n*o-a*e,d=n*i-r*e,p=a*i-r*o,x=c*v-s*l,y=c*b-M*l,q=s*b-M*v;return h*(n*q-a*y+r*x)-u*(e*q-o*y+i*x)+t[15]*(c*p-s*d+M*m)-f*(l*p-v*d+b*m)},multiply:_,translate:function(t,n,a){var r,u,e,o,i,h,c,s,M,f,l,v,b=a[0],m=a[1],d=a[2];return n===t?(t[12]=n[0]*b+n[4]*m+n[8]*d+n[12],t[13]=n[1]*b+n[5]*m+n[9]*d+n[13],t[14]=n[2]*b+n[6]*m+n[10]*d+n[14],t[15]=n[3]*b+n[7]*m+n[11]*d+n[15]):(r=n[0],u=n[1],e=n[2],o=n[3],i=n[4],h=n[5],c=n[6],s=n[7],M=n[8],f=n[9],l=n[10],v=n[11],t[0]=r,t[1]=u,t[2]=e,t[3]=o,t[4]=i,t[5]=h,t[6]=c,t[7]=s,t[8]=M,t[9]=f,t[10]=l,t[11]=v,t[12]=r*b+i*m+M*d+n[12],t[13]=u*b+h*m+f*d+n[13],t[14]=e*b+c*m+l*d+n[14],t[15]=o*b+s*m+v*d+n[15]),t},scale:function(t,n,a){var r=a[0],u=a[1],e=a[2];return t[0]=n[0]*r,t[1]=n[1]*r,t[2]=n[2]*r,t[3]=n[3]*r,t[4]=n[4]*u,t[5]=n[5]*u,t[6]=n[6]*u,t[7]=n[7]*u,t[8]=n[8]*e,t[9]=n[9]*e,t[10]=n[10]*e,t[11]=n[11]*e,t[12]=n[12],t[13]=n[13],t[14]=n[14],t[15]=n[15],t},rotate:function(t,a,r,u){var e,o,i,h,c,s,M,f,l,v,b,m,d,p,x,y,q,g,_,A,w,z,R,O,j=u[0],E=u[1],P=u[2],T=Math.hypot(j,E,P);return T0?(r[0]=2*(h*i+M*u+c*o-s*e)/f,r[1]=2*(c*i+M*e+s*u-h*o)/f,r[2]=2*(s*i+M*o+h*e-c*u)/f):(r[0]=2*(h*i+M*u+c*o-s*e),r[1]=2*(c*i+M*e+s*u-h*o),r[2]=2*(s*i+M*o+h*e-c*u)),A(t,n,r),t},getTranslation:w,getScaling:z,getRotation:R,decompose:function(t,n,a,r){n[0]=r[12],n[1]=r[13],n[2]=r[14];var u=r[0],e=r[1],o=r[2],i=r[4],h=r[5],c=r[6],s=r[8],M=r[9],f=r[10];a[0]=Math.hypot(u,e,o),a[1]=Math.hypot(i,h,c),a[2]=Math.hypot(s,M,f);var l=1/a[0],v=1/a[1],b=1/a[2],m=u*l,d=e*v,p=o*b,x=i*l,y=h*v,q=c*b,g=s*l,_=M*v,A=f*b,w=m+y+A,z=0;return w>0?(z=2*Math.sqrt(w+1),t[3]=.25*z,t[0]=(q-_)/z,t[1]=(g-p)/z,t[2]=(d-x)/z):m>y&&m>A?(z=2*Math.sqrt(1+m-y-A),t[3]=(q-_)/z,t[0]=.25*z,t[1]=(d+x)/z,t[2]=(g+p)/z):y>A?(z=2*Math.sqrt(1+y-m-A),t[3]=(g-p)/z,t[0]=(d+x)/z,t[1]=.25*z,t[2]=(q+_)/z):(z=2*Math.sqrt(1+A-m-y),t[3]=(d-x)/z,t[0]=(g+p)/z,t[1]=(q+_)/z,t[2]=.25*z),t},fromRotationTranslationScale:function(t,n,a,r){var u=n[0],e=n[1],o=n[2],i=n[3],h=u+u,c=e+e,s=o+o,M=u*h,f=u*c,l=u*s,v=e*c,b=e*s,m=o*s,d=i*h,p=i*c,x=i*s,y=r[0],q=r[1],g=r[2];return t[0]=(1-(v+m))*y,t[1]=(f+x)*y,t[2]=(l-p)*y,t[3]=0,t[4]=(f-x)*q,t[5]=(1-(M+m))*q,t[6]=(b+d)*q,t[7]=0,t[8]=(l+p)*g,t[9]=(b-d)*g,t[10]=(1-(M+v))*g,t[11]=0,t[12]=a[0],t[13]=a[1],t[14]=a[2],t[15]=1,t},fromRotationTranslationScaleOrigin:function(t,n,a,r,u){var e=n[0],o=n[1],i=n[2],h=n[3],c=e+e,s=o+o,M=i+i,f=e*c,l=e*s,v=e*M,b=o*s,m=o*M,d=i*M,p=h*c,x=h*s,y=h*M,q=r[0],g=r[1],_=r[2],A=u[0],w=u[1],z=u[2],R=(1-(b+d))*q,O=(l+y)*q,j=(v-x)*q,E=(l-y)*g,P=(1-(f+d))*g,T=(m+p)*g,S=(v+x)*_,D=(m-p)*_,F=(1-(f+b))*_;return t[0]=R,t[1]=O,t[2]=j,t[3]=0,t[4]=E,t[5]=P,t[6]=T,t[7]=0,t[8]=S,t[9]=D,t[10]=F,t[11]=0,t[12]=a[0]+A-(R*A+E*w+S*z),t[13]=a[1]+w-(O*A+P*w+D*z),t[14]=a[2]+z-(j*A+T*w+F*z),t[15]=1,t},fromQuat:function(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=a+a,i=r+r,h=u+u,c=a*o,s=r*o,M=r*i,f=u*o,l=u*i,v=u*h,b=e*o,m=e*i,d=e*h;return t[0]=1-M-v,t[1]=s+d,t[2]=f-m,t[3]=0,t[4]=s-d,t[5]=1-c-v,t[6]=l+b,t[7]=0,t[8]=f+m,t[9]=l-b,t[10]=1-c-M,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t},frustum:function(t,n,a,r,u,e,o){var i=1/(a-n),h=1/(u-r),c=1/(e-o);return t[0]=2*e*i,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=2*e*h,t[6]=0,t[7]=0,t[8]=(a+n)*i,t[9]=(u+r)*h,t[10]=(o+e)*c,t[11]=-1,t[12]=0,t[13]=0,t[14]=o*e*2*c,t[15]=0,t},perspectiveNO:O,perspective:j,perspectiveZO:function(t,n,a,r,u){var e=1/Math.tan(n/2);if(t[0]=e/a,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=e,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[11]=-1,t[12]=0,t[13]=0,t[15]=0,null!=u&&u!==1/0){var o=1/(r-u);t[10]=u*o,t[14]=u*r*o}else t[10]=-1,t[14]=-r;return t},perspectiveFromFieldOfView:function(t,n,a,r){var u=Math.tan(n.upDegrees*Math.PI/180),e=Math.tan(n.downDegrees*Math.PI/180),o=Math.tan(n.leftDegrees*Math.PI/180),i=Math.tan(n.rightDegrees*Math.PI/180),h=2/(o+i),c=2/(u+e);return t[0]=h,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=c,t[6]=0,t[7]=0,t[8]=-(o-i)*h*.5,t[9]=(u-e)*c*.5,t[10]=r/(a-r),t[11]=-1,t[12]=0,t[13]=0,t[14]=r*a/(a-r),t[15]=0,t},orthoNO:E,ortho:P,orthoZO:function(t,n,a,r,u,e,o){var i=1/(n-a),h=1/(r-u),c=1/(e-o);return t[0]=-2*i,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=-2*h,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=c,t[11]=0,t[12]=(n+a)*i,t[13]=(u+r)*h,t[14]=e*c,t[15]=1,t},lookAt:function(t,a,r,u){var e,o,i,h,c,s,M,f,l,v,b=a[0],m=a[1],d=a[2],p=u[0],x=u[1],y=u[2],q=r[0],_=r[1],A=r[2];return Math.abs(b-q)0&&(s*=l=1/Math.sqrt(l),M*=l,f*=l);var v=h*f-c*M,b=c*s-i*f,m=i*M-h*s;return(l=v*v+b*b+m*m)>0&&(v*=l=1/Math.sqrt(l),b*=l,m*=l),t[0]=v,t[1]=b,t[2]=m,t[3]=0,t[4]=M*m-f*b,t[5]=f*v-s*m,t[6]=s*b-M*v,t[7]=0,t[8]=s,t[9]=M,t[10]=f,t[11]=0,t[12]=u,t[13]=e,t[14]=o,t[15]=1,t},str:function(t){return"mat4("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+", "+t[4]+", "+t[5]+", "+t[6]+", "+t[7]+", "+t[8]+", "+t[9]+", "+t[10]+", "+t[11]+", "+t[12]+", "+t[13]+", "+t[14]+", "+t[15]+")"},frob:function(t){return Math.hypot(t[0],t[1],t[2],t[3],t[4],t[5],t[6],t[7],t[8],t[9],t[10],t[11],t[12],t[13],t[14],t[15])},add:function(t,n,a){return t[0]=n[0]+a[0],t[1]=n[1]+a[1],t[2]=n[2]+a[2],t[3]=n[3]+a[3],t[4]=n[4]+a[4],t[5]=n[5]+a[5],t[6]=n[6]+a[6],t[7]=n[7]+a[7],t[8]=n[8]+a[8],t[9]=n[9]+a[9],t[10]=n[10]+a[10],t[11]=n[11]+a[11],t[12]=n[12]+a[12],t[13]=n[13]+a[13],t[14]=n[14]+a[14],t[15]=n[15]+a[15],t},subtract:T,multiplyScalar:function(t,n,a){return t[0]=n[0]*a,t[1]=n[1]*a,t[2]=n[2]*a,t[3]=n[3]*a,t[4]=n[4]*a,t[5]=n[5]*a,t[6]=n[6]*a,t[7]=n[7]*a,t[8]=n[8]*a,t[9]=n[9]*a,t[10]=n[10]*a,t[11]=n[11]*a,t[12]=n[12]*a,t[13]=n[13]*a,t[14]=n[14]*a,t[15]=n[15]*a,t},multiplyScalarAndAdd:function(t,n,a,r){return t[0]=n[0]+a[0]*r,t[1]=n[1]+a[1]*r,t[2]=n[2]+a[2]*r,t[3]=n[3]+a[3]*r,t[4]=n[4]+a[4]*r,t[5]=n[5]+a[5]*r,t[6]=n[6]+a[6]*r,t[7]=n[7]+a[7]*r,t[8]=n[8]+a[8]*r,t[9]=n[9]+a[9]*r,t[10]=n[10]+a[10]*r,t[11]=n[11]+a[11]*r,t[12]=n[12]+a[12]*r,t[13]=n[13]+a[13]*r,t[14]=n[14]+a[14]*r,t[15]=n[15]+a[15]*r,t},exactEquals:function(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]&&t[3]===n[3]&&t[4]===n[4]&&t[5]===n[5]&&t[6]===n[6]&&t[7]===n[7]&&t[8]===n[8]&&t[9]===n[9]&&t[10]===n[10]&&t[11]===n[11]&&t[12]===n[12]&&t[13]===n[13]&&t[14]===n[14]&&t[15]===n[15]},equals:function(t,a){var r=t[0],u=t[1],e=t[2],o=t[3],i=t[4],h=t[5],c=t[6],s=t[7],M=t[8],f=t[9],l=t[10],v=t[11],b=t[12],m=t[13],d=t[14],p=t[15],x=a[0],y=a[1],q=a[2],g=a[3],_=a[4],A=a[5],w=a[6],z=a[7],R=a[8],O=a[9],j=a[10],E=a[11],P=a[12],T=a[13],S=a[14],D=a[15];return Math.abs(r-x)<=n*Math.max(1,Math.abs(r),Math.abs(x))&&Math.abs(u-y)<=n*Math.max(1,Math.abs(u),Math.abs(y))&&Math.abs(e-q)<=n*Math.max(1,Math.abs(e),Math.abs(q))&&Math.abs(o-g)<=n*Math.max(1,Math.abs(o),Math.abs(g))&&Math.abs(i-_)<=n*Math.max(1,Math.abs(i),Math.abs(_))&&Math.abs(h-A)<=n*Math.max(1,Math.abs(h),Math.abs(A))&&Math.abs(c-w)<=n*Math.max(1,Math.abs(c),Math.abs(w))&&Math.abs(s-z)<=n*Math.max(1,Math.abs(s),Math.abs(z))&&Math.abs(M-R)<=n*Math.max(1,Math.abs(M),Math.abs(R))&&Math.abs(f-O)<=n*Math.max(1,Math.abs(f),Math.abs(O))&&Math.abs(l-j)<=n*Math.max(1,Math.abs(l),Math.abs(j))&&Math.abs(v-E)<=n*Math.max(1,Math.abs(v),Math.abs(E))&&Math.abs(b-P)<=n*Math.max(1,Math.abs(b),Math.abs(P))&&Math.abs(m-T)<=n*Math.max(1,Math.abs(m),Math.abs(T))&&Math.abs(d-S)<=n*Math.max(1,Math.abs(d),Math.abs(S))&&Math.abs(p-D)<=n*Math.max(1,Math.abs(p),Math.abs(D))},mul:S,sub:D});function I(){var t=new a(3);return a!=Float32Array&&(t[0]=0,t[1]=0,t[2]=0),t}function L(t){var n=t[0],a=t[1],r=t[2];return Math.hypot(n,a,r)}function V(t,n,r){var u=new a(3);return u[0]=t,u[1]=n,u[2]=r,u}function k(t,n,a){return t[0]=n[0]-a[0],t[1]=n[1]-a[1],t[2]=n[2]-a[2],t}function Q(t,n,a){return t[0]=n[0]*a[0],t[1]=n[1]*a[1],t[2]=n[2]*a[2],t}function Y(t,n,a){return t[0]=n[0]/a[0],t[1]=n[1]/a[1],t[2]=n[2]/a[2],t}function Z(t,n){var a=n[0]-t[0],r=n[1]-t[1],u=n[2]-t[2];return Math.hypot(a,r,u)}function N(t,n){var a=n[0]-t[0],r=n[1]-t[1],u=n[2]-t[2];return a*a+r*r+u*u}function X(t){var n=t[0],a=t[1],r=t[2];return n*n+a*a+r*r}function B(t,n){var a=n[0],r=n[1],u=n[2],e=a*a+r*r+u*u;return e>0&&(e=1/Math.sqrt(e)),t[0]=n[0]*e,t[1]=n[1]*e,t[2]=n[2]*e,t}function U(t,n){return t[0]*n[0]+t[1]*n[1]+t[2]*n[2]}function G(t,n,a){var r=n[0],u=n[1],e=n[2],o=a[0],i=a[1],h=a[2];return t[0]=u*h-e*i,t[1]=e*o-r*h,t[2]=r*i-u*o,t}var W,C=k,H=Q,J=Y,K=Z,$=N,tt=L,nt=X,at=(W=I(),function(t,n,a,r,u,e){var o,i;for(n||(n=3),a||(a=0),i=r?Math.min(r*n+a,t.length):t.length,o=a;o0&&(o=1/Math.sqrt(o)),t[0]=a*o,t[1]=r*o,t[2]=u*o,t[3]=e*o,t}function xt(t,n){return t[0]*n[0]+t[1]*n[1]+t[2]*n[2]+t[3]*n[3]}function yt(t,n,a,r){var u=n[0],e=n[1],o=n[2],i=n[3];return t[0]=u+r*(a[0]-u),t[1]=e+r*(a[1]-e),t[2]=o+r*(a[2]-o),t[3]=i+r*(a[3]-i),t}function qt(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]&&t[3]===n[3]}var gt=st,_t=Mt,At=ft,wt=vt,zt=bt,Rt=mt,Ot=dt,jt=function(){var t=ut();return function(n,a,r,u,e,o){var i,h;for(a||(a=4),r||(r=0),h=u?Math.min(u*a+r,n.length):n.length,i=r;i=1);do{h=(e=2*r()-1)*e+(o=2*r()-1)*o}while(h>=1);var c=Math.sqrt((1-i)/h);return t[0]=n*a,t[1]=n*u,t[2]=n*e*c,t[3]=n*o*c,t},transformMat4:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3];return t[0]=a[0]*r+a[4]*u+a[8]*e+a[12]*o,t[1]=a[1]*r+a[5]*u+a[9]*e+a[13]*o,t[2]=a[2]*r+a[6]*u+a[10]*e+a[14]*o,t[3]=a[3]*r+a[7]*u+a[11]*e+a[15]*o,t},transformQuat:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=a[0],i=a[1],h=a[2],c=a[3],s=c*r+i*e-h*u,M=c*u+h*r-o*e,f=c*e+o*u-i*r,l=-o*r-i*u-h*e;return t[0]=s*c+l*-o+M*-h-f*-i,t[1]=M*c+l*-i+f*-o-s*-h,t[2]=f*c+l*-h+s*-i-M*-o,t[3]=n[3],t},zero:function(t){return t[0]=0,t[1]=0,t[2]=0,t[3]=0,t},str:function(t){return"vec4("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+")"},exactEquals:qt,equals:function(t,a){var r=t[0],u=t[1],e=t[2],o=t[3],i=a[0],h=a[1],c=a[2],s=a[3];return Math.abs(r-i)<=n*Math.max(1,Math.abs(r),Math.abs(i))&&Math.abs(u-h)<=n*Math.max(1,Math.abs(u),Math.abs(h))&&Math.abs(e-c)<=n*Math.max(1,Math.abs(e),Math.abs(c))&&Math.abs(o-s)<=n*Math.max(1,Math.abs(o),Math.abs(s))},sub:gt,mul:_t,div:At,dist:wt,sqrDist:zt,len:Rt,sqrLen:Ot,forEach:jt});function Pt(){var t=new a(4);return a!=Float32Array&&(t[0]=0,t[1]=0,t[2]=0),t[3]=1,t}function Tt(t,n,a){a*=.5;var r=Math.sin(a);return t[0]=r*n[0],t[1]=r*n[1],t[2]=r*n[2],t[3]=Math.cos(a),t}function St(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=a[0],h=a[1],c=a[2],s=a[3];return t[0]=r*s+o*i+u*c-e*h,t[1]=u*s+o*h+e*i-r*c,t[2]=e*s+o*c+r*h-u*i,t[3]=o*s-r*i-u*h-e*c,t}function Dt(t,n,a){a*=.5;var r=n[0],u=n[1],e=n[2],o=n[3],i=Math.sin(a),h=Math.cos(a);return t[0]=r*h+o*i,t[1]=u*h+e*i,t[2]=e*h-u*i,t[3]=o*h-r*i,t}function Ft(t,n,a){a*=.5;var r=n[0],u=n[1],e=n[2],o=n[3],i=Math.sin(a),h=Math.cos(a);return t[0]=r*h-e*i,t[1]=u*h+o*i,t[2]=e*h+r*i,t[3]=o*h-u*i,t}function It(t,n,a){a*=.5;var r=n[0],u=n[1],e=n[2],o=n[3],i=Math.sin(a),h=Math.cos(a);return t[0]=r*h+u*i,t[1]=u*h-r*i,t[2]=e*h+o*i,t[3]=o*h-e*i,t}function Lt(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=Math.sqrt(a*a+r*r+u*u),i=Math.exp(e),h=o>0?i*Math.sin(o)/o:0;return t[0]=a*h,t[1]=r*h,t[2]=u*h,t[3]=i*Math.cos(o),t}function Vt(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=Math.sqrt(a*a+r*r+u*u),i=o>0?Math.atan2(o,e)/o:0;return t[0]=a*i,t[1]=r*i,t[2]=u*i,t[3]=.5*Math.log(a*a+r*r+u*u+e*e),t}function kt(t,a,r,u){var e,o,i,h,c,s=a[0],M=a[1],f=a[2],l=a[3],v=r[0],b=r[1],m=r[2],d=r[3];return(o=s*v+M*b+f*m+l*d)<0&&(o=-o,v=-v,b=-b,m=-m,d=-d),1-o>n?(e=Math.acos(o),i=Math.sin(e),h=Math.sin((1-u)*e)/i,c=Math.sin(u*e)/i):(h=1-u,c=u),t[0]=h*s+c*v,t[1]=h*M+c*b,t[2]=h*f+c*m,t[3]=h*l+c*d,t}function Qt(t,n){var a,r=n[0]+n[4]+n[8];if(r>0)a=Math.sqrt(r+1),t[3]=.5*a,a=.5/a,t[0]=(n[5]-n[7])*a,t[1]=(n[6]-n[2])*a,t[2]=(n[1]-n[3])*a;else{var u=0;n[4]>n[0]&&(u=1),n[8]>n[3*u+u]&&(u=2);var e=(u+1)%3,o=(u+2)%3;a=Math.sqrt(n[3*u+u]-n[3*e+e]-n[3*o+o]+1),t[u]=.5*a,a=.5/a,t[3]=(n[3*e+o]-n[3*o+e])*a,t[e]=(n[3*e+u]+n[3*u+e])*a,t[o]=(n[3*o+u]+n[3*u+o])*a}return t}var Yt=et,Zt=ot,Nt=it,Xt=ht,Bt=ct,Ut=St,Gt=lt,Wt=xt,Ct=yt,Ht=mt,Jt=Ht,Kt=dt,$t=Kt,tn=pt,nn=qt;var an,rn,un,en,on,hn,cn=(an=I(),rn=V(1,0,0),un=V(0,1,0),function(t,n,a){var r=U(n,a);return r<-.999999?(G(an,rn,n),tt(an)<1e-6&&G(an,un,n),B(an,an),Tt(t,an,Math.PI),t):r>.999999?(t[0]=0,t[1]=0,t[2]=0,t[3]=1,t):(G(an,n,a),t[0]=an[0],t[1]=an[1],t[2]=an[2],t[3]=1+r,tn(t,t))}),sn=(en=Pt(),on=Pt(),function(t,n,a,r,u,e){return kt(en,n,u,e),kt(on,a,r,e),kt(t,en,on,2*e*(1-e)),t}),Mn=(hn=m(),function(t,n,a,r){return hn[0]=a[0],hn[3]=a[1],hn[6]=a[2],hn[1]=r[0],hn[4]=r[1],hn[7]=r[2],hn[2]=-n[0],hn[5]=-n[1],hn[8]=-n[2],tn(t,Qt(t,hn))}),fn=Object.freeze({__proto__:null,create:Pt,identity:function(t){return t[0]=0,t[1]=0,t[2]=0,t[3]=1,t},setAxisAngle:Tt,getAxisAngle:function(t,a){var r=2*Math.acos(a[3]),u=Math.sin(r/2);return u>n?(t[0]=a[0]/u,t[1]=a[1]/u,t[2]=a[2]/u):(t[0]=1,t[1]=0,t[2]=0),r},getAngle:function(t,n){var a=Wt(t,n);return Math.acos(2*a*a-1)},multiply:St,rotateX:Dt,rotateY:Ft,rotateZ:It,calculateW:function(t,n){var a=n[0],r=n[1],u=n[2];return t[0]=a,t[1]=r,t[2]=u,t[3]=Math.sqrt(Math.abs(1-a*a-r*r-u*u)),t},exp:Lt,ln:Vt,pow:function(t,n,a){return Vt(t,n),Gt(t,t,a),Lt(t,t),t},slerp:kt,random:function(t){var n=r(),a=r(),u=r(),e=Math.sqrt(1-n),o=Math.sqrt(n);return t[0]=e*Math.sin(2*Math.PI*a),t[1]=e*Math.cos(2*Math.PI*a),t[2]=o*Math.sin(2*Math.PI*u),t[3]=o*Math.cos(2*Math.PI*u),t},invert:function(t,n){var a=n[0],r=n[1],u=n[2],e=n[3],o=a*a+r*r+u*u+e*e,i=o?1/o:0;return t[0]=-a*i,t[1]=-r*i,t[2]=-u*i,t[3]=e*i,t},conjugate:function(t,n){return t[0]=-n[0],t[1]=-n[1],t[2]=-n[2],t[3]=n[3],t},fromMat3:Qt,fromEuler:function(t,n,a,r){var u=arguments.length>4&&void 0!==arguments[4]?arguments[4]:"zyx",e=Math.PI/360;n*=e,r*=e,a*=e;var o=Math.sin(n),i=Math.cos(n),h=Math.sin(a),c=Math.cos(a),s=Math.sin(r),M=Math.cos(r);switch(u){case"xyz":t[0]=o*c*M+i*h*s,t[1]=i*h*M-o*c*s,t[2]=i*c*s+o*h*M,t[3]=i*c*M-o*h*s;break;case"xzy":t[0]=o*c*M-i*h*s,t[1]=i*h*M-o*c*s,t[2]=i*c*s+o*h*M,t[3]=i*c*M+o*h*s;break;case"yxz":t[0]=o*c*M+i*h*s,t[1]=i*h*M-o*c*s,t[2]=i*c*s-o*h*M,t[3]=i*c*M+o*h*s;break;case"yzx":t[0]=o*c*M+i*h*s,t[1]=i*h*M+o*c*s,t[2]=i*c*s-o*h*M,t[3]=i*c*M-o*h*s;break;case"zxy":t[0]=o*c*M-i*h*s,t[1]=i*h*M+o*c*s,t[2]=i*c*s+o*h*M,t[3]=i*c*M-o*h*s;break;case"zyx":t[0]=o*c*M-i*h*s,t[1]=i*h*M+o*c*s,t[2]=i*c*s-o*h*M,t[3]=i*c*M+o*h*s;break;default:throw new Error("Unknown angle order "+u)}return t},str:function(t){return"quat("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+")"},clone:Yt,fromValues:Zt,copy:Nt,set:Xt,add:Bt,mul:Ut,scale:Gt,dot:Wt,lerp:Ct,length:Ht,len:Jt,squaredLength:Kt,sqrLen:$t,normalize:tn,exactEquals:nn,equals:function(t,a){return Math.abs(xt(t,a))>=1-n},rotationTo:cn,sqlerp:sn,setAxes:Mn});function ln(t,n,a){var r=.5*a[0],u=.5*a[1],e=.5*a[2],o=n[0],i=n[1],h=n[2],c=n[3];return t[0]=o,t[1]=i,t[2]=h,t[3]=c,t[4]=r*c+u*h-e*i,t[5]=u*c+e*o-r*h,t[6]=e*c+r*i-u*o,t[7]=-r*o-u*i-e*h,t}function vn(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t}var bn=Nt;var mn=Nt;function dn(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=a[4],h=a[5],c=a[6],s=a[7],M=n[4],f=n[5],l=n[6],v=n[7],b=a[0],m=a[1],d=a[2],p=a[3];return t[0]=r*p+o*b+u*d-e*m,t[1]=u*p+o*m+e*b-r*d,t[2]=e*p+o*d+r*m-u*b,t[3]=o*p-r*b-u*m-e*d,t[4]=r*s+o*i+u*c-e*h+M*p+v*b+f*d-l*m,t[5]=u*s+o*h+e*i-r*c+f*p+v*m+l*b-M*d,t[6]=e*s+o*c+r*h-u*i+l*p+v*d+M*m-f*b,t[7]=o*s-r*i-u*h-e*c+v*p-M*b-f*m-l*d,t}var pn=dn;var xn=Wt;var yn=Ht,qn=yn,gn=Kt,_n=gn;var An=Object.freeze({__proto__:null,create:function(){var t=new a(8);return a!=Float32Array&&(t[0]=0,t[1]=0,t[2]=0,t[4]=0,t[5]=0,t[6]=0,t[7]=0),t[3]=1,t},clone:function(t){var n=new a(8);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n[4]=t[4],n[5]=t[5],n[6]=t[6],n[7]=t[7],n},fromValues:function(t,n,r,u,e,o,i,h){var c=new a(8);return c[0]=t,c[1]=n,c[2]=r,c[3]=u,c[4]=e,c[5]=o,c[6]=i,c[7]=h,c},fromRotationTranslationValues:function(t,n,r,u,e,o,i){var h=new a(8);h[0]=t,h[1]=n,h[2]=r,h[3]=u;var c=.5*e,s=.5*o,M=.5*i;return h[4]=c*u+s*r-M*n,h[5]=s*u+M*t-c*r,h[6]=M*u+c*n-s*t,h[7]=-c*t-s*n-M*r,h},fromRotationTranslation:ln,fromTranslation:function(t,n){return t[0]=0,t[1]=0,t[2]=0,t[3]=1,t[4]=.5*n[0],t[5]=.5*n[1],t[6]=.5*n[2],t[7]=0,t},fromRotation:function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=0,t[5]=0,t[6]=0,t[7]=0,t},fromMat4:function(t,n){var r=Pt();R(r,n);var u=new a(3);return w(u,n),ln(t,r,u),t},copy:vn,identity:function(t){return t[0]=0,t[1]=0,t[2]=0,t[3]=1,t[4]=0,t[5]=0,t[6]=0,t[7]=0,t},set:function(t,n,a,r,u,e,o,i,h){return t[0]=n,t[1]=a,t[2]=r,t[3]=u,t[4]=e,t[5]=o,t[6]=i,t[7]=h,t},getReal:bn,getDual:function(t,n){return t[0]=n[4],t[1]=n[5],t[2]=n[6],t[3]=n[7],t},setReal:mn,setDual:function(t,n){return t[4]=n[0],t[5]=n[1],t[6]=n[2],t[7]=n[3],t},getTranslation:function(t,n){var a=n[4],r=n[5],u=n[6],e=n[7],o=-n[0],i=-n[1],h=-n[2],c=n[3];return t[0]=2*(a*c+e*o+r*h-u*i),t[1]=2*(r*c+e*i+u*o-a*h),t[2]=2*(u*c+e*h+a*i-r*o),t},translate:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=.5*a[0],h=.5*a[1],c=.5*a[2],s=n[4],M=n[5],f=n[6],l=n[7];return t[0]=r,t[1]=u,t[2]=e,t[3]=o,t[4]=o*i+u*c-e*h+s,t[5]=o*h+e*i-r*c+M,t[6]=o*c+r*h-u*i+f,t[7]=-r*i-u*h-e*c+l,t},rotateX:function(t,n,a){var r=-n[0],u=-n[1],e=-n[2],o=n[3],i=n[4],h=n[5],c=n[6],s=n[7],M=i*o+s*r+h*e-c*u,f=h*o+s*u+c*r-i*e,l=c*o+s*e+i*u-h*r,v=s*o-i*r-h*u-c*e;return Dt(t,n,a),r=t[0],u=t[1],e=t[2],o=t[3],t[4]=M*o+v*r+f*e-l*u,t[5]=f*o+v*u+l*r-M*e,t[6]=l*o+v*e+M*u-f*r,t[7]=v*o-M*r-f*u-l*e,t},rotateY:function(t,n,a){var r=-n[0],u=-n[1],e=-n[2],o=n[3],i=n[4],h=n[5],c=n[6],s=n[7],M=i*o+s*r+h*e-c*u,f=h*o+s*u+c*r-i*e,l=c*o+s*e+i*u-h*r,v=s*o-i*r-h*u-c*e;return Ft(t,n,a),r=t[0],u=t[1],e=t[2],o=t[3],t[4]=M*o+v*r+f*e-l*u,t[5]=f*o+v*u+l*r-M*e,t[6]=l*o+v*e+M*u-f*r,t[7]=v*o-M*r-f*u-l*e,t},rotateZ:function(t,n,a){var r=-n[0],u=-n[1],e=-n[2],o=n[3],i=n[4],h=n[5],c=n[6],s=n[7],M=i*o+s*r+h*e-c*u,f=h*o+s*u+c*r-i*e,l=c*o+s*e+i*u-h*r,v=s*o-i*r-h*u-c*e;return It(t,n,a),r=t[0],u=t[1],e=t[2],o=t[3],t[4]=M*o+v*r+f*e-l*u,t[5]=f*o+v*u+l*r-M*e,t[6]=l*o+v*e+M*u-f*r,t[7]=v*o-M*r-f*u-l*e,t},rotateByQuatAppend:function(t,n,a){var r=a[0],u=a[1],e=a[2],o=a[3],i=n[0],h=n[1],c=n[2],s=n[3];return t[0]=i*o+s*r+h*e-c*u,t[1]=h*o+s*u+c*r-i*e,t[2]=c*o+s*e+i*u-h*r,t[3]=s*o-i*r-h*u-c*e,i=n[4],h=n[5],c=n[6],s=n[7],t[4]=i*o+s*r+h*e-c*u,t[5]=h*o+s*u+c*r-i*e,t[6]=c*o+s*e+i*u-h*r,t[7]=s*o-i*r-h*u-c*e,t},rotateByQuatPrepend:function(t,n,a){var r=n[0],u=n[1],e=n[2],o=n[3],i=a[0],h=a[1],c=a[2],s=a[3];return t[0]=r*s+o*i+u*c-e*h,t[1]=u*s+o*h+e*i-r*c,t[2]=e*s+o*c+r*h-u*i,t[3]=o*s-r*i-u*h-e*c,i=a[4],h=a[5],c=a[6],s=a[7],t[4]=r*s+o*i+u*c-e*h,t[5]=u*s+o*h+e*i-r*c,t[6]=e*s+o*c+r*h-u*i,t[7]=o*s-r*i-u*h-e*c,t},rotateAroundAxis:function(t,a,r,u){if(Math.abs(u)0){a=Math.sqrt(a);var r=n[0]/a,u=n[1]/a,e=n[2]/a,o=n[3]/a,i=n[4],h=n[5],c=n[6],s=n[7],M=r*i+u*h+e*c+o*s;t[0]=r,t[1]=u,t[2]=e,t[3]=o,t[4]=(i-r*M)/a,t[5]=(h-u*M)/a,t[6]=(c-e*M)/a,t[7]=(s-o*M)/a}return t},str:function(t){return"quat2("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+", "+t[4]+", "+t[5]+", "+t[6]+", "+t[7]+")"},exactEquals:function(t,n){return t[0]===n[0]&&t[1]===n[1]&&t[2]===n[2]&&t[3]===n[3]&&t[4]===n[4]&&t[5]===n[5]&&t[6]===n[6]&&t[7]===n[7]},equals:function(t,a){var r=t[0],u=t[1],e=t[2],o=t[3],i=t[4],h=t[5],c=t[6],s=t[7],M=a[0],f=a[1],l=a[2],v=a[3],b=a[4],m=a[5],d=a[6],p=a[7];return Math.abs(r-M)<=n*Math.max(1,Math.abs(r),Math.abs(M))&&Math.abs(u-f)<=n*Math.max(1,Math.abs(u),Math.abs(f))&&Math.abs(e-l)<=n*Math.max(1,Math.abs(e),Math.abs(l))&&Math.abs(o-v)<=n*Math.max(1,Math.abs(o),Math.abs(v))&&Math.abs(i-b)<=n*Math.max(1,Math.abs(i),Math.abs(b))&&Math.abs(h-m)<=n*Math.max(1,Math.abs(h),Math.abs(m))&&Math.abs(c-d)<=n*Math.max(1,Math.abs(c),Math.abs(d))&&Math.abs(s-p)<=n*Math.max(1,Math.abs(s),Math.abs(p))}});function wn(){var t=new a(2);return a!=Float32Array&&(t[0]=0,t[1]=0),t}function zn(t,n,a){return t[0]=n[0]-a[0],t[1]=n[1]-a[1],t}function Rn(t,n,a){return t[0]=n[0]*a[0],t[1]=n[1]*a[1],t}function On(t,n,a){return t[0]=n[0]/a[0],t[1]=n[1]/a[1],t}function jn(t,n){var a=n[0]-t[0],r=n[1]-t[1];return Math.hypot(a,r)}function En(t,n){var a=n[0]-t[0],r=n[1]-t[1];return a*a+r*r}function Pn(t){var n=t[0],a=t[1];return Math.hypot(n,a)}function Tn(t){var n=t[0],a=t[1];return n*n+a*a}var Sn=Pn,Dn=zn,Fn=Rn,In=On,Ln=jn,Vn=En,kn=Tn,Qn=function(){var t=wn();return function(n,a,r,u,e,o){var i,h;for(a||(a=2),r||(r=0),h=u?Math.min(u*a+r,n.length):n.length,i=r;i0&&(u=1/Math.sqrt(u)),t[0]=n[0]*u,t[1]=n[1]*u,t},dot:function(t,n){return t[0]*n[0]+t[1]*n[1]},cross:function(t,n,a){var r=n[0]*a[1]-n[1]*a[0];return t[0]=t[1]=0,t[2]=r,t},lerp:function(t,n,a,r){var u=n[0],e=n[1];return t[0]=u+r*(a[0]-u),t[1]=e+r*(a[1]-e),t},random:function(t,n){n=n||1;var a=2*r()*Math.PI;return t[0]=Math.cos(a)*n,t[1]=Math.sin(a)*n,t},transformMat2:function(t,n,a){var r=n[0],u=n[1];return t[0]=a[0]*r+a[2]*u,t[1]=a[1]*r+a[3]*u,t},transformMat2d:function(t,n,a){var r=n[0],u=n[1];return t[0]=a[0]*r+a[2]*u+a[4],t[1]=a[1]*r+a[3]*u+a[5],t},transformMat3:function(t,n,a){var r=n[0],u=n[1];return t[0]=a[0]*r+a[3]*u+a[6],t[1]=a[1]*r+a[4]*u+a[7],t},transformMat4:function(t,n,a){var r=n[0],u=n[1];return t[0]=a[0]*r+a[4]*u+a[12],t[1]=a[1]*r+a[5]*u+a[13],t},rotate:function(t,n,a,r){var u=n[0]-a[0],e=n[1]-a[1],o=Math.sin(r),i=Math.cos(r);return t[0]=u*i-e*o+a[0],t[1]=u*o+e*i+a[1],t},angle:function(t,n){var a=t[0],r=t[1],u=n[0],e=n[1],o=Math.sqrt((a*a+r*r)*(u*u+e*e)),i=o&&(a*u+r*e)/o;return Math.acos(Math.min(Math.max(i,-1),1))},zero:function(t){return t[0]=0,t[1]=0,t},str:function(t){return"vec2("+t[0]+", "+t[1]+")"},exactEquals:function(t,n){return t[0]===n[0]&&t[1]===n[1]},equals:function(t,a){var r=t[0],u=t[1],e=a[0],o=a[1];return Math.abs(r-e)<=n*Math.max(1,Math.abs(r),Math.abs(e))&&Math.abs(u-o)<=n*Math.max(1,Math.abs(u),Math.abs(o))},len:Sn,sub:Dn,mul:Fn,div:In,dist:Ln,sqrDist:Vn,sqrLen:kn,forEach:Qn});t.glMatrix=e,t.mat2=s,t.mat2d=b,t.mat3=q,t.mat4=F,t.quat=fn,t.quat2=An,t.vec2=Yn,t.vec3=rt,t.vec4=Et,Object.defineProperty(t,"__esModule",{value:!0})}));