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 = '%s
' % 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 + + + + +
+ MiniMates: loading... +
+ + + + + + + + + + + +
+ + + + + + + \ 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})}));