├── .DS_Store ├── .gitignore ├── .idea ├── RainModel.iml ├── misc.xml ├── modules.xml ├── vcs.xml └── workspace.xml ├── collect_filename.py ├── data ├── .DS_Store ├── ._.DS_Store ├── disp_left.pfm ├── disp_right.pfm ├── left0.png └── right0.png ├── demo.py ├── drive_dataset.py ├── haze_iteration.py ├── lib ├── __init__.py ├── flowlib.py ├── haze.py └── pfm.py ├── out ├── .DS_Store └── ._.DS_Store ├── pfm_to_flo.py └── profiler.py /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liruoteng/RainModel/cd7bfe7b0121a377163d8ab215e0356a5734c6bc/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *.txt 3 | *.pfm 4 | *.flo 5 | out/* 6 | .idea/* 7 | -------------------------------------------------------------------------------- /.idea/RainModel.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 11 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 17 | 18 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 163 | 164 | 165 | 167 | 168 | 185 | 186 | 187 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | Python 201 | 202 | 203 | 204 | 205 | PyInterpreterInspection 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 245 | 246 | 247 | 248 | 251 | 252 | 255 | 256 | 257 | 258 | 261 | 262 | 265 | 266 | 269 | 270 | 271 | 272 | 275 | 276 | 279 | 280 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 319 | 320 | 336 | 337 | 353 | 354 | 370 | 371 | 387 | 388 | 404 | 405 | 416 | 417 | 435 | 436 | 454 | 455 | 475 | 476 | 497 | 498 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | 539 | 541 | 542 | 543 | 544 | 1474632346089 545 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 578 | 581 | 582 | 583 | 585 | 586 | 587 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 682 | 683 | 684 | 685 | 686 | 687 | 688 | 689 | 690 | 691 | 692 | 693 | 694 | 695 | 696 | 697 | 698 | 699 | 700 | 701 | 702 | 703 | 704 | 705 | 706 | 707 | 708 | 709 | 710 | 711 | 712 | 713 | 714 | 715 | 716 | 717 | 718 | 719 | 720 | 721 | 722 | 723 | 724 | 725 | 726 | 727 | 728 | 729 | 730 | 731 | 732 | 733 | 734 | 735 | 736 | 737 | 738 | 739 | 740 | 741 | 742 | 743 | 744 | 745 | 746 | 747 | 748 | 749 | 750 | 751 | 752 | 753 | 754 | 755 | 756 | 757 | 758 | 759 | 760 | 761 | 762 | 763 | 764 | 765 | 766 | 767 | 768 | 769 | 770 | 771 | 772 | 773 | 774 | 775 | 776 | 777 | 778 | 779 | 780 | 781 | 782 | 783 | 784 | 785 | 786 | 787 | 788 | 789 | 790 | 791 | 792 | 793 | 794 | 795 | 796 | 797 | 798 | 799 | 800 | 801 | 802 | 803 | 804 | 805 | 806 | 807 | 808 | 809 | 810 | 811 | 812 | 813 | 814 | 815 | 816 | 817 | 818 | 819 | 820 | 821 | 822 | 823 | 824 | 825 | 826 | 827 | 828 | 829 | 830 | 831 | 832 | 833 | 834 | 835 | 836 | 837 | 838 | 839 | 840 | 841 | 842 | 843 | 844 | 845 | 846 | 847 | 848 | 849 | 850 | 851 | 852 | 853 | 854 | 855 | 856 | 857 | 858 | 859 | 860 | 861 | 862 | 863 | 864 | 865 | 866 | 867 | 868 | 869 | 870 | 871 | 872 | 873 | 874 | 875 | 876 | 877 | 878 | 879 | 880 | 881 | 882 | 883 | 884 | 885 | 886 | 887 | 888 | 889 | 890 | 891 | 892 | 893 | 894 | 895 | 896 | 897 | 898 | 899 | 900 | 901 | 902 | 903 | 904 | 905 | 906 | 907 | 908 | 909 | 910 | 911 | 912 | 913 | 914 | 915 | 916 | 917 | 918 | 919 | 920 | 921 | 922 | 923 | 924 | 925 | 926 | 927 | 928 | 929 | 930 | 931 | 932 | 933 | 934 | 935 | 936 | 937 | 938 | 939 | 940 | 941 | 942 | 943 | 944 | 945 | 946 | 947 | 948 | 949 | 950 | 951 | 952 | 953 | 954 | 955 | 956 | 957 | 958 | 959 | 960 | 961 | 962 | 963 | 964 | 965 | 966 | 967 | 968 | 969 | 970 | 971 | 972 | 973 | 974 | 975 | 976 | 977 | 978 | 979 | 980 | 981 | 982 | 983 | 984 | 985 | 986 | 987 | 988 | 989 | 990 | 991 | 992 | 993 | 994 | 995 | 996 | 997 | 998 | 999 | 1000 | 1001 | 1002 | 1003 | 1004 | 1005 | 1006 | 1007 | 1008 | 1009 | 1010 | 1011 | 1012 | 1013 | 1014 | 1015 | 1016 | 1017 | 1018 | 1019 | 1020 | 1021 | 1022 | 1023 | 1024 | 1025 | 1026 | 1027 | 1028 | 1029 | 1030 | 1031 | 1032 | 1033 | 1034 | 1035 | 1036 | 1037 | 1038 | 1039 | 1040 | 1041 | 1042 | 1043 | 1044 | 1045 | 1046 | 1047 | 1048 | 1049 | 1050 | 1051 | 1052 | 1053 | 1054 | 1055 | 1056 | 1057 | 1058 | 1059 | 1060 | 1061 | 1062 | 1063 | 1064 | 1065 | 1066 | 1067 | 1068 | 1069 | 1070 | 1071 | 1072 | 1073 | 1074 | 1075 | 1076 | 1077 | 1078 | 1079 | 1080 | 1081 | 1082 | 1083 | 1084 | 1085 | 1086 | 1087 | 1088 | 1089 | 1090 | 1091 | 1092 | 1093 | 1094 | 1095 | 1096 | 1097 | 1098 | 1099 | 1100 | 1101 | 1102 | 1103 | 1104 | 1105 | 1106 | 1107 | 1108 | 1109 | 1110 | 1111 | 1112 | 1113 | 1114 | 1115 | 1116 | 1117 | 1118 | 1119 | 1120 | 1121 | 1122 | 1123 | 1124 | 1125 | 1126 | 1127 | 1128 | 1129 | 1130 | 1131 | 1132 | 1133 | 1134 | 1135 | 1136 | 1137 | 1138 | 1139 | 1140 | 1141 | 1142 | 1143 | 1144 | 1145 | 1146 | 1147 | 1148 | 1149 | 1150 | 1151 | 1152 | 1153 | 1154 | 1155 | 1156 | 1157 | 1158 | 1159 | 1160 | 1161 | 1162 | 1163 | 1164 | 1165 | 1166 | 1167 | 1168 | 1169 | 1170 | 1171 | 1172 | 1173 | 1174 | 1175 | 1176 | 1177 | 1178 | 1179 | 1180 | 1181 | 1182 | 1183 | 1184 | 1185 | 1186 | 1187 | 1188 | 1189 | 1190 | 1191 | 1192 | 1193 | 1194 | 1195 | 1196 | 1197 | 1198 | 1199 | 1200 | 1201 | 1202 | 1203 | 1204 | 1205 | 1206 | 1207 | 1208 | 1209 | 1210 | 1211 | 1212 | 1213 | 1214 | 1215 | 1216 | 1217 | 1218 | 1219 | 1220 | 1221 | 1222 | 1223 | 1224 | 1225 | 1226 | 1227 | 1228 | 1229 | 1230 | 1231 | 1232 | 1233 | 1234 | 1235 | 1236 | 1237 | 1238 | 1239 | 1240 | 1241 | 1242 | 1243 | 1244 | 1245 | 1246 | 1247 | 1248 | 1249 | 1250 | 1251 | 1252 | 1253 | 1254 | 1255 | 1256 | 1257 | 1258 | 1259 | 1260 | 1261 | 1262 | 1263 | 1264 | 1265 | 1266 | 1267 | 1268 | 1269 | 1270 | 1271 | 1272 | 1273 | 1274 | 1275 | 1276 | 1277 | 1278 | 1279 | 1280 | 1281 | 1282 | 1283 | 1284 | 1285 | 1286 | 1287 | 1288 | 1289 | 1290 | 1291 | 1292 | 1293 | 1294 | 1295 | 1296 | 1297 | 1298 | 1299 | 1300 | 1301 | 1302 | 1303 | 1304 | 1305 | 1306 | 1307 | 1308 | 1309 | 1310 | 1311 | 1312 | 1313 | 1314 | 1315 | 1316 | 1317 | 1318 | 1319 | 1320 | 1321 | 1322 | 1323 | 1324 | 1325 | 1326 | 1327 | 1328 | 1329 | 1330 | 1331 | 1332 | 1333 | 1334 | 1335 | 1336 | 1337 | 1338 | 1339 | 1340 | 1341 | 1342 | 1343 | 1344 | 1345 | 1346 | 1347 | 1348 | 1349 | 1350 | 1351 | 1352 | 1353 | 1354 | 1355 | 1356 | 1357 | 1358 | 1359 | 1360 | 1361 | 1362 | 1363 | 1364 | 1365 | 1366 | 1367 | 1368 | 1369 | 1370 | 1371 | 1372 | 1373 | 1374 | 1375 | 1376 | 1377 | 1378 | 1379 | 1380 | 1381 | 1382 | 1383 | -------------------------------------------------------------------------------- /collect_filename.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/python 2 | """ 3 | Collect drive data set files 4 | """ 5 | import os 6 | 7 | 8 | f = open('left_rain.txt', 'wb') 9 | g = open('right_rain.txt', 'wb') 10 | left = [] 11 | right = [] 12 | 13 | for root, dirs, files in os.walk('../../../data/drive/drive_cleanpass_aug'): 14 | for dirname in dirs: 15 | if dirname == 'left': 16 | files = os.listdir(root + '/left') 17 | for filename in files: 18 | if filename.find('_s.png') != -1: 19 | left.append(os.path.join(root + '/left', filename)) 20 | elif dirname == 'right': 21 | files = os.listdir(root + '/right') 22 | for filename in files: 23 | if filename.find('_s.png') != -1: 24 | right.append(os.path.join(root + '/right', filename)) 25 | 26 | left.sort() 27 | right.sort() 28 | 29 | for line in left: 30 | f.write(line + '\n') 31 | for line in right: 32 | g.write(line + '\n') 33 | 34 | f.close() 35 | g.close() 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /data/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liruoteng/RainModel/cd7bfe7b0121a377163d8ab215e0356a5734c6bc/data/.DS_Store -------------------------------------------------------------------------------- /data/._.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liruoteng/RainModel/cd7bfe7b0121a377163d8ab215e0356a5734c6bc/data/._.DS_Store -------------------------------------------------------------------------------- /data/disp_left.pfm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liruoteng/RainModel/cd7bfe7b0121a377163d8ab215e0356a5734c6bc/data/disp_left.pfm -------------------------------------------------------------------------------- /data/disp_right.pfm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liruoteng/RainModel/cd7bfe7b0121a377163d8ab215e0356a5734c6bc/data/disp_right.pfm -------------------------------------------------------------------------------- /data/left0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liruoteng/RainModel/cd7bfe7b0121a377163d8ab215e0356a5734c6bc/data/left0.png -------------------------------------------------------------------------------- /data/right0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liruoteng/RainModel/cd7bfe7b0121a377163d8ab215e0356a5734c6bc/data/right0.png -------------------------------------------------------------------------------- /demo.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/python 2 | from lib import haze 3 | """ 4 | Run haze/rain rendering on the background image with default settings. 5 | Author : Ruoteng Li 6 | Date : 5 Oct 2016 7 | """ 8 | 9 | # Initialize haze model object 10 | haze_object = haze.Haze() 11 | # Parameter set up as followed 12 | # haze_object.set_beta(65) 13 | # haze_object.set_noise_param(0, 10) 14 | # Generate haze rendered output 15 | haze_object.synthesize_haze() 16 | # Generate rain rendered output 17 | haze_object.synthesize_rain() 18 | # Generate rain and haze both rendered output 19 | haze_object.synthesize_all() 20 | -------------------------------------------------------------------------------- /drive_dataset.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/python 2 | from lib import haze 3 | import numpy 4 | """ 5 | This script renders haze and rain to the driving dataset for optical flow training 6 | Author : Ruoteng LI 7 | Date: 5 Oct 2016 8 | """ 9 | 10 | h = haze.Haze() 11 | intensity = 220 12 | 13 | contrast = 130 14 | h.set_haze_intensity(contrast) 15 | h.set_rain_intensity(intensity) 16 | left_imagefile = open('data/left.txt', 'r') 17 | right_imagefile = open('data/right.txt', 'r') 18 | left_dispfile = open('data/left_disp.txt', 'r') 19 | right_dispfile = open('data/right_disp.txt', 'r') 20 | left_rainfiles = open('data/left_rain.txt', 'r') 21 | right_rainfiles = open('data/right_rain.txt', 'r') 22 | left_images = left_imagefile.readlines() 23 | right_images = right_imagefile.readlines() 24 | left_disp = left_dispfile.readlines() 25 | right_disp = right_dispfile.readlines() 26 | left_rain = left_rainfiles.readlines() 27 | right_rain = right_rainfiles.readlines() 28 | image_num = len(left_images) 29 | 30 | for i in range(0, image_num, 2): 31 | beta = numpy.random.randint(0,40, size=1) 32 | for j in range(2): 33 | print "No. : ", i+j, "beta: ", beta 34 | h.set_beta(beta) 35 | left_bg_file = left_images[i+j] 36 | right_bg_file = right_images[i+j] 37 | h.set_background(left_bg_file.strip(), right_bg_file.strip()) 38 | left_disp_file = left_disp[i+j] 39 | right_disp_file = right_disp[i+j] 40 | h.set_disparity_map(left_disp_file.strip(), right_disp_file.strip()) 41 | left_rain_file = left_rain[i+j] 42 | right_rain_file = right_rain[i+j] 43 | h.set_rain_file(left_rain_file.strip(), right_rain_file.strip()) 44 | left_out_file = left_bg_file[0: left_bg_file.find('.png')] + '_rain_haze4.png' 45 | right_out_file = right_bg_file[0:right_bg_file.find('.png')] + '_rain_haze4.png' 46 | h.set_all_output(left_out_file, right_out_file) 47 | h.synthesize_all() 48 | print left_bg_file, ':', right_bg_file 49 | print left_out_file, ':', right_out_file 50 | 51 | 52 | -------------------------------------------------------------------------------- /haze_iteration.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/python 2 | from lib import haze 3 | """ 4 | haze_iteration.py 5 | This script use iteration to systematically render haze and rain on the background images with different parameters 6 | Author: Ruoteng Li 7 | Date: 5 Oct 2016 8 | """ 9 | 10 | 11 | h = haze.Haze() 12 | intensity = 220 13 | h.set_rain_intensity(intensity) 14 | 15 | for beta in range(0, 200, 5): 16 | h.set_beta(beta) 17 | for contrast in range(120, 201, 5): 18 | print "beta: ", beta 19 | print "haze intensity: ", contrast 20 | 21 | h.set_haze_intensity(contrast) 22 | 23 | left_file = 'out/render_haze_left_' + 'beta' + str(beta) + 'contrast' + str(contrast) + '.png' 24 | right_file = 'out/render_haze_right_' + 'beta' + str(beta) + 'contrast' + str(contrast) + '.png' 25 | # h.set_haze_output(left_file, right_file) 26 | # h.synthesize_haze() 27 | h.set_all_output(left_file, right_file) 28 | h.synthesize_all() 29 | -------------------------------------------------------------------------------- /lib/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liruoteng/RainModel/cd7bfe7b0121a377163d8ab215e0356a5734c6bc/lib/__init__.py -------------------------------------------------------------------------------- /lib/flowlib.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | import numpy as np 3 | import matplotlib.pyplot as plt 4 | import png 5 | import pfm 6 | UNKNOWN_FLOW_THRESH = 1e7 7 | 8 | 9 | # Calculate flow end point error 10 | def evaluate_flow(gt, pred): 11 | # Read flow files and calculate the errors 12 | gt_flow = read_flow(gt) # ground truth flow 13 | eva_flow = read_flow(pred) # predicted flow 14 | # Calculate errors 15 | average_pe = flowAngErr(gt_flow[:, :, 0], gt_flow[:, :, 1], eva_flow[:, :, 0], eva_flow[:, :, 1]) 16 | return average_pe 17 | 18 | 19 | # show flow file visualization 20 | def show_flow(filename): 21 | flow = read_flow(filename) 22 | img = flow_to_image(flow) 23 | plt.imshow(img) 24 | plt.show() 25 | 26 | 27 | # WARNING: this will work on little-endian architectures (eg Intel x86) only! 28 | def read_flow(filename): 29 | f = open(filename, 'rb') 30 | magic = np.fromfile(f, np.float32, count=1) 31 | data2d = None 32 | 33 | if 202021.25 != magic: 34 | print 'Magic number incorrect. Invalid .flo file' 35 | else: 36 | w = np.fromfile(f, np.int32, count=1) 37 | h = np.fromfile(f, np.int32, count=1) 38 | print "Reading %d x %d flo file" % (h, w) 39 | data2d = np.fromfile(f, np.float32, count=2 * w * h) 40 | # reshape data into 3D array (columns, rows, channels) 41 | data2d = np.resize(data2d, (h, w, 2)) 42 | f.close() 43 | return data2d 44 | 45 | 46 | # Calculate average end point error 47 | def flowAngErr(tu, tv, u, v): 48 | smallflow = 0.0 49 | ''' 50 | stu = tu[bord+1:end-bord,bord+1:end-bord] 51 | stv = tv[bord+1:end-bord,bord+1:end-bord] 52 | su = u[bord+1:end-bord,bord+1:end-bord] 53 | sv = v[bord+1:end-bord,bord+1:end-bord] 54 | ''' 55 | stu = tu[:] 56 | stv = tv[:] 57 | su = u[:] 58 | sv = v[:] 59 | 60 | idxUnknow = (abs(stu) > UNKNOWN_FLOW_THRESH) | (abs(stv) > UNKNOWN_FLOW_THRESH) 61 | stu[idxUnknow] = 0 62 | stv[idxUnknow] = 0 63 | su[idxUnknow] = 0 64 | sv[idxUnknow] = 0 65 | 66 | ind2 = [(np.absolute(stu) > smallflow) | (np.absolute(stv) > smallflow)] 67 | index_su = su[ind2] 68 | index_sv = sv[ind2] 69 | an = 1.0 / np.sqrt(index_su ** 2 + index_sv ** 2 + 1) 70 | un = index_su * an 71 | vn = index_sv * an 72 | 73 | index_stu = stu[ind2] 74 | index_stv = stv[ind2] 75 | tn = 1.0 / np.sqrt(index_stu ** 2 + index_stv ** 2 + 1) 76 | tun = index_stu * tn 77 | tvn = index_stv * tn 78 | 79 | ''' 80 | angle = un * tun + vn * tvn + (an * tn) 81 | index = [angle == 1.0] 82 | angle[index] = 0.999 83 | ang = np.arccos(angle) 84 | mang = np.mean(ang) 85 | mang = mang * 180 / np.pi 86 | ''' 87 | 88 | epe = np.sqrt((stu - su) ** 2 + (stv - sv) ** 2) 89 | epe = epe[ind2] 90 | mepe = np.mean(epe) 91 | return mepe 92 | 93 | 94 | # Convert flow into middlebury color code image 95 | def flow_to_image(flow): 96 | """ 97 | :param flow: 98 | :return: 99 | """ 100 | u = flow[:, :, 0] 101 | v = flow[:, :, 1] 102 | 103 | maxu = -999. 104 | maxv = -999. 105 | minu = 999. 106 | minv = 999. 107 | 108 | idxUnknow = (abs(u) > UNKNOWN_FLOW_THRESH) | (abs(v) > UNKNOWN_FLOW_THRESH) 109 | u[idxUnknow] = 0 110 | v[idxUnknow] = 0 111 | 112 | maxu = max(maxu, np.max(u)) 113 | minu = min(minu, np.min(u)) 114 | 115 | maxv = max(maxv, np.max(v)) 116 | minv = min(minv, np.min(v)) 117 | 118 | rad = np.sqrt(u ** 2 + v ** 2) 119 | maxrad = max(-1, np.max(rad)) 120 | 121 | print "max flow: %.4f\nflow range:\nu = %.3f .. %.3f\nv = %.3f .. %.3f" % (maxrad, minu,maxu, minv, maxv) 122 | 123 | u = u/(maxrad + np.finfo(float).eps) 124 | v = v/(maxrad + np.finfo(float).eps) 125 | 126 | img = compute_color(u, v) 127 | 128 | idx = np.repeat(idxUnknow[:, :, np.newaxis], 3, axis=2) 129 | img[idx] = 0 130 | 131 | return np.uint8(img) 132 | 133 | 134 | def compute_color(u,v): 135 | [h, w] = u.shape 136 | img = np.zeros([h, w, 3]) 137 | nanIdx = np.isnan(u) | np.isnan(v) 138 | u[nanIdx] = 0 139 | v[nanIdx] = 0 140 | 141 | colorwheel = make_color_wheel() 142 | ncols = np.size(colorwheel, 0) 143 | 144 | rad = np.sqrt(u**2+v**2) 145 | 146 | a = np.arctan2(-v, -u) / np.pi 147 | 148 | fk = (a+1) / 2 * (ncols - 1) + 1 149 | 150 | k0 = np.floor(fk).astype(int) 151 | 152 | k1 = k0 + 1 153 | k1[k1 == ncols+1] = 1 154 | f = fk - k0 155 | 156 | for i in range(0, np.size(colorwheel,1)): 157 | tmp = colorwheel[:, i] 158 | col0 = tmp[k0-1] / 255 159 | col1 = tmp[k1-1] / 255 160 | col = (1-f) * col0 + f * col1 161 | 162 | idx = rad <= 1 163 | col[idx] = 1-rad[idx]*(1-col[idx]) 164 | notidx = np.logical_not(idx) 165 | 166 | col[notidx] *= 0.75 167 | img[:, :, i] = np.uint8(np.floor(255 * col*(1-nanIdx))) 168 | 169 | return img 170 | 171 | 172 | def make_color_wheel(): 173 | RY = 15 174 | YG = 6 175 | GC = 4 176 | CB = 11 177 | BM = 13 178 | MR = 6 179 | 180 | ncols = RY + YG + GC + CB + BM + MR 181 | 182 | colorwheel = np.zeros([ncols, 3]) 183 | 184 | col = 0 185 | 186 | # RY 187 | colorwheel[0:RY, 0] = 255 188 | colorwheel[0:RY, 1] = np.transpose(np.floor(255*np.arange(0, RY) / RY)) 189 | col += RY 190 | 191 | # YG 192 | colorwheel[col:col+YG, 0] = 255 - np.transpose(np.floor(255*np.arange(0, YG) / YG)) 193 | colorwheel[col:col+YG, 1] = 255 194 | col += YG 195 | 196 | # GC 197 | colorwheel[col:col+GC, 1] = 255 198 | colorwheel[col:col+GC, 2] = np.transpose(np.floor(255*np.arange(0, GC) / GC)) 199 | col += GC 200 | 201 | # CB 202 | colorwheel[col:col+CB, 1] = 255 - np.transpose(np.floor(255*np.arange(0, CB) / CB)) 203 | colorwheel[col:col+CB, 2] = 255 204 | col += CB 205 | 206 | # BM 207 | colorwheel[col:col+BM, 2] = 255 208 | colorwheel[col:col+BM, 0] = np.transpose(np.floor(255*np.arange(0, BM) / BM)) 209 | col += + BM 210 | 211 | # MR 212 | colorwheel[col:col+MR, 2] = 255 - np.transpose(np.floor(255 * np.arange(0, MR) / MR)) 213 | colorwheel[col:col+MR, 0] = 255 214 | 215 | return colorwheel 216 | 217 | 218 | def disp_to_flow(disp, filename): 219 | f = open(filename, 'wb') 220 | magic = np.array([202021.25], dtype=np.float32) 221 | (height, width) = disp.shape[0:2] 222 | w = np.array([width], dtype=np.int32) 223 | h = np.array([height], dtype=np.int32) 224 | empty_map = np.zeros((height, width), dtype=np.float32) 225 | data = np.dstack((disp, empty_map)) 226 | magic.tofile(f) 227 | w.tofile(f) 228 | h.tofile(f) 229 | data.tofile(f) 230 | f.close() 231 | 232 | 233 | def write_flow(flow, filename): 234 | f = open(filename, 'wb') 235 | magic = np.array([202021.25], dtype=np.float32) 236 | (height, width) = flow.shape[0:2] 237 | w = np.array([width], dtype=np.int32) 238 | h = np.array([height], dtype=np.int32) 239 | magic.tofile(f) 240 | w.tofile(f) 241 | h.tofile(f) 242 | flow.tofile(f) 243 | f.close() 244 | 245 | 246 | def scale_image(image, new_range): 247 | min_val = np.min(image).astype(np.float32) 248 | max_val = np.max(image).astype(np.float32) 249 | min_val_new = np.array(min(new_range), dtype=np.float32) 250 | max_val_new = np.array(max(new_range), dtype=np.float32) 251 | scaled_image = (image - min_val) / (max_val - min_val) * (max_val_new - min_val_new) + min_val_new 252 | return scaled_image.astype(np.uint8) 253 | 254 | 255 | def read_png(flow_file): 256 | """ 257 | Read kitti flow from .png file 258 | :param flow_file: 259 | :return: 260 | """ 261 | image_object = png.Reader(filename=flow_file) 262 | image_direct = image_object.asDirect() 263 | image_data = list(image_direct[2]) 264 | (w, h) = image_direct[3]['size'] 265 | channel = len(image_data[0]) / w 266 | flow = np.zeros((h, w, channel), dtype=np.uint16) 267 | for i in range(len(image_data)): 268 | for j in range(channel): 269 | flow[i, :, j] = image_data[i][j::channel] 270 | return flow[:, :, 0] / 256 271 | 272 | 273 | def read_pfm(flow_file): 274 | import pfm 275 | (data, scale) = pfm.readPFM(flow_file) 276 | return data 277 | 278 | 279 | def pfm_to_flo(pfm_file): 280 | flow_filename = pfm_file[0:pfm_file.find('.pfm')] + '.flo' 281 | (data, scale) = pfm.readPFM(pfm_file) 282 | flow = data[:, :, 0:2] 283 | write_flow(flow, flow_filename) 284 | 285 | -------------------------------------------------------------------------------- /lib/haze.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from PIL import Image 3 | 4 | import matplotlib.pyplot as plt 5 | import png 6 | 7 | 8 | class Haze(object): 9 | 10 | def __init__(self): 11 | self.focal_length = 1 12 | self.baseline = 1 13 | self.beta = 2 14 | self.height = 0 15 | self.width = 0 16 | self.haze_intensity = 200 17 | self.noise_variance = 1 18 | self.noise_mean = 0 19 | self.infinite_far = 1 20 | self.left_file = 'data/left0.png' 21 | self.right_file = 'data/right0.png' 22 | self.rain_left_file = 'data/rain_left.png' 23 | self.rain_right_file = 'data/rain_right.png' 24 | self.left = None 25 | self.right = None 26 | self.disp_left = None 27 | self.disp_right = None 28 | self.disp_left_file = 'data/disp_left.pfm' 29 | self.disp_right_file = 'data/disp_right.pfm' 30 | self.alpha_left = None 31 | self.alpha_right = None 32 | self.rain_left = None 33 | self.rain_right = None 34 | self.rain_intensity = 255 35 | self.haze_map = None 36 | self.noisy_haze_map = None 37 | self.rendered_haze_left = None 38 | self.rendered_haze_right = None 39 | self.rendered_rain_left = None 40 | self.rendered_rain_right = None 41 | self.haze_rain_left_map = None 42 | self.haze_rain_right_map = None 43 | self.haze_outfile_left = 'out/render_haze_left.png' 44 | self.haze_outfile_right = 'out/render_haze_right.png' 45 | self.rain_outfile_left = 'out/render_rain_left.png' 46 | self.rain_outfile_right = 'out/render_rain_right.png' 47 | self.haze_rain_left = 'out/render_haze_rain_left.png' 48 | self.haze_rain_right = 'out/render_haze_rain_right.png' 49 | self.read_background_map() 50 | self.read_disparity_map(mode='pfm') 51 | 52 | ''' 53 | Set up functions 54 | ''' 55 | def set_alpha_param(self, focal_length, baseline): 56 | self.focal_length = focal_length 57 | self.baseline = baseline 58 | 59 | def set_haze_intensity(self, intensity): 60 | self.haze_intensity = intensity 61 | 62 | def set_rain_intensity(self, intensity): 63 | self.rain_intensity = intensity 64 | 65 | def set_noise_param(self, mean, variance): 66 | self.noise_mean = mean 67 | self.noise_variance = variance 68 | 69 | def set_beta(self, beta_value): 70 | self.beta = beta_value 71 | 72 | def set_depth_param(self, infinite_far): 73 | self.infinite_far = infinite_far 74 | 75 | def set_haze_output(self, file_left, file_right): 76 | self.haze_outfile_left = file_left 77 | self.haze_outfile_right = file_right 78 | 79 | def set_rain_output(self, file_left, file_right): 80 | self.rain_outfile_left = file_left 81 | self.rain_outfile_right = file_right 82 | 83 | def set_all_output(self, file_left, file_right): 84 | self.haze_rain_left = file_left 85 | self.haze_rain_right = file_right 86 | 87 | def set_background(self, file_left, file_right): 88 | self.left_file = file_left 89 | self.right_file = file_right 90 | self.read_background_map() 91 | 92 | def set_disparity_map(self, file_left, file_right): 93 | self.disp_left_file = file_left 94 | self.disp_right_file = file_right 95 | if file_left.find('.pfm') != -1: 96 | self.read_disparity_map(mode='pfm') 97 | else: 98 | self.read_disparity_map() 99 | 100 | def set_rain_file(self, file_left, file_right): 101 | self.rain_left_file = file_left 102 | self.rain_right_file = file_right 103 | 104 | ''' 105 | Process 106 | ''' 107 | 108 | def read_disparity_map(self, mode='pfm'): 109 | if mode == 'pfm': 110 | self.disp_left = self.read_disp_pfm(self.disp_left_file) 111 | self.disp_right = self.read_disp_pfm(self.disp_right_file) 112 | else: 113 | self.disp_left = self.read_disp_png(self.disp_left_file) 114 | self.disp_right = self.read_disp_png(self.disp_right_file) 115 | 116 | def read_background_map(self): 117 | self.left = self.read_image(self.left_file) 118 | self.right = self.read_image(self.right_file) 119 | # sanity check 120 | if self.left.shape == self.right.shape: 121 | (self.height, self.width) = self.left.shape[0:2] 122 | else: 123 | raise AssertionError 124 | 125 | def read_haze(self): 126 | haze = np.ones((self.height, self.width), dtype=np.float32) 127 | self.haze_map = haze * self.haze_intensity 128 | 129 | def add_noise(self): 130 | noise = self.noise_variance * np.random.random(self.haze_map.shape) 131 | self.noisy_haze_map = self.haze_map + noise 132 | 133 | def get_depth_map(self, disparity_map): 134 | mask = (disparity_map == 0) 135 | disparity_map[mask] = self.infinite_far 136 | depth_map = self.focal_length * self.baseline / disparity_map 137 | return depth_map 138 | 139 | def get_alpha_map(self): 140 | depth_left = self.get_depth_map(self.disp_left.astype(np.float32)) 141 | depth_right = self.get_depth_map(self.disp_right.astype(np.float32)) 142 | self.alpha_left = np.exp(-1 * self.beta * depth_left) 143 | self.alpha_right = np.exp(-1 * self.beta * depth_right) 144 | 145 | def read_rain(self): 146 | self.rain_left = np.array(Image.open(self.rain_left_file)) 147 | self.rain_right = np.array(Image.open(self.rain_right_file)) 148 | self.rain_left = self.scale_image(self.rain_left, [128, self.rain_intensity]) - 128 149 | self.rain_right = self.scale_image(self.rain_right, [128, self.rain_intensity]) - 128 150 | 151 | def synthesize_rain(self): 152 | self.read_rain() 153 | self.rendered_rain_left = self.render_rain(self.left, self.rain_left) 154 | self.rendered_rain_right = self.render_rain(self.right, self.rain_right) 155 | self.write_image(self.rendered_rain_left, self.rain_outfile_left) 156 | self.write_image(self.rendered_rain_left, self.rain_outfile_right) 157 | 158 | def synthesize_haze(self): 159 | self.read_haze() 160 | self.add_noise() 161 | self.get_alpha_map() 162 | self.rendered_haze_left = self.render_haze(self.alpha_left, self.left, self.noisy_haze_map) 163 | self.rendered_haze_right = self.render_haze(self.alpha_right, self.right, self.noisy_haze_map) 164 | self.write_image(self.rendered_haze_left, self.haze_outfile_left) 165 | self.write_image(self.rendered_haze_right, self.haze_outfile_right) 166 | 167 | def synthesize_all(self): 168 | self.read_rain() 169 | self.get_alpha_map() 170 | self.read_haze() 171 | self.add_noise() 172 | haze_left = self.render_haze(self.alpha_left, self.left, self.noisy_haze_map) 173 | haze_right = self.render_haze(self.alpha_right, self.right, self.noisy_haze_map) 174 | self.haze_rain_left_map = self.render_rain(haze_left, self.rain_left) 175 | self.haze_rain_right_map = self.render_rain(haze_right, self.rain_right) 176 | self.write_image(self.haze_rain_left_map, self.haze_rain_left) 177 | self.write_image(self.haze_rain_right_map, self.haze_rain_right) 178 | 179 | ''' 180 | Static methods 181 | ''' 182 | @staticmethod 183 | def visualize(img): 184 | plt.imshow(img) 185 | plt.show() 186 | 187 | @staticmethod 188 | def read_image(image_file): 189 | img = Image.open(image_file) 190 | img_array = np.array(img, dtype=np.uint8) 191 | return img_array 192 | 193 | @staticmethod 194 | def write_image(image_map, filename): 195 | img = Image.fromarray(image_map) 196 | img.save(filename) 197 | 198 | @staticmethod 199 | def render_haze(alpha_map, background_map, haze_map): 200 | render_map = np.zeros(background_map.shape) 201 | render_map[:, :, 0] = alpha_map * background_map[:, :, 0] + (1 - alpha_map) * haze_map 202 | render_map[:, :, 1] = alpha_map * background_map[:, :, 1] + (1 - alpha_map) * haze_map 203 | render_map[:, :, 2] = alpha_map * background_map[:, :, 2] + (1 - alpha_map) * haze_map 204 | return render_map.astype(np.uint8) 205 | 206 | @staticmethod 207 | def read_disp_png(disp_file): 208 | """ 209 | Read kitti disp from .png file 210 | :param disp_file: 211 | :return: 212 | """ 213 | image_object = png.Reader(filename=disp_file) 214 | image_direct = image_object.asDirect() 215 | image_data = list(image_direct[2]) 216 | (w, h) = image_direct[3]['size'] 217 | channel = len(image_data[0]) / w 218 | disp = np.zeros((h, w, channel), dtype=np.uint16) 219 | for i in range(len(image_data)): 220 | for j in range(channel): 221 | disp[i, :, j] = image_data[i][j::channel] 222 | return disp[:, :, 0] / 256 223 | 224 | @staticmethod 225 | def read_disp_pfm(disp_file): 226 | import pfm 227 | (data, scale) = pfm.readPFM(disp_file) 228 | return data 229 | 230 | @staticmethod 231 | def render_rain(background_map, rain_map): 232 | bg = background_map.astype(np.uint16) 233 | r = rain_map.astype(np.uint16) 234 | rendered_map = np.clip(bg + r, 0, 255).astype(np.uint8) 235 | return rendered_map 236 | 237 | @staticmethod 238 | def write_flow(image_map, filename): 239 | f = open(filename, 'wb') 240 | magic = np.array([202021.25], dtype=np.float32) 241 | (height, width) = image_map.shape 242 | w = np.array([width], dtype=np.int32) 243 | h = np.array([height], dtype=np.int32) 244 | empty_map = np.zeros((height, width), dtype=np.float32) 245 | data = np.dstack((image_map, empty_map)) 246 | magic.tofile(f) 247 | w.tofile(f) 248 | h.tofile(f) 249 | data.tofile(f) 250 | f.close() 251 | 252 | @staticmethod 253 | def scale_image(image, new_range): 254 | min_val = np.min(image).astype(np.float32) 255 | max_val = np.max(image).astype(np.float32) 256 | min_val_new = np.array(min(new_range), dtype=np.float32) 257 | max_val_new = np.array(max(new_range), dtype=np.float32) 258 | scaled_image = (image - min_val) / (max_val - min_val) * (max_val_new - min_val_new) + min_val_new 259 | return scaled_image.astype(np.uint8) 260 | 261 | 262 | -------------------------------------------------------------------------------- /lib/pfm.py: -------------------------------------------------------------------------------- 1 | import re 2 | import numpy as np 3 | import sys 4 | 5 | 6 | def readPFM(file): 7 | file = open(file, 'rb') 8 | 9 | color = None 10 | width = None 11 | height = None 12 | scale = None 13 | endian = None 14 | 15 | header = file.readline().rstrip() 16 | if header == 'PF': 17 | color = True 18 | elif header == 'Pf': 19 | color = False 20 | else: 21 | raise Exception('Not a PFM file.') 22 | 23 | dim_match = re.match(r'^(\d+)\s(\d+)\s$', file.readline()) 24 | if dim_match: 25 | width, height = map(int, dim_match.groups()) 26 | else: 27 | raise Exception('Malformed PFM header.') 28 | 29 | scale = float(file.readline().rstrip()) 30 | if scale < 0: # little-endian 31 | endian = '<' 32 | scale = -scale 33 | else: 34 | endian = '>' # big-endian 35 | 36 | data = np.fromfile(file, endian + 'f') 37 | shape = (height, width, 3) if color else (height, width) 38 | 39 | data = np.reshape(data, shape) 40 | data = np.flipud(data) 41 | return data, scale 42 | 43 | 44 | def writePFM(file, image, scale=1): 45 | file = open(file, 'wb') 46 | 47 | color = None 48 | 49 | if image.dtype.name != 'float32': 50 | raise Exception('Image dtype must be float32.') 51 | 52 | image = np.flipud(image) 53 | 54 | if len(image.shape) == 3 and image.shape[2] == 3: # color image 55 | color = True 56 | elif len(image.shape) == 2 or len(image.shape) == 3 and image.shape[2] == 1: # greyscale 57 | color = False 58 | else: 59 | raise Exception('Image must have H x W x 3, H x W x 1 or H x W dimensions.') 60 | 61 | file.write('PF\n' if color else 'Pf\n') 62 | file.write('%d %d\n' % (image.shape[1], image.shape[0])) 63 | 64 | endian = image.dtype.byteorder 65 | 66 | if endian == '<' or endian == '=' and sys.byteorder == 'little': 67 | scale = -scale 68 | 69 | file.write('%f\n' % scale) 70 | 71 | image.tofile(file) -------------------------------------------------------------------------------- /out/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liruoteng/RainModel/cd7bfe7b0121a377163d8ab215e0356a5734c6bc/out/.DS_Store -------------------------------------------------------------------------------- /out/._.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liruoteng/RainModel/cd7bfe7b0121a377163d8ab215e0356a5734c6bc/out/._.DS_Store -------------------------------------------------------------------------------- /pfm_to_flo.py: -------------------------------------------------------------------------------- 1 | from lib import flowlib as fl 2 | from lib import pfm 3 | import numpy as np 4 | """ 5 | Massively convert pfm flow file into flo type 6 | Author : Ruoteng LI 7 | Data 6 Oct 2016 8 | """ 9 | 10 | f = open('data/left_flow.txt', 'r') 11 | lines = f.readlines() 12 | i = 0 13 | 14 | for line in lines: 15 | print i 16 | fl.pfm_to_flo(line.strip()) 17 | i += 1 18 | 19 | f.close() 20 | 21 | f = open('data/right_flow.txt', 'r') 22 | lines = f.readlines() 23 | i = 0 24 | 25 | for line in lines: 26 | print i 27 | fl.pfm_to_flo(line.strip()) 28 | i += 1 29 | 30 | f.close() 31 | 32 | -------------------------------------------------------------------------------- /profiler.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import sys 3 | import matplotlib.pyplot as plt 4 | 5 | 6 | a = sys.argv 7 | 8 | f = open('result.txt') 9 | beta_range_min = 0 10 | beta_range_max = 200 11 | contrast_range_min = 120 12 | contrast_range_max = 201 13 | contrast_number = int((contrast_range_max - contrast_range_min)/5 + 1) 14 | lines = f.readlines() 15 | 16 | beta = [] 17 | contrast = [] 18 | AAE = [] 19 | EPE = [] 20 | 21 | 22 | for b in range(len(lines)): 23 | line = lines[b] 24 | words = line.split() 25 | if b % 2 == 0: 26 | beta.append(int(words[2])) 27 | contrast.append(int(words[3])) 28 | else: 29 | AAE.append(float(words[1])) 30 | EPE.append(float(words[4])) 31 | 32 | for b in range(len(lines)): 33 | line = lines[b] 34 | words = line.split() 35 | beta.append(int(words[1])) 36 | contrast.append(int(words[3])) 37 | EPE.append(float(words[5])) 38 | 39 | 40 | # Show AAE error according to beta value 41 | xt = range(0, 195, 5) 42 | plt.figure() 43 | x = [] 44 | y = [] 45 | value = [] 46 | for c in range(17): 47 | x = [] 48 | y = [] 49 | for b in range(195/5 + 1): 50 | x.append(beta[b * 17 + c]) 51 | y.append(AAE[b * 17 + c]) 52 | value.append(contrast[b * 17 + c]) 53 | plt.plot(x, y, label='haze = ' + str(value[c * (195/5+1)])) 54 | 55 | print x 56 | print y 57 | print value 58 | plt.xticks(xt) 59 | plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=-2) 60 | 61 | # Show EPE error according to beta value 62 | # Show error according to beta value 63 | xt = range(0, 195, 5) 64 | plt.figure() 65 | x = [] 66 | y = [] 67 | value = [] 68 | for c in range(17): 69 | x = [] 70 | y = [] 71 | for b in range(195/5 + 1): 72 | x.append(beta[b * 17 + c]) 73 | y.append(EPE[b * 17 + c]) 74 | value.append(contrast[b * 17 + c]) 75 | plt.plot(x, y, label='haze = ' + str(value[c * (195/5+1)])) 76 | 77 | print x 78 | print y 79 | print value 80 | plt.xticks(xt) 81 | plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=-2) 82 | 83 | # Show EPE error according to beta value 84 | # Show error according to beta value 85 | xt = range(120, 201, 5) 86 | plt.figure() 87 | x = [] 88 | y = [] 89 | value = [] 90 | for b in range(beta_range_min, beta_range_max, 5): 91 | x = [] 92 | y = [] 93 | for c in range((contrast_range_max-contrast_range_min)/5 + 1): 94 | x.append(contrast[b/5 * contrast_number + c]) 95 | y.append(EPE[b/5 * contrast_number + c]) 96 | value.append(beta[b/5 * contrast_number + c]) 97 | plt.plot(x, y, label='beta = ' + str(value[b/5 * contrast_number])) 98 | 99 | print x 100 | print y 101 | print value 102 | plt.xticks(xt) 103 | plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=-2) 104 | 105 | plt.show() --------------------------------------------------------------------------------