From c21c3b0befeb46a51b6bf3758ffa30813bea0ff0 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 9 Mar 2024 14:19:22 +0100 Subject: Adding upstream version 1.44.3. Signed-off-by: Daniel Baumann --- ml/dlib/examples/3d_point_cloud_ex.cpp | 50 + ml/dlib/examples/CMakeLists.txt | 250 +++ ml/dlib/examples/LICENSE_FOR_EXAMPLE_PROGRAMS.txt | 22 + ml/dlib/examples/assignment_learning_ex.cpp | 325 ++++ ml/dlib/examples/bayes_net_ex.cpp | 307 ++++ ml/dlib/examples/bayes_net_from_disk_ex.cpp | 83 + ml/dlib/examples/bayes_net_gui_ex.cpp | 989 +++++++++++ ml/dlib/examples/bridge_ex.cpp | 365 ++++ ml/dlib/examples/bsp_ex.cpp | 282 ++++ ml/dlib/examples/compress_stream_ex.cpp | 245 +++ ml/dlib/examples/config.txt | 30 + ml/dlib/examples/config_reader_ex.cpp | 146 ++ ml/dlib/examples/custom_trainer_ex.cpp | 277 +++ ml/dlib/examples/dir_nav_ex.cpp | 75 + ml/dlib/examples/dnn_face_recognition_ex.cpp | 220 +++ ml/dlib/examples/dnn_imagenet_ex.cpp | 171 ++ ml/dlib/examples/dnn_imagenet_train_ex.cpp | 368 ++++ ml/dlib/examples/dnn_inception_ex.cpp | 154 ++ ml/dlib/examples/dnn_introduction2_ex.cpp | 388 +++++ ml/dlib/examples/dnn_introduction_ex.cpp | 170 ++ ml/dlib/examples/dnn_metric_learning_ex.cpp | 128 ++ .../examples/dnn_metric_learning_on_images_ex.cpp | 340 ++++ ml/dlib/examples/dnn_mmod_dog_hipsterizer.cpp | 180 ++ ml/dlib/examples/dnn_mmod_ex.cpp | 230 +++ ml/dlib/examples/dnn_mmod_face_detection_ex.cpp | 114 ++ ml/dlib/examples/dnn_mmod_find_cars2_ex.cpp | 96 ++ ml/dlib/examples/dnn_mmod_find_cars_ex.cpp | 236 +++ ml/dlib/examples/dnn_mmod_train_find_cars_ex.cpp | 425 +++++ ml/dlib/examples/dnn_semantic_segmentation_ex.cpp | 172 ++ ml/dlib/examples/dnn_semantic_segmentation_ex.h | 200 +++ .../dnn_semantic_segmentation_train_ex.cpp | 390 +++++ ml/dlib/examples/empirical_kernel_map_ex.cpp | 355 ++++ ml/dlib/examples/face_detection_ex.cpp | 103 ++ ml/dlib/examples/face_landmark_detection_ex.cpp | 144 ++ ml/dlib/examples/faces/2007_007763.jpg | Bin 0 -> 89619 bytes ml/dlib/examples/faces/2008_001009.jpg | Bin 0 -> 41770 bytes ml/dlib/examples/faces/2008_001322.jpg | Bin 0 -> 65344 bytes ml/dlib/examples/faces/2008_002079.jpg | Bin 0 -> 92641 bytes ml/dlib/examples/faces/2008_002470.jpg | Bin 0 -> 91349 bytes ml/dlib/examples/faces/2008_002506.jpg | Bin 0 -> 79316 bytes ml/dlib/examples/faces/2008_004176.jpg | Bin 0 -> 93821 bytes ml/dlib/examples/faces/2008_007676.jpg | Bin 0 -> 110034 bytes ml/dlib/examples/faces/2009_004587.jpg | Bin 0 -> 79462 bytes ml/dlib/examples/faces/Tom_Cruise_avp_2014_4.jpg | Bin 0 -> 66360 bytes ml/dlib/examples/faces/bald_guys.jpg | Bin 0 -> 648373 bytes ml/dlib/examples/faces/dogs.jpg | Bin 0 -> 175216 bytes .../examples/faces/image_metadata_stylesheet.xsl | 109 ++ ml/dlib/examples/faces/testing.xml | 43 + .../examples/faces/testing_with_face_landmarks.xml | 1772 ++++++++++++++++++++ ml/dlib/examples/faces/training.xml | 34 + .../faces/training_with_face_landmarks.xml | 1280 ++++++++++++++ ml/dlib/examples/fhog_ex.cpp | 88 + ml/dlib/examples/fhog_object_detector_ex.cpp | 269 +++ ml/dlib/examples/file_to_code_ex.cpp | 111 ++ ml/dlib/examples/graph_labeling_ex.cpp | 259 +++ ml/dlib/examples/gui_api_ex.cpp | 231 +++ ml/dlib/examples/hough_transform_ex.cpp | 84 + ml/dlib/examples/image_ex.cpp | 104 ++ .../examples/integrate_function_adapt_simp_ex.cpp | 89 + ml/dlib/examples/iosockstream_ex.cpp | 47 + .../examples/johns/John_Salley/000179_02159509.jpg | Bin 0 -> 9192 bytes .../examples/johns/John_Salley/000183_02159543.jpg | Bin 0 -> 9811 bytes .../examples/johns/John_Salley/000186_02159346.jpg | Bin 0 -> 8161 bytes .../examples/johns/John_Salley/000189_02159361.jpg | Bin 0 -> 9000 bytes .../examples/johns/John_Salley/000190_02159501.jpg | Bin 0 -> 8133 bytes .../examples/johns/John_Salley/000192_02159531.jpg | Bin 0 -> 9465 bytes .../examples/johns/John_Salley/000194_02159572.jpg | Bin 0 -> 7450 bytes .../examples/johns/John_Salley/000197_02159322.jpg | Bin 0 -> 9227 bytes .../examples/johns/John_Salley/000197_02159525.jpg | Bin 0 -> 7935 bytes .../examples/johns/John_Salley/000198_02159470.jpg | Bin 0 -> 10581 bytes .../examples/johns/John_Salley/000200_02159354.jpg | Bin 0 -> 8485 bytes .../examples/johns/John_Savage/000264_01099001.jpg | Bin 0 -> 6494 bytes .../examples/johns/John_Savage/000274_01099061.jpg | Bin 0 -> 6031 bytes .../examples/johns/John_Savage/000277_01099000.jpg | Bin 0 -> 6636 bytes .../examples/johns/John_Savage/000289_01099139.jpg | Bin 0 -> 5746 bytes .../examples/johns/John_Savage/000290_01099067.jpg | Bin 0 -> 6812 bytes .../examples/johns/John_Savage/000290_01099090.jpg | Bin 0 -> 5937 bytes .../examples/johns/John_Savage/000291_01099023.jpg | Bin 0 -> 6374 bytes .../examples/johns/John_Savage/000291_01099214.jpg | Bin 0 -> 5640 bytes .../examples/johns/John_Savage/000293_01099081.jpg | Bin 0 -> 6849 bytes .../examples/johns/John_Savage/000296_01099007.jpg | Bin 0 -> 6576 bytes .../examples/johns/John_Savage/000299_01099008.jpg | Bin 0 -> 5924 bytes .../johns/John_Schneider/000288_00925786.jpg | Bin 0 -> 7542 bytes .../johns/John_Schneider/000302_00925785.jpg | Bin 0 -> 6806 bytes .../johns/John_Schneider/000307_00925823.jpg | Bin 0 -> 7004 bytes .../johns/John_Schneider/000325_00925954.jpg | Bin 0 -> 7627 bytes .../johns/John_Schneider/000326_00925765.jpg | Bin 0 -> 7325 bytes .../johns/John_Schneider/000326_00926089.jpg | Bin 0 -> 7167 bytes .../johns/John_Schneider/000326_00926128.jpg | Bin 0 -> 6057 bytes .../johns/John_Schneider/000326_00926139.jpg | Bin 0 -> 6233 bytes .../johns/John_Schneider/000329_00925859.jpg | Bin 0 -> 6870 bytes .../johns/John_Schneider/000329_00925963.jpg | Bin 0 -> 7393 bytes .../johns/John_Schneider/000331_00926012.jpg | Bin 0 -> 6852 bytes .../johns/John_Shimkus/000373_03228153.jpg | Bin 0 -> 6910 bytes .../johns/John_Shimkus/000375_03227651.jpg | Bin 0 -> 6952 bytes .../johns/John_Shimkus/000376_02340068.jpg | Bin 0 -> 6810 bytes .../johns/John_Shimkus/000378_02340151.jpg | Bin 0 -> 7215 bytes .../johns/John_Shimkus/000378_03227610.jpg | Bin 0 -> 7215 bytes .../johns/John_Shimkus/000383_03227939.jpg | Bin 0 -> 5846 bytes .../johns/John_Shimkus/000385_03227766.jpg | Bin 0 -> 6084 bytes .../johns/John_Shimkus/000388_03227773.jpg | Bin 0 -> 6510 bytes .../johns/John_Shimkus/000390_03227666.jpg | Bin 0 -> 7838 bytes .../johns/John_Shimkus/000394_02340150.jpg | Bin 0 -> 10182 bytes .../johns/John_Shimkus/000396_03227722.jpg | Bin 0 -> 5802 bytes .../examples/johns/John_Simm/000288_00470387.jpg | Bin 0 -> 6513 bytes .../examples/johns/John_Simm/000297_00470170.jpg | Bin 0 -> 7194 bytes .../examples/johns/John_Simm/000300_00470148.jpg | Bin 0 -> 7289 bytes .../examples/johns/John_Simm/000304_00470122.jpg | Bin 0 -> 6582 bytes .../examples/johns/John_Simm/000305_00470162.jpg | Bin 0 -> 7965 bytes .../examples/johns/John_Simm/000305_00470717.jpg | Bin 0 -> 8694 bytes .../examples/johns/John_Simm/000306_00470222.jpg | Bin 0 -> 6306 bytes .../examples/johns/John_Simm/000306_00470223.jpg | Bin 0 -> 6274 bytes .../examples/johns/John_Simm/000309_00470287.jpg | Bin 0 -> 6195 bytes .../examples/johns/John_Simm/000310_00470421.jpg | Bin 0 -> 5563 bytes .../examples/johns/John_Simm/000310_00470511.jpg | Bin 0 -> 7574 bytes ml/dlib/examples/kcentroid_ex.cpp | 129 ++ ml/dlib/examples/kkmeans_ex.cpp | 154 ++ ml/dlib/examples/krls_ex.cpp | 94 ++ ml/dlib/examples/krls_filter_ex.cpp | 109 ++ ml/dlib/examples/krr_classification_ex.cpp | 205 +++ ml/dlib/examples/krr_regression_ex.cpp | 104 ++ ml/dlib/examples/learning_to_track_ex.cpp | 354 ++++ ml/dlib/examples/least_squares_ex.cpp | 228 +++ .../examples/linear_manifold_regularizer_ex.cpp | 284 ++++ ml/dlib/examples/logger_custom_output_ex.cpp | 73 + ml/dlib/examples/logger_ex.cpp | 70 + ml/dlib/examples/logger_ex_2.cpp | 153 ++ ml/dlib/examples/matrix_ex.cpp | 276 +++ ml/dlib/examples/matrix_expressions_ex.cpp | 406 +++++ ml/dlib/examples/max_cost_assignment_ex.cpp | 47 + ml/dlib/examples/member_function_pointer_ex.cpp | 78 + ml/dlib/examples/mlp_ex.cpp | 86 + ml/dlib/examples/mmod_cars_test_image.jpg | Bin 0 -> 100135 bytes ml/dlib/examples/mmod_cars_test_image2.jpg | Bin 0 -> 259439 bytes ml/dlib/examples/model_selection_ex.cpp | 148 ++ ml/dlib/examples/mpc_ex.cpp | 156 ++ ml/dlib/examples/multiclass_classification_ex.cpp | 248 +++ ml/dlib/examples/multithreaded_object_ex.cpp | 138 ++ ml/dlib/examples/object_detector_advanced_ex.cpp | 302 ++++ ml/dlib/examples/object_detector_ex.cpp | 263 +++ ml/dlib/examples/one_class_classifiers_ex.cpp | 245 +++ ml/dlib/examples/optimization_ex.cpp | 319 ++++ ml/dlib/examples/parallel_for_ex.cpp | 158 ++ ml/dlib/examples/pipe_ex.cpp | 172 ++ ml/dlib/examples/pipe_ex_2.cpp | 160 ++ ml/dlib/examples/quantum_computing_ex.cpp | 337 ++++ ml/dlib/examples/queue_ex.cpp | 78 + ml/dlib/examples/random_cropper_ex.cpp | 99 ++ ml/dlib/examples/rank_features_ex.cpp | 152 ++ ml/dlib/examples/running_stats_ex.cpp | 58 + ml/dlib/examples/rvm_ex.cpp | 217 +++ ml/dlib/examples/rvm_regression_ex.cpp | 101 ++ ml/dlib/examples/sequence_labeler_ex.cpp | 392 +++++ ml/dlib/examples/sequence_segmenter_ex.cpp | 238 +++ ml/dlib/examples/server_http_ex.cpp | 108 ++ ml/dlib/examples/server_iostream_ex.cpp | 84 + ml/dlib/examples/sockets_ex.cpp | 63 + ml/dlib/examples/sockstreambuf_ex.cpp | 92 + ml/dlib/examples/sqlite_ex.cpp | 137 ++ ml/dlib/examples/std_allocator_ex.cpp | 57 + ml/dlib/examples/surf_ex.cpp | 82 + ml/dlib/examples/svm_c_ex.cpp | 266 +++ ml/dlib/examples/svm_ex.cpp | 255 +++ ml/dlib/examples/svm_pegasos_ex.cpp | 160 ++ ml/dlib/examples/svm_rank_ex.cpp | 151 ++ ml/dlib/examples/svm_sparse_ex.cpp | 120 ++ ml/dlib/examples/svm_struct_ex.cpp | 414 +++++ ml/dlib/examples/svr_ex.cpp | 96 ++ ml/dlib/examples/thread_function_ex.cpp | 71 + ml/dlib/examples/thread_pool_ex.cpp | 183 ++ ml/dlib/examples/threaded_object_ex.cpp | 79 + ml/dlib/examples/threads_ex.cpp | 93 + ml/dlib/examples/timer_ex.cpp | 56 + ml/dlib/examples/train_object_detector.cpp | 422 +++++ ml/dlib/examples/train_shape_predictor_ex.cpp | 198 +++ ml/dlib/examples/using_custom_kernels_ex.cpp | 208 +++ ml/dlib/examples/video_frames/frame_000100.jpg | Bin 0 -> 4674 bytes ml/dlib/examples/video_frames/frame_000101.jpg | Bin 0 -> 4756 bytes ml/dlib/examples/video_frames/frame_000102.jpg | Bin 0 -> 4683 bytes ml/dlib/examples/video_frames/frame_000103.jpg | Bin 0 -> 4653 bytes ml/dlib/examples/video_frames/frame_000104.jpg | Bin 0 -> 4807 bytes ml/dlib/examples/video_frames/frame_000105.jpg | Bin 0 -> 4760 bytes ml/dlib/examples/video_frames/frame_000106.jpg | Bin 0 -> 4640 bytes ml/dlib/examples/video_frames/frame_000107.jpg | Bin 0 -> 4713 bytes ml/dlib/examples/video_frames/frame_000108.jpg | Bin 0 -> 4908 bytes ml/dlib/examples/video_frames/frame_000109.jpg | Bin 0 -> 4854 bytes ml/dlib/examples/video_frames/frame_000110.jpg | Bin 0 -> 4775 bytes ml/dlib/examples/video_frames/frame_000111.jpg | Bin 0 -> 4587 bytes ml/dlib/examples/video_frames/frame_000112.jpg | Bin 0 -> 4759 bytes ml/dlib/examples/video_frames/frame_000113.jpg | Bin 0 -> 4686 bytes ml/dlib/examples/video_frames/frame_000114.jpg | Bin 0 -> 4740 bytes ml/dlib/examples/video_frames/frame_000115.jpg | Bin 0 -> 4667 bytes ml/dlib/examples/video_frames/frame_000116.jpg | Bin 0 -> 5027 bytes ml/dlib/examples/video_frames/frame_000117.jpg | Bin 0 -> 5160 bytes ml/dlib/examples/video_frames/frame_000118.jpg | Bin 0 -> 5033 bytes ml/dlib/examples/video_frames/frame_000119.jpg | Bin 0 -> 5262 bytes ml/dlib/examples/video_frames/frame_000120.jpg | Bin 0 -> 5213 bytes ml/dlib/examples/video_frames/frame_000121.jpg | Bin 0 -> 5229 bytes ml/dlib/examples/video_frames/frame_000122.jpg | Bin 0 -> 5076 bytes ml/dlib/examples/video_frames/frame_000123.jpg | Bin 0 -> 5162 bytes ml/dlib/examples/video_frames/frame_000124.jpg | Bin 0 -> 5068 bytes ml/dlib/examples/video_frames/frame_000125.jpg | Bin 0 -> 5108 bytes ml/dlib/examples/video_frames/frame_000126.jpg | Bin 0 -> 4987 bytes ml/dlib/examples/video_frames/frame_000127.jpg | Bin 0 -> 5068 bytes ml/dlib/examples/video_frames/frame_000128.jpg | Bin 0 -> 4973 bytes ml/dlib/examples/video_frames/frame_000129.jpg | Bin 0 -> 4931 bytes ml/dlib/examples/video_frames/frame_000130.jpg | Bin 0 -> 5087 bytes ml/dlib/examples/video_frames/frame_000131.jpg | Bin 0 -> 4982 bytes ml/dlib/examples/video_frames/frame_000132.jpg | Bin 0 -> 4965 bytes ml/dlib/examples/video_frames/frame_000133.jpg | Bin 0 -> 4944 bytes ml/dlib/examples/video_frames/frame_000134.jpg | Bin 0 -> 4854 bytes ml/dlib/examples/video_frames/frame_000135.jpg | Bin 0 -> 4803 bytes ml/dlib/examples/video_frames/frame_000136.jpg | Bin 0 -> 4793 bytes ml/dlib/examples/video_frames/frame_000137.jpg | Bin 0 -> 4863 bytes ml/dlib/examples/video_frames/frame_000138.jpg | Bin 0 -> 4969 bytes ml/dlib/examples/video_frames/frame_000139.jpg | Bin 0 -> 4960 bytes ml/dlib/examples/video_frames/frame_000140.jpg | Bin 0 -> 5064 bytes ml/dlib/examples/video_frames/frame_000141.jpg | Bin 0 -> 5115 bytes ml/dlib/examples/video_frames/frame_000142.jpg | Bin 0 -> 5112 bytes ml/dlib/examples/video_frames/frame_000143.jpg | Bin 0 -> 5095 bytes ml/dlib/examples/video_frames/frame_000144.jpg | Bin 0 -> 5082 bytes ml/dlib/examples/video_frames/frame_000145.jpg | Bin 0 -> 4971 bytes ml/dlib/examples/video_frames/frame_000146.jpg | Bin 0 -> 4828 bytes ml/dlib/examples/video_frames/frame_000147.jpg | Bin 0 -> 4813 bytes ml/dlib/examples/video_frames/frame_000148.jpg | Bin 0 -> 4804 bytes ml/dlib/examples/video_frames/frame_000149.jpg | Bin 0 -> 4686 bytes ml/dlib/examples/video_frames/frame_000150.jpg | Bin 0 -> 4859 bytes ml/dlib/examples/video_frames/frame_000151.jpg | Bin 0 -> 4780 bytes ml/dlib/examples/video_frames/frame_000152.jpg | Bin 0 -> 4733 bytes ml/dlib/examples/video_frames/frame_000153.jpg | Bin 0 -> 4619 bytes ml/dlib/examples/video_frames/frame_000154.jpg | Bin 0 -> 4661 bytes ml/dlib/examples/video_frames/frame_000155.jpg | Bin 0 -> 4584 bytes ml/dlib/examples/video_frames/frame_000156.jpg | Bin 0 -> 4577 bytes ml/dlib/examples/video_frames/frame_000157.jpg | Bin 0 -> 4680 bytes ml/dlib/examples/video_frames/frame_000158.jpg | Bin 0 -> 4759 bytes ml/dlib/examples/video_frames/frame_000159.jpg | Bin 0 -> 4671 bytes ml/dlib/examples/video_frames/frame_000160.jpg | Bin 0 -> 4776 bytes ml/dlib/examples/video_frames/frame_000161.jpg | Bin 0 -> 4767 bytes ml/dlib/examples/video_frames/frame_000162.jpg | Bin 0 -> 4763 bytes ml/dlib/examples/video_frames/frame_000163.jpg | Bin 0 -> 4793 bytes ml/dlib/examples/video_frames/frame_000164.jpg | Bin 0 -> 4809 bytes ml/dlib/examples/video_frames/frame_000165.jpg | Bin 0 -> 4774 bytes ml/dlib/examples/video_frames/frame_000166.jpg | Bin 0 -> 4801 bytes ml/dlib/examples/video_frames/frame_000167.jpg | Bin 0 -> 4724 bytes ml/dlib/examples/video_frames/frame_000168.jpg | Bin 0 -> 4656 bytes ml/dlib/examples/video_frames/frame_000169.jpg | Bin 0 -> 4544 bytes ml/dlib/examples/video_frames/frame_000170.jpg | Bin 0 -> 4554 bytes ml/dlib/examples/video_frames/frame_000171.jpg | Bin 0 -> 4574 bytes ml/dlib/examples/video_frames/frame_000172.jpg | Bin 0 -> 4379 bytes ml/dlib/examples/video_frames/frame_000173.jpg | Bin 0 -> 4185 bytes ml/dlib/examples/video_frames/frame_000174.jpg | Bin 0 -> 4457 bytes ml/dlib/examples/video_frames/frame_000175.jpg | Bin 0 -> 4596 bytes ml/dlib/examples/video_frames/frame_000176.jpg | Bin 0 -> 4630 bytes ml/dlib/examples/video_frames/frame_000177.jpg | Bin 0 -> 4539 bytes ml/dlib/examples/video_frames/frame_000178.jpg | Bin 0 -> 4582 bytes ml/dlib/examples/video_frames/frame_000179.jpg | Bin 0 -> 4522 bytes ml/dlib/examples/video_frames/frame_000180.jpg | Bin 0 -> 4599 bytes ml/dlib/examples/video_frames/frame_000181.jpg | Bin 0 -> 4523 bytes ml/dlib/examples/video_frames/frame_000182.jpg | Bin 0 -> 4694 bytes ml/dlib/examples/video_frames/frame_000183.jpg | Bin 0 -> 4729 bytes ml/dlib/examples/video_frames/frame_000184.jpg | Bin 0 -> 4916 bytes ml/dlib/examples/video_frames/frame_000185.jpg | Bin 0 -> 4759 bytes ml/dlib/examples/video_frames/frame_000186.jpg | Bin 0 -> 4963 bytes ml/dlib/examples/video_frames/frame_000187.jpg | Bin 0 -> 5026 bytes ml/dlib/examples/video_frames/frame_000188.jpg | Bin 0 -> 5150 bytes ml/dlib/examples/video_frames/frame_000189.jpg | Bin 0 -> 5233 bytes ml/dlib/examples/video_frames/frame_000190.jpg | Bin 0 -> 4999 bytes ml/dlib/examples/video_frames/frame_000191.jpg | Bin 0 -> 5043 bytes ml/dlib/examples/video_frames/frame_000192.jpg | Bin 0 -> 4730 bytes ml/dlib/examples/video_frames/frame_000193.jpg | Bin 0 -> 4773 bytes ml/dlib/examples/video_frames/frame_000194.jpg | Bin 0 -> 4959 bytes ml/dlib/examples/video_frames/frame_000195.jpg | Bin 0 -> 4775 bytes ml/dlib/examples/video_frames/frame_000196.jpg | Bin 0 -> 5078 bytes ml/dlib/examples/video_frames/frame_000197.jpg | Bin 0 -> 5424 bytes ml/dlib/examples/video_frames/frame_000198.jpg | Bin 0 -> 5373 bytes ml/dlib/examples/video_frames/frame_000199.jpg | Bin 0 -> 5797 bytes ml/dlib/examples/video_frames/frame_000200.jpg | Bin 0 -> 6121 bytes ml/dlib/examples/video_frames/frame_000201.jpg | Bin 0 -> 6208 bytes ml/dlib/examples/video_frames/frame_000202.jpg | Bin 0 -> 6116 bytes ml/dlib/examples/video_frames/frame_000203.jpg | Bin 0 -> 6070 bytes ml/dlib/examples/video_frames/frame_000204.jpg | Bin 0 -> 6069 bytes ml/dlib/examples/video_frames/frame_000205.jpg | Bin 0 -> 5959 bytes ml/dlib/examples/video_frames/frame_000206.jpg | Bin 0 -> 5717 bytes ml/dlib/examples/video_frames/frame_000207.jpg | Bin 0 -> 5751 bytes ml/dlib/examples/video_frames/frame_000208.jpg | Bin 0 -> 5529 bytes ml/dlib/examples/video_frames/frame_000209.jpg | Bin 0 -> 5404 bytes ml/dlib/examples/video_frames/frame_000210.jpg | Bin 0 -> 5458 bytes ml/dlib/examples/video_frames/frame_000211.jpg | Bin 0 -> 5320 bytes ml/dlib/examples/video_frames/frame_000212.jpg | Bin 0 -> 5257 bytes ml/dlib/examples/video_frames/frame_000213.jpg | Bin 0 -> 5462 bytes ml/dlib/examples/video_frames/frame_000214.jpg | Bin 0 -> 5434 bytes ml/dlib/examples/video_frames/frame_000215.jpg | Bin 0 -> 5822 bytes ml/dlib/examples/video_frames/frame_000216.jpg | Bin 0 -> 6131 bytes ml/dlib/examples/video_frames/frame_000217.jpg | Bin 0 -> 6031 bytes ml/dlib/examples/video_frames/frame_000218.jpg | Bin 0 -> 6105 bytes ml/dlib/examples/video_frames/frame_000219.jpg | Bin 0 -> 6136 bytes ml/dlib/examples/video_frames/frame_000220.jpg | Bin 0 -> 5870 bytes ml/dlib/examples/video_frames/frame_000221.jpg | Bin 0 -> 5694 bytes ml/dlib/examples/video_frames/frame_000222.jpg | Bin 0 -> 5430 bytes ml/dlib/examples/video_frames/frame_000223.jpg | Bin 0 -> 5222 bytes ml/dlib/examples/video_frames/frame_000224.jpg | Bin 0 -> 4880 bytes ml/dlib/examples/video_frames/frame_000225.jpg | Bin 0 -> 5090 bytes ml/dlib/examples/video_frames/frame_000226.jpg | Bin 0 -> 4821 bytes ml/dlib/examples/video_frames/frame_000227.jpg | Bin 0 -> 4738 bytes ml/dlib/examples/video_frames/frame_000228.jpg | Bin 0 -> 4500 bytes ml/dlib/examples/video_frames/frame_000229.jpg | Bin 0 -> 4360 bytes ml/dlib/examples/video_frames/frame_000230.jpg | Bin 0 -> 4236 bytes ml/dlib/examples/video_frames/frame_000231.jpg | Bin 0 -> 4243 bytes ml/dlib/examples/video_frames/frame_000232.jpg | Bin 0 -> 4191 bytes ml/dlib/examples/video_frames/frame_000233.jpg | Bin 0 -> 4232 bytes ml/dlib/examples/video_frames/frame_000234.jpg | Bin 0 -> 4250 bytes ml/dlib/examples/video_frames/frame_000235.jpg | Bin 0 -> 4119 bytes ml/dlib/examples/video_frames/frame_000236.jpg | Bin 0 -> 4004 bytes ml/dlib/examples/video_frames/frame_000237.jpg | Bin 0 -> 4248 bytes ml/dlib/examples/video_frames/frame_000238.jpg | Bin 0 -> 4283 bytes ml/dlib/examples/video_frames/frame_000239.jpg | Bin 0 -> 4325 bytes ml/dlib/examples/video_frames/frame_000240.jpg | Bin 0 -> 4458 bytes ml/dlib/examples/video_frames/frame_000241.jpg | Bin 0 -> 4577 bytes ml/dlib/examples/video_frames/frame_000242.jpg | Bin 0 -> 4699 bytes ml/dlib/examples/video_frames/frame_000243.jpg | Bin 0 -> 4773 bytes ml/dlib/examples/video_frames/frame_000244.jpg | Bin 0 -> 4956 bytes ml/dlib/examples/video_frames/frame_000245.jpg | Bin 0 -> 5054 bytes ml/dlib/examples/video_frames/frame_000246.jpg | Bin 0 -> 5200 bytes ml/dlib/examples/video_frames/frame_000247.jpg | Bin 0 -> 5210 bytes ml/dlib/examples/video_frames/frame_000248.jpg | Bin 0 -> 5252 bytes ml/dlib/examples/video_frames/frame_000249.jpg | Bin 0 -> 5249 bytes ml/dlib/examples/video_frames/frame_000250.jpg | Bin 0 -> 5148 bytes ml/dlib/examples/video_frames/license.txt | 6 + ml/dlib/examples/video_tracking_ex.cpp | 72 + ml/dlib/examples/webcam_face_pose_ex.cpp | 100 ++ ml/dlib/examples/xml_parser_ex.cpp | 115 ++ 331 files changed, 23069 insertions(+) create mode 100644 ml/dlib/examples/3d_point_cloud_ex.cpp create mode 100644 ml/dlib/examples/CMakeLists.txt create mode 100644 ml/dlib/examples/LICENSE_FOR_EXAMPLE_PROGRAMS.txt create mode 100644 ml/dlib/examples/assignment_learning_ex.cpp create mode 100644 ml/dlib/examples/bayes_net_ex.cpp create mode 100644 ml/dlib/examples/bayes_net_from_disk_ex.cpp create mode 100644 ml/dlib/examples/bayes_net_gui_ex.cpp create mode 100644 ml/dlib/examples/bridge_ex.cpp create mode 100644 ml/dlib/examples/bsp_ex.cpp create mode 100644 ml/dlib/examples/compress_stream_ex.cpp create mode 100644 ml/dlib/examples/config.txt create mode 100644 ml/dlib/examples/config_reader_ex.cpp create mode 100644 ml/dlib/examples/custom_trainer_ex.cpp create mode 100644 ml/dlib/examples/dir_nav_ex.cpp create mode 100644 ml/dlib/examples/dnn_face_recognition_ex.cpp create mode 100644 ml/dlib/examples/dnn_imagenet_ex.cpp create mode 100644 ml/dlib/examples/dnn_imagenet_train_ex.cpp create mode 100644 ml/dlib/examples/dnn_inception_ex.cpp create mode 100644 ml/dlib/examples/dnn_introduction2_ex.cpp create mode 100644 ml/dlib/examples/dnn_introduction_ex.cpp create mode 100644 ml/dlib/examples/dnn_metric_learning_ex.cpp create mode 100644 ml/dlib/examples/dnn_metric_learning_on_images_ex.cpp create mode 100644 ml/dlib/examples/dnn_mmod_dog_hipsterizer.cpp create mode 100644 ml/dlib/examples/dnn_mmod_ex.cpp create mode 100644 ml/dlib/examples/dnn_mmod_face_detection_ex.cpp create mode 100644 ml/dlib/examples/dnn_mmod_find_cars2_ex.cpp create mode 100644 ml/dlib/examples/dnn_mmod_find_cars_ex.cpp create mode 100644 ml/dlib/examples/dnn_mmod_train_find_cars_ex.cpp create mode 100644 ml/dlib/examples/dnn_semantic_segmentation_ex.cpp create mode 100644 ml/dlib/examples/dnn_semantic_segmentation_ex.h create mode 100644 ml/dlib/examples/dnn_semantic_segmentation_train_ex.cpp create mode 100644 ml/dlib/examples/empirical_kernel_map_ex.cpp create mode 100644 ml/dlib/examples/face_detection_ex.cpp create mode 100644 ml/dlib/examples/face_landmark_detection_ex.cpp create mode 100755 ml/dlib/examples/faces/2007_007763.jpg create mode 100755 ml/dlib/examples/faces/2008_001009.jpg create mode 100755 ml/dlib/examples/faces/2008_001322.jpg create mode 100755 ml/dlib/examples/faces/2008_002079.jpg create mode 100755 ml/dlib/examples/faces/2008_002470.jpg create mode 100755 ml/dlib/examples/faces/2008_002506.jpg create mode 100755 ml/dlib/examples/faces/2008_004176.jpg create mode 100755 ml/dlib/examples/faces/2008_007676.jpg create mode 100755 ml/dlib/examples/faces/2009_004587.jpg create mode 100644 ml/dlib/examples/faces/Tom_Cruise_avp_2014_4.jpg create mode 100644 ml/dlib/examples/faces/bald_guys.jpg create mode 100644 ml/dlib/examples/faces/dogs.jpg create mode 100644 ml/dlib/examples/faces/image_metadata_stylesheet.xsl create mode 100644 ml/dlib/examples/faces/testing.xml create mode 100644 ml/dlib/examples/faces/testing_with_face_landmarks.xml create mode 100644 ml/dlib/examples/faces/training.xml create mode 100644 ml/dlib/examples/faces/training_with_face_landmarks.xml create mode 100644 ml/dlib/examples/fhog_ex.cpp create mode 100644 ml/dlib/examples/fhog_object_detector_ex.cpp create mode 100644 ml/dlib/examples/file_to_code_ex.cpp create mode 100644 ml/dlib/examples/graph_labeling_ex.cpp create mode 100644 ml/dlib/examples/gui_api_ex.cpp create mode 100644 ml/dlib/examples/hough_transform_ex.cpp create mode 100644 ml/dlib/examples/image_ex.cpp create mode 100644 ml/dlib/examples/integrate_function_adapt_simp_ex.cpp create mode 100644 ml/dlib/examples/iosockstream_ex.cpp create mode 100644 ml/dlib/examples/johns/John_Salley/000179_02159509.jpg create mode 100644 ml/dlib/examples/johns/John_Salley/000183_02159543.jpg create mode 100644 ml/dlib/examples/johns/John_Salley/000186_02159346.jpg create mode 100644 ml/dlib/examples/johns/John_Salley/000189_02159361.jpg create mode 100644 ml/dlib/examples/johns/John_Salley/000190_02159501.jpg create mode 100644 ml/dlib/examples/johns/John_Salley/000192_02159531.jpg create mode 100644 ml/dlib/examples/johns/John_Salley/000194_02159572.jpg create mode 100644 ml/dlib/examples/johns/John_Salley/000197_02159322.jpg create mode 100644 ml/dlib/examples/johns/John_Salley/000197_02159525.jpg create mode 100644 ml/dlib/examples/johns/John_Salley/000198_02159470.jpg create mode 100644 ml/dlib/examples/johns/John_Salley/000200_02159354.jpg create mode 100644 ml/dlib/examples/johns/John_Savage/000264_01099001.jpg create mode 100644 ml/dlib/examples/johns/John_Savage/000274_01099061.jpg create mode 100644 ml/dlib/examples/johns/John_Savage/000277_01099000.jpg create mode 100644 ml/dlib/examples/johns/John_Savage/000289_01099139.jpg create mode 100644 ml/dlib/examples/johns/John_Savage/000290_01099067.jpg create mode 100644 ml/dlib/examples/johns/John_Savage/000290_01099090.jpg create mode 100644 ml/dlib/examples/johns/John_Savage/000291_01099023.jpg create mode 100644 ml/dlib/examples/johns/John_Savage/000291_01099214.jpg create mode 100644 ml/dlib/examples/johns/John_Savage/000293_01099081.jpg create mode 100644 ml/dlib/examples/johns/John_Savage/000296_01099007.jpg create mode 100644 ml/dlib/examples/johns/John_Savage/000299_01099008.jpg create mode 100644 ml/dlib/examples/johns/John_Schneider/000288_00925786.jpg create mode 100644 ml/dlib/examples/johns/John_Schneider/000302_00925785.jpg create mode 100644 ml/dlib/examples/johns/John_Schneider/000307_00925823.jpg create mode 100644 ml/dlib/examples/johns/John_Schneider/000325_00925954.jpg create mode 100644 ml/dlib/examples/johns/John_Schneider/000326_00925765.jpg create mode 100644 ml/dlib/examples/johns/John_Schneider/000326_00926089.jpg create mode 100644 ml/dlib/examples/johns/John_Schneider/000326_00926128.jpg create mode 100644 ml/dlib/examples/johns/John_Schneider/000326_00926139.jpg create mode 100644 ml/dlib/examples/johns/John_Schneider/000329_00925859.jpg create mode 100644 ml/dlib/examples/johns/John_Schneider/000329_00925963.jpg create mode 100644 ml/dlib/examples/johns/John_Schneider/000331_00926012.jpg create mode 100644 ml/dlib/examples/johns/John_Shimkus/000373_03228153.jpg create mode 100644 ml/dlib/examples/johns/John_Shimkus/000375_03227651.jpg create mode 100644 ml/dlib/examples/johns/John_Shimkus/000376_02340068.jpg create mode 100644 ml/dlib/examples/johns/John_Shimkus/000378_02340151.jpg create mode 100644 ml/dlib/examples/johns/John_Shimkus/000378_03227610.jpg create mode 100644 ml/dlib/examples/johns/John_Shimkus/000383_03227939.jpg create mode 100644 ml/dlib/examples/johns/John_Shimkus/000385_03227766.jpg create mode 100644 ml/dlib/examples/johns/John_Shimkus/000388_03227773.jpg create mode 100644 ml/dlib/examples/johns/John_Shimkus/000390_03227666.jpg create mode 100644 ml/dlib/examples/johns/John_Shimkus/000394_02340150.jpg create mode 100644 ml/dlib/examples/johns/John_Shimkus/000396_03227722.jpg create mode 100644 ml/dlib/examples/johns/John_Simm/000288_00470387.jpg create mode 100644 ml/dlib/examples/johns/John_Simm/000297_00470170.jpg create mode 100644 ml/dlib/examples/johns/John_Simm/000300_00470148.jpg create mode 100644 ml/dlib/examples/johns/John_Simm/000304_00470122.jpg create mode 100644 ml/dlib/examples/johns/John_Simm/000305_00470162.jpg create mode 100644 ml/dlib/examples/johns/John_Simm/000305_00470717.jpg create mode 100644 ml/dlib/examples/johns/John_Simm/000306_00470222.jpg create mode 100644 ml/dlib/examples/johns/John_Simm/000306_00470223.jpg create mode 100644 ml/dlib/examples/johns/John_Simm/000309_00470287.jpg create mode 100644 ml/dlib/examples/johns/John_Simm/000310_00470421.jpg create mode 100644 ml/dlib/examples/johns/John_Simm/000310_00470511.jpg create mode 100644 ml/dlib/examples/kcentroid_ex.cpp create mode 100644 ml/dlib/examples/kkmeans_ex.cpp create mode 100644 ml/dlib/examples/krls_ex.cpp create mode 100644 ml/dlib/examples/krls_filter_ex.cpp create mode 100644 ml/dlib/examples/krr_classification_ex.cpp create mode 100644 ml/dlib/examples/krr_regression_ex.cpp create mode 100644 ml/dlib/examples/learning_to_track_ex.cpp create mode 100644 ml/dlib/examples/least_squares_ex.cpp create mode 100644 ml/dlib/examples/linear_manifold_regularizer_ex.cpp create mode 100644 ml/dlib/examples/logger_custom_output_ex.cpp create mode 100644 ml/dlib/examples/logger_ex.cpp create mode 100644 ml/dlib/examples/logger_ex_2.cpp create mode 100644 ml/dlib/examples/matrix_ex.cpp create mode 100644 ml/dlib/examples/matrix_expressions_ex.cpp create mode 100755 ml/dlib/examples/max_cost_assignment_ex.cpp create mode 100644 ml/dlib/examples/member_function_pointer_ex.cpp create mode 100644 ml/dlib/examples/mlp_ex.cpp create mode 100644 ml/dlib/examples/mmod_cars_test_image.jpg create mode 100644 ml/dlib/examples/mmod_cars_test_image2.jpg create mode 100644 ml/dlib/examples/model_selection_ex.cpp create mode 100644 ml/dlib/examples/mpc_ex.cpp create mode 100644 ml/dlib/examples/multiclass_classification_ex.cpp create mode 100644 ml/dlib/examples/multithreaded_object_ex.cpp create mode 100644 ml/dlib/examples/object_detector_advanced_ex.cpp create mode 100644 ml/dlib/examples/object_detector_ex.cpp create mode 100644 ml/dlib/examples/one_class_classifiers_ex.cpp create mode 100644 ml/dlib/examples/optimization_ex.cpp create mode 100644 ml/dlib/examples/parallel_for_ex.cpp create mode 100644 ml/dlib/examples/pipe_ex.cpp create mode 100644 ml/dlib/examples/pipe_ex_2.cpp create mode 100644 ml/dlib/examples/quantum_computing_ex.cpp create mode 100644 ml/dlib/examples/queue_ex.cpp create mode 100644 ml/dlib/examples/random_cropper_ex.cpp create mode 100644 ml/dlib/examples/rank_features_ex.cpp create mode 100644 ml/dlib/examples/running_stats_ex.cpp create mode 100644 ml/dlib/examples/rvm_ex.cpp create mode 100644 ml/dlib/examples/rvm_regression_ex.cpp create mode 100644 ml/dlib/examples/sequence_labeler_ex.cpp create mode 100644 ml/dlib/examples/sequence_segmenter_ex.cpp create mode 100644 ml/dlib/examples/server_http_ex.cpp create mode 100644 ml/dlib/examples/server_iostream_ex.cpp create mode 100644 ml/dlib/examples/sockets_ex.cpp create mode 100644 ml/dlib/examples/sockstreambuf_ex.cpp create mode 100644 ml/dlib/examples/sqlite_ex.cpp create mode 100644 ml/dlib/examples/std_allocator_ex.cpp create mode 100644 ml/dlib/examples/surf_ex.cpp create mode 100644 ml/dlib/examples/svm_c_ex.cpp create mode 100644 ml/dlib/examples/svm_ex.cpp create mode 100644 ml/dlib/examples/svm_pegasos_ex.cpp create mode 100644 ml/dlib/examples/svm_rank_ex.cpp create mode 100644 ml/dlib/examples/svm_sparse_ex.cpp create mode 100644 ml/dlib/examples/svm_struct_ex.cpp create mode 100644 ml/dlib/examples/svr_ex.cpp create mode 100644 ml/dlib/examples/thread_function_ex.cpp create mode 100644 ml/dlib/examples/thread_pool_ex.cpp create mode 100644 ml/dlib/examples/threaded_object_ex.cpp create mode 100644 ml/dlib/examples/threads_ex.cpp create mode 100644 ml/dlib/examples/timer_ex.cpp create mode 100644 ml/dlib/examples/train_object_detector.cpp create mode 100644 ml/dlib/examples/train_shape_predictor_ex.cpp create mode 100644 ml/dlib/examples/using_custom_kernels_ex.cpp create mode 100644 ml/dlib/examples/video_frames/frame_000100.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000101.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000102.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000103.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000104.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000105.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000106.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000107.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000108.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000109.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000110.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000111.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000112.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000113.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000114.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000115.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000116.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000117.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000118.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000119.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000120.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000121.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000122.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000123.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000124.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000125.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000126.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000127.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000128.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000129.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000130.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000131.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000132.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000133.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000134.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000135.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000136.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000137.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000138.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000139.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000140.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000141.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000142.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000143.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000144.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000145.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000146.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000147.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000148.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000149.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000150.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000151.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000152.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000153.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000154.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000155.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000156.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000157.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000158.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000159.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000160.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000161.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000162.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000163.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000164.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000165.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000166.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000167.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000168.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000169.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000170.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000171.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000172.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000173.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000174.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000175.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000176.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000177.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000178.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000179.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000180.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000181.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000182.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000183.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000184.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000185.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000186.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000187.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000188.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000189.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000190.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000191.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000192.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000193.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000194.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000195.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000196.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000197.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000198.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000199.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000200.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000201.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000202.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000203.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000204.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000205.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000206.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000207.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000208.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000209.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000210.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000211.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000212.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000213.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000214.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000215.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000216.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000217.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000218.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000219.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000220.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000221.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000222.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000223.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000224.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000225.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000226.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000227.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000228.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000229.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000230.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000231.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000232.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000233.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000234.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000235.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000236.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000237.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000238.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000239.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000240.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000241.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000242.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000243.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000244.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000245.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000246.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000247.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000248.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000249.jpg create mode 100644 ml/dlib/examples/video_frames/frame_000250.jpg create mode 100644 ml/dlib/examples/video_frames/license.txt create mode 100644 ml/dlib/examples/video_tracking_ex.cpp create mode 100644 ml/dlib/examples/webcam_face_pose_ex.cpp create mode 100644 ml/dlib/examples/xml_parser_ex.cpp (limited to 'ml/dlib/examples') diff --git a/ml/dlib/examples/3d_point_cloud_ex.cpp b/ml/dlib/examples/3d_point_cloud_ex.cpp new file mode 100644 index 000000000..f64a68976 --- /dev/null +++ b/ml/dlib/examples/3d_point_cloud_ex.cpp @@ -0,0 +1,50 @@ +// The contents of this file are in the public domain. See LICENSE_FOR_EXAMPLE_PROGRAMS.txt +/* + + This is an example illustrating the use of the perspective_window tool + in the dlib C++ Library. It is a simple tool for displaying 3D point + clouds on the screen. + +*/ + +#include +#include +#include + +using namespace dlib; +using namespace std; + +// ---------------------------------------------------------------------------------------- + +int main() +{ + // Let's make a point cloud that looks like a 3D spiral. + std::vector points; + dlib::rand rnd; + for (double i = 0; i < 20; i+=0.001) + { + // Get a point on a spiral + dlib::vector val(sin(i),cos(i),i/4); + + // Now add some random noise to it + dlib::vector temp(rnd.get_random_gaussian(), + rnd.get_random_gaussian(), + rnd.get_random_gaussian()); + val += temp/20; + + // Pick a color based on how far we are along the spiral + rgb_pixel color = colormap_jet(i,0,20); + + // And add the point to the list of points we will display + points.push_back(perspective_window::overlay_dot(val, color)); + } + + // Now finally display the point cloud. + perspective_window win; + win.set_title("perspective_window 3D point cloud"); + win.add_overlay(points); + win.wait_until_closed(); +} + +// ---------------------------------------------------------------------------- + diff --git a/ml/dlib/examples/CMakeLists.txt b/ml/dlib/examples/CMakeLists.txt new file mode 100644 index 000000000..5c408d74f --- /dev/null +++ b/ml/dlib/examples/CMakeLists.txt @@ -0,0 +1,250 @@ +# +# _______ _ _ _____ _____ _____ _____ +# |__ __| | | |_ _|/ ____| |_ _|/ ____| /\ +# | | | |__| | | | | (___ | | | (___ / \ +# | | | __ | | | \___ \ | | \___ \ / /\ \ +# | | | | | |_| |_ ____) | _| |_ ____) | / ____ \ +# |_|__|_|_ |_|_____|_____/__ |_____|_____/ /_/ _ \_\ +# |__ __| | | |__ __/ __ \| __ \|_ _| /\ | | +# | | | | | | | | | | | | |__) | | | / \ | | +# | | | | | | | | | | | | _ / | | / /\ \ | | +# | | | |__| | | | | |__| | | \ \ _| |_ / ____ \| |____ +# |_| \____/ |_| \____/|_| \_\_____/_/ \_\______| +# +# +# _____ ______ _____ _______ _ _ ______ +# | __ \| ____| /\ | __ \ |__ __| | | | ____| +# | |__) | |__ / \ | | | | | | | |__| | |__ +# | _ /| __| / /\ \ | | | | | | | __ | __| +# | | \ \| |____ / ____ \| |__| | | | | | | | |____ +# |_|__\_\______/_/_ __\_\_____/__ _ |_|__|_|_ |_|______|_ _ _ +# / ____/ __ \| \/ | \/ | ____| \ | |__ __/ ____| | | | | | +# | | | | | | \ / | \ / | |__ | \| | | | | (___ | | | | | +# | | | | | | |\/| | |\/| | __| | . ` | | | \___ \ | | | | | +# | |___| |__| | | | | | | | |____| |\ | | | ____) | |_|_|_|_| +# \_____\____/|_| |_|_| |_|______|_| \_| |_| |_____/ (_|_|_|_) +# +# +# +# This is a CMake makefile. CMake is a tool that helps you build C++ programs. +# You can download CMake from http://www.cmake.org. This CMakeLists.txt file +# you are reading builds dlib's example programs. +# + + +cmake_minimum_required(VERSION 2.8.12) +# Every project needs a name. We call this the "examples" project. +project(examples) + + +# Tell cmake we will need dlib. This command will pull in dlib and compile it +# into your project. Note that you don't need to compile or install dlib. All +# cmake needs is the dlib source code folder and it will take care of everything. +add_subdirectory(../dlib dlib_build) + + +# The next thing we need to do is tell CMake about the code you want to +# compile. We do this with the add_executable() statement which takes the name +# of the output executable and then a list of .cpp files to compile. Here we +# are going to compile one of the dlib example programs which has only one .cpp +# file, assignment_learning_ex.cpp. If your program consisted of multiple .cpp +# files you would simply list them here in the add_executable() statement. +add_executable(assignment_learning_ex assignment_learning_ex.cpp) +# Finally, you need to tell CMake that this program, assignment_learning_ex, +# depends on dlib. You do that with this statement: +target_link_libraries(assignment_learning_ex dlib::dlib) + + + +# To compile this program all you need to do is ask cmake. You would type +# these commands from within the directory containing this CMakeLists.txt +# file: +# mkdir build +# cd build +# cmake .. +# cmake --build . --config Release +# +# The cmake .. command looks in the parent folder for a file named +# CMakeLists.txt, reads it, and sets up everything needed to build program. +# Also, note that CMake can generate Visual Studio or XCode project files. So +# if instead you had written: +# cd build +# cmake .. -G Xcode +# +# You would be able to open the resulting Xcode project and compile and edit +# the example programs within the Xcode IDE. CMake can generate a lot of +# different types of IDE projects. Run the cmake -h command to see a list of +# arguments to -G to see what kinds of projects cmake can generate for you. It +# probably includes your favorite IDE in the list. + + + + +################################################################################# +################################################################################# +# A CMakeLists.txt file can compile more than just one program. So below we +# tell it to compile the other dlib example programs using pretty much the +# same CMake commands we used above. +################################################################################# +################################################################################# + + +# Since there are a lot of examples I'm going to use a macro to simplify this +# CMakeLists.txt file. However, usually you will create only one executable in +# your cmake projects and use the syntax shown above. +macro(add_example name) + add_executable(${name} ${name}.cpp) + target_link_libraries(${name} dlib::dlib ) +endmacro() + +# if an example requires GUI, call this macro to check DLIB_NO_GUI_SUPPORT to include or exclude +macro(add_gui_example name) + if (DLIB_NO_GUI_SUPPORT) + message("No GUI support, so we won't build the ${name} example.") + else() + add_example(${name}) + endif() +endmacro() + +# The deep learning toolkit requires a compiler with essentially complete C++11 +# support. However, versions of Visual Studio prior to October 2016 didn't +# provide enough C++11 support to compile the DNN tooling, but were good enough +# to compile the rest of dlib. So new versions of Visual Studio 2015 will +# work. However, Visual Studio 2017 had some C++11 support regressions, so it +# wasn't until December 2017 that Visual Studio 2017 had good enough C++11 +# support to compile the DNN examples. So if you are using Visual Studio, make +# sure you have an updated version if you want to compile the DNN code. +# +# Also note that Visual Studio users should give the -T host=x64 option so that +# CMake will instruct Visual Studio to use its 64bit toolchain. If you don't +# do this then by default Visual Studio uses a 32bit toolchain, WHICH RESTRICTS +# THE COMPILER TO ONLY 2GB OF RAM, causing it to run out of RAM and crash when +# compiling some of the DNN examples. So generate your project with a statement +# like this: +# cmake .. -G "Visual Studio 14 2015 Win64" -T host=x64 +if (NOT USING_OLD_VISUAL_STUDIO_COMPILER) + add_example(dnn_metric_learning_ex) + add_gui_example(dnn_face_recognition_ex) + add_example(dnn_introduction_ex) + add_example(dnn_introduction2_ex) + add_example(dnn_inception_ex) + add_gui_example(dnn_mmod_ex) + add_gui_example(dnn_mmod_face_detection_ex) + add_gui_example(random_cropper_ex) + add_gui_example(dnn_mmod_dog_hipsterizer) + add_gui_example(dnn_imagenet_ex) + add_gui_example(dnn_mmod_find_cars_ex) + add_gui_example(dnn_mmod_find_cars2_ex) + add_example(dnn_mmod_train_find_cars_ex) + add_gui_example(dnn_semantic_segmentation_ex) + add_example(dnn_imagenet_train_ex) + add_example(dnn_semantic_segmentation_train_ex) + add_example(dnn_metric_learning_on_images_ex) +endif() + + +if (DLIB_NO_GUI_SUPPORT) + message("No GUI support, so we won't build the webcam_face_pose_ex example.") +else() + find_package(OpenCV QUIET) + if (OpenCV_FOUND) + include_directories(${OpenCV_INCLUDE_DIRS}) + + add_executable(webcam_face_pose_ex webcam_face_pose_ex.cpp) + target_link_libraries(webcam_face_pose_ex dlib::dlib ${OpenCV_LIBS} ) + else() + message("OpenCV not found, so we won't build the webcam_face_pose_ex example.") + endif() +endif() + + + +#here we apply our macros +add_gui_example(3d_point_cloud_ex) +add_example(bayes_net_ex) +add_example(bayes_net_from_disk_ex) +add_gui_example(bayes_net_gui_ex) +add_example(bridge_ex) +add_example(bsp_ex) +add_example(compress_stream_ex) +add_example(config_reader_ex) +add_example(custom_trainer_ex) +add_example(dir_nav_ex) +add_example(empirical_kernel_map_ex) +add_gui_example(face_detection_ex) +add_gui_example(face_landmark_detection_ex) +add_gui_example(fhog_ex) +add_gui_example(fhog_object_detector_ex) +add_example(file_to_code_ex) +add_example(graph_labeling_ex) +add_gui_example(gui_api_ex) +add_gui_example(hough_transform_ex) +add_gui_example(image_ex) +add_example(integrate_function_adapt_simp_ex) +add_example(iosockstream_ex) +add_example(kcentroid_ex) +add_example(kkmeans_ex) +add_example(krls_ex) +add_example(krls_filter_ex) +add_example(krr_classification_ex) +add_example(krr_regression_ex) +add_example(learning_to_track_ex) +add_example(least_squares_ex) +add_example(linear_manifold_regularizer_ex) +add_example(logger_custom_output_ex) +add_example(logger_ex) +add_example(logger_ex_2) +add_example(matrix_ex) +add_example(matrix_expressions_ex) +add_example(max_cost_assignment_ex) +add_example(member_function_pointer_ex) +add_example(mlp_ex) +add_example(model_selection_ex) +add_gui_example(mpc_ex) +add_example(multiclass_classification_ex) +add_example(multithreaded_object_ex) +add_gui_example(object_detector_advanced_ex) +add_gui_example(object_detector_ex) +add_gui_example(one_class_classifiers_ex) +add_example(optimization_ex) +add_example(parallel_for_ex) +add_example(pipe_ex) +add_example(pipe_ex_2) +add_example(quantum_computing_ex) +add_example(queue_ex) +add_example(rank_features_ex) +add_example(running_stats_ex) +add_example(rvm_ex) +add_example(rvm_regression_ex) +add_example(sequence_labeler_ex) +add_example(sequence_segmenter_ex) +add_example(server_http_ex) +add_example(server_iostream_ex) +add_example(sockets_ex) +add_example(sockstreambuf_ex) +add_example(std_allocator_ex) +add_gui_example(surf_ex) +add_example(svm_c_ex) +add_example(svm_ex) +add_example(svm_pegasos_ex) +add_example(svm_rank_ex) +add_example(svm_sparse_ex) +add_example(svm_struct_ex) +add_example(svr_ex) +add_example(thread_function_ex) +add_example(thread_pool_ex) +add_example(threaded_object_ex) +add_example(threads_ex) +add_example(timer_ex) +add_gui_example(train_object_detector) +add_example(train_shape_predictor_ex) +add_example(using_custom_kernels_ex) +add_gui_example(video_tracking_ex) +add_example(xml_parser_ex) + + +if (DLIB_LINK_WITH_SQLITE3) + add_example(sqlite_ex) +endif() + + diff --git a/ml/dlib/examples/LICENSE_FOR_EXAMPLE_PROGRAMS.txt b/ml/dlib/examples/LICENSE_FOR_EXAMPLE_PROGRAMS.txt new file mode 100644 index 000000000..c69b87af3 --- /dev/null +++ b/ml/dlib/examples/LICENSE_FOR_EXAMPLE_PROGRAMS.txt @@ -0,0 +1,22 @@ +The intent of the example programs supplied with the dlib C++ library is +to both instruct users and to also provide a simple body of code they +may copy and paste from. To make this as painless as possible all the +example programs have been placed into the public domain. + + +This work is hereby released into the Public Domain. +To view a copy of the public domain dedication, visit +http://creativecommons.org/licenses/publicdomain/ or send a +letter to + Creative Commons + 171 Second Street + Suite 300, + San Francisco, California, 94105, USA. + + + +Public domain dedications are not recognized by some countries. So +if you live in an area where the above dedication isn't valid then +you can consider the example programs to be licensed under the Boost +Software License. + diff --git a/ml/dlib/examples/assignment_learning_ex.cpp b/ml/dlib/examples/assignment_learning_ex.cpp new file mode 100644 index 000000000..7a3acd013 --- /dev/null +++ b/ml/dlib/examples/assignment_learning_ex.cpp @@ -0,0 +1,325 @@ +// The contents of this file are in the public domain. See LICENSE_FOR_EXAMPLE_PROGRAMS.txt +/* + + This is an example illustrating the use of the dlib machine learning tools for + learning to solve the assignment problem. + + Many tasks in computer vision or natural language processing can be thought of + as assignment problems. For example, in a computer vision application where + you are trying to track objects moving around in video, you likely need to solve + an association problem every time you get a new video frame. That is, each new + frame will contain objects (e.g. people, cars, etc.) and you will want to + determine which of these objects are actually things you have seen in previous + frames. + + The assignment problem can be optimally solved using the well known Hungarian + algorithm. However, this algorithm requires the user to supply some function + which measures the "goodness" of an individual association. In many cases the + best way to measure this goodness isn't obvious and therefore machine learning + methods are used. + + The remainder of this example will show you how to learn a goodness function + which is optimal, in a certain sense, for use with the Hungarian algorithm. To + do this, we will make a simple dataset of example associations and use them to + train a supervised machine learning method. + + Finally, note that there is a whole example program dedicated to assignment + learning problems where you are trying to make an object tracker. So if that is + what you are interested in then take a look at the learning_to_track_ex.cpp + example program. +*/ + + +#include +#include + +using namespace std; +using namespace dlib; + + +// ---------------------------------------------------------------------------------------- + +/* + In an association problem, we will talk about the "Left Hand Set" (LHS) and the + "Right Hand Set" (RHS). The task will be to learn to map all elements of LHS to + unique elements of RHS. If an element of LHS can't be mapped to a unique element of + RHS for some reason (e.g. LHS is bigger than RHS) then it can also be mapped to the + special -1 output, indicating no mapping to RHS. + + So the first step is to define the type of elements in each of these sets. In the + code below we will use column vectors in both LHS and RHS. However, in general, + they can each contain any type you like. LHS can even contain a different type + than RHS. +*/ + +typedef dlib::matrix column_vector; + +// This type represents a pair of LHS and RHS. That is, sample_type::first +// contains a left hand set and sample_type::second contains a right hand set. +typedef std::pair, std::vector > sample_type; + +// This type will contain the association information between LHS and RHS. That is, +// it will determine which elements of LHS map to which elements of RHS. +typedef std::vector label_type; + +// In this example, all our LHS and RHS elements will be 3-dimensional vectors. +const unsigned long num_dims = 3; + +void make_data ( + std::vector& samples, + std::vector& labels +); +/*! + ensures + - This function creates a training dataset of 5 example associations. + - #samples.size() == 5 + - #labels.size() == 5 + - for all valid i: + - #samples[i].first == a left hand set + - #samples[i].second == a right hand set + - #labels[i] == a set of integers indicating how to map LHS to RHS. To be + precise: + - #samples[i].first.size() == #labels[i].size() + - for all valid j: + -1 <= #labels[i][j] < #samples[i].second.size() + (A value of -1 indicates that #samples[i].first[j] isn't associated with anything. + All other values indicate the associating element of #samples[i].second) + - All elements of #labels[i] which are not equal to -1 are unique. That is, + multiple elements of #samples[i].first can't associate to the same element + in #samples[i].second. +!*/ + +// ---------------------------------------------------------------------------------------- + +struct feature_extractor +{ + /*! + Recall that our task is to learn the "goodness of assignment" function for + use with the Hungarian algorithm. The dlib tools assume this function + can be written as: + match_score(l,r) == dot(w, PSI(l,r)) + bias + where l is an element of LHS, r is an element of RHS, w is a parameter vector, + bias is a scalar value, and PSI() is a user supplied feature extractor. + + This feature_extractor is where we implement PSI(). How you implement this + is highly problem dependent. + !*/ + + // The type of feature vector returned from get_features(). This must be either + // a dlib::matrix or a sparse vector. + typedef column_vector feature_vector_type; + + // The types of elements in the LHS and RHS sets + typedef column_vector lhs_element; + typedef column_vector rhs_element; + + + unsigned long num_features() const + { + // Return the dimensionality of feature vectors produced by get_features() + return num_dims; + } + + void get_features ( + const lhs_element& left, + const rhs_element& right, + feature_vector_type& feats + ) const + /*! + ensures + - #feats == PSI(left,right) + (i.e. This function computes a feature vector which, in some sense, + captures information useful for deciding if matching left to right + is "good"). + !*/ + { + // Let's just use the squared difference between each vector as our features. + // However, it should be emphasized that how to compute the features here is very + // problem dependent. + feats = squared(left - right); + } + +}; + +// We need to define serialize() and deserialize() for our feature extractor if we want +// to be able to serialize and deserialize our learned models. In this case the +// implementation is empty since our feature_extractor doesn't have any state. But you +// might define more complex feature extractors which have state that needs to be saved. +void serialize (const feature_extractor& , std::ostream& ) {} +void deserialize (feature_extractor& , std::istream& ) {} + +// ---------------------------------------------------------------------------------------- + +int main() +{ + try + { + // Get a small bit of training data. + std::vector samples; + std::vector labels; + make_data(samples, labels); + + + structural_assignment_trainer trainer; + // This is the common SVM C parameter. Larger values encourage the + // trainer to attempt to fit the data exactly but might overfit. + // In general, you determine this parameter by cross-validation. + trainer.set_c(10); + // This trainer can use multiple CPU cores to speed up the training. + // So set this to the number of available CPU cores. + trainer.set_num_threads(4); + + // Do the training and save the results in assigner. + assignment_function assigner = trainer.train(samples, labels); + + + // Test the assigner on our data. The output will indicate that it makes the + // correct associations on all samples. + cout << "Test the learned assignment function: " << endl; + for (unsigned long i = 0; i < samples.size(); ++i) + { + // Predict the assignments for the LHS and RHS in samples[i]. + std::vector predicted_assignments = assigner(samples[i]); + cout << "true labels: " << trans(mat(labels[i])); + cout << "predicted labels: " << trans(mat(predicted_assignments)) << endl; + } + + // We can also use this tool to compute the percentage of assignments predicted correctly. + cout << "training accuracy: " << test_assignment_function(assigner, samples, labels) << endl; + + + // Since testing on your training data is a really bad idea, we can also do 5-fold cross validation. + // Happily, this also indicates that all associations were made correctly. + randomize_samples(samples, labels); + cout << "cv accuracy: " << cross_validate_assignment_trainer(trainer, samples, labels, 5) << endl; + + + + // Finally, the assigner can be serialized to disk just like most dlib objects. + serialize("assigner.dat") << assigner; + + // recall from disk + deserialize("assigner.dat") >> assigner; + } + catch (std::exception& e) + { + cout << "EXCEPTION THROWN" << endl; + cout << e.what() << endl; + } +} + +// ---------------------------------------------------------------------------------------- + +void make_data ( + std::vector& samples, + std::vector& labels +) +{ + // Make four different vectors. We will use them to make example assignments. + column_vector A(num_dims), B(num_dims), C(num_dims), D(num_dims); + A = 1,0,0; + B = 0,1,0; + C = 0,0,1; + D = 0,1,1; + + std::vector lhs; + std::vector rhs; + label_type mapping; + + // In all the assignments to follow, we will only say an element of the LHS + // matches an element of the RHS if the two are equal. So A matches with A, + // B with B, etc. But never A with C, for example. + // ------------------------ + + lhs.resize(3); + lhs[0] = A; + lhs[1] = B; + lhs[2] = C; + + rhs.resize(3); + rhs[0] = B; + rhs[1] = A; + rhs[2] = C; + + mapping.resize(3); + mapping[0] = 1; // lhs[0] matches rhs[1] + mapping[1] = 0; // lhs[1] matches rhs[0] + mapping[2] = 2; // lhs[2] matches rhs[2] + + samples.push_back(make_pair(lhs,rhs)); + labels.push_back(mapping); + + // ------------------------ + + lhs[0] = C; + lhs[1] = A; + lhs[2] = B; + + rhs[0] = A; + rhs[1] = B; + rhs[2] = D; + + mapping[0] = -1; // The -1 indicates that lhs[0] doesn't match anything in rhs. + mapping[1] = 0; // lhs[1] matches rhs[0] + mapping[2] = 1; // lhs[2] matches rhs[1] + + samples.push_back(make_pair(lhs,rhs)); + labels.push_back(mapping); + + // ------------------------ + + lhs[0] = A; + lhs[1] = B; + lhs[2] = C; + + rhs.resize(4); + rhs[0] = C; + rhs[1] = B; + rhs[2] = A; + rhs[3] = D; + + mapping[0] = 2; + mapping[1] = 1; + mapping[2] = 0; + + samples.push_back(make_pair(lhs,rhs)); + labels.push_back(mapping); + + // ------------------------ + + lhs.resize(2); + lhs[0] = B; + lhs[1] = C; + + rhs.resize(3); + rhs[0] = C; + rhs[1] = A; + rhs[2] = D; + + mapping.resize(2); + mapping[0] = -1; + mapping[1] = 0; + + samples.push_back(make_pair(lhs,rhs)); + labels.push_back(mapping); + + // ------------------------ + + lhs.resize(3); + lhs[0] = D; + lhs[1] = B; + lhs[2] = C; + + // rhs will be empty. So none of the items in lhs can match anything. + rhs.resize(0); + + mapping.resize(3); + mapping[0] = -1; + mapping[1] = -1; + mapping[2] = -1; + + samples.push_back(make_pair(lhs,rhs)); + labels.push_back(mapping); + +} + diff --git a/ml/dlib/examples/bayes_net_ex.cpp b/ml/dlib/examples/bayes_net_ex.cpp new file mode 100644 index 000000000..64f2ad957 --- /dev/null +++ b/ml/dlib/examples/bayes_net_ex.cpp @@ -0,0 +1,307 @@ +// The contents of this file are in the public domain. See LICENSE_FOR_EXAMPLE_PROGRAMS.txt +/* + This is an example illustrating the use of the Bayesian Network + inference utilities found in the dlib C++ library. + + + In this example all the nodes in the Bayesian network are + boolean variables. That is, they take on either the value + 0 or the value 1. + + The network contains 4 nodes and looks as follows: + + B C + \\ // + \/ \/ + A + || + \/ + D + + + The probabilities of each node are summarized below. (The probability + of each node being 0 is not listed since it is just P(X=0) = 1-p(X=1) ) + + p(B=1) = 0.01 + + p(C=1) = 0.001 + + p(A=1 | B=0, C=0) = 0.01 + p(A=1 | B=0, C=1) = 0.5 + p(A=1 | B=1, C=0) = 0.9 + p(A=1 | B=1, C=1) = 0.99 + + p(D=1 | A=0) = 0.2 + p(D=1 | A=1) = 0.5 + +*/ + + +#include +#include +#include +#include +#include + + +using namespace dlib; +using namespace std; + +// ---------------------------------------------------------------------------------------- + +int main() +{ + try + { + // There are many useful convenience functions in this namespace. They all + // perform simple access or modify operations on the nodes of a bayesian network. + // You don't have to use them but they are convenient and they also will check for + // various errors in your bayesian network when your application is built with + // the DEBUG or ENABLE_ASSERTS preprocessor definitions defined. So their use + // is recommended. In fact, most of the global functions used in this example + // program are from this namespace. + using namespace bayes_node_utils; + + // This statement declares a bayesian network called bn. Note that a bayesian network + // in the dlib world is just a directed_graph object that contains a special kind + // of node called a bayes_node. + directed_graph::kernel_1a_c bn; + + // Use an enum to make some more readable names for our nodes. + enum nodes + { + A = 0, + B = 1, + C = 2, + D = 3 + }; + + // The next few blocks of code setup our bayesian network. + + // The first thing we do is tell the bn object how many nodes it has + // and also add the three edges. Again, we are using the network + // shown in ASCII art at the top of this file. + bn.set_number_of_nodes(4); + bn.add_edge(A, D); + bn.add_edge(B, A); + bn.add_edge(C, A); + + + // Now we inform all the nodes in the network that they are binary + // nodes. That is, they only have two possible values. + set_node_num_values(bn, A, 2); + set_node_num_values(bn, B, 2); + set_node_num_values(bn, C, 2); + set_node_num_values(bn, D, 2); + + assignment parent_state; + // Now we will enter all the conditional probability information for each node. + // Each node's conditional probability is dependent on the state of its parents. + // To specify this state we need to use the assignment object. This assignment + // object allows us to specify the state of each nodes parents. + + + // Here we specify that p(B=1) = 0.01 + // parent_state is empty in this case since B is a root node. + set_node_probability(bn, B, 1, parent_state, 0.01); + // Here we specify that p(B=0) = 1-0.01 + set_node_probability(bn, B, 0, parent_state, 1-0.01); + + + // Here we specify that p(C=1) = 0.001 + // parent_state is empty in this case since B is a root node. + set_node_probability(bn, C, 1, parent_state, 0.001); + // Here we specify that p(C=0) = 1-0.001 + set_node_probability(bn, C, 0, parent_state, 1-0.001); + + + // This is our first node that has parents. So we set the parent_state + // object to reflect that A has both B and C as parents. + parent_state.add(B, 1); + parent_state.add(C, 1); + // Here we specify that p(A=1 | B=1, C=1) = 0.99 + set_node_probability(bn, A, 1, parent_state, 0.99); + // Here we specify that p(A=0 | B=1, C=1) = 1-0.99 + set_node_probability(bn, A, 0, parent_state, 1-0.99); + + // Here we use the [] notation because B and C have already + // been added into parent state. + parent_state[B] = 1; + parent_state[C] = 0; + // Here we specify that p(A=1 | B=1, C=0) = 0.9 + set_node_probability(bn, A, 1, parent_state, 0.9); + set_node_probability(bn, A, 0, parent_state, 1-0.9); + + parent_state[B] = 0; + parent_state[C] = 1; + // Here we specify that p(A=1 | B=0, C=1) = 0.5 + set_node_probability(bn, A, 1, parent_state, 0.5); + set_node_probability(bn, A, 0, parent_state, 1-0.5); + + parent_state[B] = 0; + parent_state[C] = 0; + // Here we specify that p(A=1 | B=0, C=0) = 0.01 + set_node_probability(bn, A, 1, parent_state, 0.01); + set_node_probability(bn, A, 0, parent_state, 1-0.01); + + + // Here we set probabilities for node D. + // First we clear out parent state so that it doesn't have any of + // the assignments for the B and C nodes used above. + parent_state.clear(); + parent_state.add(A,1); + // Here we specify that p(D=1 | A=1) = 0.5 + set_node_probability(bn, D, 1, parent_state, 0.5); + set_node_probability(bn, D, 0, parent_state, 1-0.5); + + parent_state[A] = 0; + // Here we specify that p(D=1 | A=0) = 0.2 + set_node_probability(bn, D, 1, parent_state, 0.2); + set_node_probability(bn, D, 0, parent_state, 1-0.2); + + + + // We have now finished setting up our bayesian network. So let's compute some + // probability values. The first thing we will do is compute the prior probability + // of each node in the network. To do this we will use the join tree algorithm which + // is an algorithm for performing exact inference in a bayesian network. + + // First we need to create an undirected graph which contains set objects at each node and + // edge. This long declaration does the trick. + typedef dlib::set::compare_1b_c set_type; + typedef graph::kernel_1a_c join_tree_type; + join_tree_type join_tree; + + // Now we need to populate the join_tree with data from our bayesian network. The next + // function calls do this. Explaining exactly what they do is outside the scope of this + // example. Just think of them as filling join_tree with information that is useful + // later on for dealing with our bayesian network. + create_moral_graph(bn, join_tree); + create_join_tree(join_tree, join_tree); + + // Now that we have a proper join_tree we can use it to obtain a solution to our + // bayesian network. Doing this is as simple as declaring an instance of + // the bayesian_network_join_tree object as follows: + bayesian_network_join_tree solution(bn, join_tree); + + + // now print out the probabilities for each node + cout << "Using the join tree algorithm:\n"; + cout << "p(A=1) = " << solution.probability(A)(1) << endl; + cout << "p(A=0) = " << solution.probability(A)(0) << endl; + cout << "p(B=1) = " << solution.probability(B)(1) << endl; + cout << "p(B=0) = " << solution.probability(B)(0) << endl; + cout << "p(C=1) = " << solution.probability(C)(1) << endl; + cout << "p(C=0) = " << solution.probability(C)(0) << endl; + cout << "p(D=1) = " << solution.probability(D)(1) << endl; + cout << "p(D=0) = " << solution.probability(D)(0) << endl; + cout << "\n\n\n"; + + + // Now to make things more interesting let's say that we have discovered that the C + // node really has a value of 1. That is to say, we now have evidence that + // C is 1. We can represent this in the network using the following two function + // calls. + set_node_value(bn, C, 1); + set_node_as_evidence(bn, C); + + // Now we want to compute the probabilities of all the nodes in the network again + // given that we now know that C is 1. We can do this as follows: + bayesian_network_join_tree solution_with_evidence(bn, join_tree); + + // now print out the probabilities for each node + cout << "Using the join tree algorithm:\n"; + cout << "p(A=1 | C=1) = " << solution_with_evidence.probability(A)(1) << endl; + cout << "p(A=0 | C=1) = " << solution_with_evidence.probability(A)(0) << endl; + cout << "p(B=1 | C=1) = " << solution_with_evidence.probability(B)(1) << endl; + cout << "p(B=0 | C=1) = " << solution_with_evidence.probability(B)(0) << endl; + cout << "p(C=1 | C=1) = " << solution_with_evidence.probability(C)(1) << endl; + cout << "p(C=0 | C=1) = " << solution_with_evidence.probability(C)(0) << endl; + cout << "p(D=1 | C=1) = " << solution_with_evidence.probability(D)(1) << endl; + cout << "p(D=0 | C=1) = " << solution_with_evidence.probability(D)(0) << endl; + cout << "\n\n\n"; + + // Note that when we made our solution_with_evidence object we reused our join_tree object. + // This saves us the time it takes to calculate the join_tree object from scratch. But + // it is important to note that we can only reuse the join_tree object if we haven't changed + // the structure of our bayesian network. That is, if we have added or removed nodes or + // edges from our bayesian network then we must recompute our join_tree. But in this example + // all we did was change the value of a bayes_node object (we made node C be evidence) + // so we are ok. + + + + + + // Next this example will show you how to use the bayesian_network_gibbs_sampler object + // to perform approximate inference in a bayesian network. This is an algorithm + // that doesn't give you an exact solution but it may be necessary to use in some + // instances. For example, the join tree algorithm used above, while fast in many + // instances, has exponential runtime in some cases. Moreover, inference in bayesian + // networks is NP-Hard for general networks so sometimes the best you can do is + // find an approximation. + // However, it should be noted that the gibbs sampler does not compute the correct + // probabilities if the network contains a deterministic node. That is, if any + // of the conditional probability tables in the bayesian network have a probability + // of 1.0 for something the gibbs sampler should not be used. + + + // This Gibbs sampler algorithm works by randomly sampling possibles values of the + // network. So to use it we should set the network to some initial state. + + set_node_value(bn, A, 0); + set_node_value(bn, B, 0); + set_node_value(bn, D, 0); + + // We will leave the C node with a value of 1 and keep it as an evidence node. + + + // First create an instance of the gibbs sampler object + bayesian_network_gibbs_sampler sampler; + + + // To use this algorithm all we do is go into a loop for a certain number of times + // and each time through we sample the bayesian network. Then we count how + // many times a node has a certain state. Then the probability of that node + // having that state is just its count/total times through the loop. + + // The following code illustrates the general procedure. + unsigned long A_count = 0; + unsigned long B_count = 0; + unsigned long C_count = 0; + unsigned long D_count = 0; + + // The more times you let the loop run the more accurate the result will be. Here we loop + // 2000 times. + const long rounds = 2000; + for (long i = 0; i < rounds; ++i) + { + sampler.sample_graph(bn); + + if (node_value(bn, A) == 1) + ++A_count; + if (node_value(bn, B) == 1) + ++B_count; + if (node_value(bn, C) == 1) + ++C_count; + if (node_value(bn, D) == 1) + ++D_count; + } + + cout << "Using the approximate Gibbs Sampler algorithm:\n"; + cout << "p(A=1 | C=1) = " << (double)A_count/(double)rounds << endl; + cout << "p(B=1 | C=1) = " << (double)B_count/(double)rounds << endl; + cout << "p(C=1 | C=1) = " << (double)C_count/(double)rounds << endl; + cout << "p(D=1 | C=1) = " << (double)D_count/(double)rounds << endl; + } + catch (std::exception& e) + { + cout << "exception thrown: " << endl; + cout << e.what() << endl; + cout << "hit enter to terminate" << endl; + cin.get(); + } +} + + + diff --git a/ml/dlib/examples/bayes_net_from_disk_ex.cpp b/ml/dlib/examples/bayes_net_from_disk_ex.cpp new file mode 100644 index 000000000..eaab5881a --- /dev/null +++ b/ml/dlib/examples/bayes_net_from_disk_ex.cpp @@ -0,0 +1,83 @@ +// The contents of this file are in the public domain. See LICENSE_FOR_EXAMPLE_PROGRAMS.txt +/* + This is an example illustrating the use of the Bayesian Network + inference utilities found in the dlib C++ library. In this example + we load a saved Bayesian Network from disk. +*/ + + +#include +#include +#include +#include +#include +#include + + +using namespace dlib; +using namespace std; + +// ---------------------------------------------------------------------------------------- + +int main(int argc, char** argv) +{ + try + { + // This statement declares a bayesian network called bn. Note that a bayesian network + // in the dlib world is just a directed_graph object that contains a special kind + // of node called a bayes_node. + directed_graph::kernel_1a_c bn; + + if (argc != 2) + { + cout << "You must supply a file name on the command line. The file should " + << "contain a serialized Bayesian Network" << endl; + return 1; + } + + ifstream fin(argv[1],ios::binary); + + // Note that the saved networks produced by the bayes_net_gui_ex.cpp example can be deserialized + // into a network. So you can make your networks using that GUI if you like. + cout << "Loading the network from disk..." << endl; + deserialize(bn, fin); + + cout << "Number of nodes in the network: " << bn.number_of_nodes() << endl; + + // Let's compute some probability values using the loaded network using the join tree (aka. Junction + // Tree) algorithm. + + // First we need to create an undirected graph which contains set objects at each node and + // edge. This long declaration does the trick. + typedef graph::compare_1b_c, dlib::set::compare_1b_c>::kernel_1a_c join_tree_type; + join_tree_type join_tree; + + // Now we need to populate the join_tree with data from our bayesian network. The next two + // function calls do this. Explaining exactly what they do is outside the scope of this + // example. Just think of them as filling join_tree with information that is useful + // later on for dealing with our bayesian network. + create_moral_graph(bn, join_tree); + create_join_tree(join_tree, join_tree); + + // Now we have a proper join_tree we can use it to obtain a solution to our + // bayesian network. Doing this is as simple as declaring an instance of + // the bayesian_network_join_tree object as follows: + bayesian_network_join_tree solution(bn, join_tree); + + + // now print out the probabilities for each node + cout << "Using the join tree algorithm:\n"; + for (unsigned long i = 0; i < bn.number_of_nodes(); ++i) + { + // print out the probability distribution for node i. + cout << "p(node " << i <<") = " << solution.probability(i); + } + } + catch (exception& e) + { + cout << "exception thrown: " << e.what() << endl; + return 1; + } +} + + diff --git a/ml/dlib/examples/bayes_net_gui_ex.cpp b/ml/dlib/examples/bayes_net_gui_ex.cpp new file mode 100644 index 000000000..81101912c --- /dev/null +++ b/ml/dlib/examples/bayes_net_gui_ex.cpp @@ -0,0 +1,989 @@ +// The contents of this file are in the public domain. See LICENSE_FOR_EXAMPLE_PROGRAMS.txt +/* + This is a rather involved example illustrating the use of the GUI api from + the dlib C++ Library. This program is a fully functional utility for + creating Bayesian Networks. It allows the user to graphically draw the network, + save/load the network to/from disk, and also to calculate the posterior + probability of any node in the network given a set of evidence. + + This is not the first dlib example program you should be looking at. If you + want to see a simpler GUI example please look at the gui_api_ex.cpp or + image_ex.cpp example. + + If you want to understand how to use the Bayesian Network utilities in the library + you should definitely look at the bayes_net_ex.cpp example program. It gives a + comprehensive introduction to creating and manipulating Bayesian Networks. If you + want to see how to load a saved network from disk and use it in a non-GUI application + then look at the bayes_net_from_disk_ex.cpp example. + + + Now all of that being said, if you have already looked at the other relevant + examples and want to see a more in-depth example then by all means, continue reading. :) +*/ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + +using namespace std; +using namespace dlib; +using namespace dlib::bayes_node_utils; + +// ---------------------------------------------------------------------------- + +typedef directed_graph::kernel_1a_c directed_graph_type; +typedef directed_graph::kernel_1a_c::node_type node_type; +typedef graph::compare_1b_c, dlib::set::compare_1b_c>::kernel_1a_c join_tree_type; + +// ---------------------------------------------------------------------------- + +class main_window : public drawable_window +{ + /*! + INITIAL VALUE + This window starts out hidden and with an empty Bayesian Network + + WHAT THIS OBJECT REPRESENTS + This object is the main window of a utility for drawing Bayesian Networks. + It allows you to draw a directed graph and to set the conditional probability + tables up for each node in the network. It also allows you to compute the + posterior probability of each node. And finally, it lets you save and load + networks from file + !*/ +public: + main_window(); + ~main_window(); + +private: + + // Private helper methods + + void initialize_node_cpt_if_necessary ( unsigned long index ); + void load_selected_node_tables_into_cpt_grid (); + void load_selected_node_tables_into_ppt_grid (); + void no_node_selected (); + + + // Event handlers + + void on_cpt_grid_modified(unsigned long row, unsigned long col); + void on_evidence_toggled (); + void on_graph_modified (); + void on_menu_file_open (); + void on_menu_file_quit (); + void on_menu_file_save (); + void on_menu_file_save_as (); + void on_menu_help_about (); + void on_menu_help_help (); + void on_node_deleted (); + void on_node_deselected ( unsigned long n ); + void on_node_selected (unsigned long n); + void on_open_file_selected ( const std::string& file_name); + void on_save_file_selected ( const std::string& file_name); + void on_sel_node_evidence_modified (); + void on_sel_node_num_values_modified (); + void on_sel_node_text_modified (); + void on_window_resized (); + void recalculate_probabilities (); + + // Member data + + const rgb_pixel color_non_evidence; + const rgb_pixel color_default_bg; + const rgb_pixel color_evidence; + const rgb_pixel color_error; + const rgb_pixel color_gray; + bool graph_modified_since_last_recalc; + + button btn_calculate; + check_box sel_node_is_evidence; + directed_graph_drawer graph_drawer; + label sel_node_index; + label sel_node_num_values_label; + label sel_node_text_label; + label sel_node_evidence_label; + menu_bar mbar; + named_rectangle selected_node_rect; + tabbed_display tables; + text_field sel_node_num_values; + text_field sel_node_text; + text_field sel_node_evidence; + text_grid cpt_grid; + text_grid ppt_grid; + unsigned long selected_node_index; + bool node_is_selected; + widget_group cpt_group; + widget_group ppt_group; + + std::unique_ptr solution; + join_tree_type join_tree; + // The std_vector_c is an object identical to the std::vector except that it checks + // all its preconditions and throws a dlib::fatal_error if they are violated. + std_vector_c cpt_grid_assignments; + std::string graph_file_name; +}; + +// ---------------------------------------------------------------------------------------- + +int main() +{ + // create our window + main_window my_window; + + // tell our window to put itself on the screen + my_window.show(); + + // wait until the user closes this window before we let the program + // terminate. + my_window.wait_until_closed(); +} + +// ---------------------------------------------------------------------------------------- + +#ifdef WIN32 +// If you use main() as your entry point when building a program on MS Windows then +// there will be a black console window associated with your application. If you +// want your application to not have this console window then you need to build +// using the WinMain() entry point as shown below and also set your compiler to +// produce a "Windows" project instead of a "Console" project. In visual studio +// this can be accomplished by going to project->properties->general configuration-> +// Linker->System->SubSystem and selecting Windows instead of Console. +// +int WINAPI WinMain (HINSTANCE, HINSTANCE, PSTR cmds, int) +{ + main(); + return 0; +} +#endif + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// Methods from the main_window object +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + +main_window:: +main_window( +) : + color_non_evidence(0,0,0), + color_default_bg(255,255,255), + color_evidence(100,200,100), + color_error(255,0,0), + color_gray(210,210,210), + graph_modified_since_last_recalc(true), + btn_calculate(*this), + sel_node_is_evidence(*this), + graph_drawer(*this), + sel_node_index(*this), + sel_node_num_values_label (*this), + sel_node_text_label(*this), + sel_node_evidence_label(*this), + mbar(*this), + selected_node_rect(*this), + tables(*this), + sel_node_num_values(*this), + sel_node_text(*this), + sel_node_evidence(*this), + cpt_grid(*this), + ppt_grid(*this), + selected_node_index(0), + node_is_selected(false), + cpt_group(*this), + ppt_group(*this) +{ + // Note that all the GUI widgets take a reference to the window that contains them + // as their constructor argument. This is a universal feature of GUI widgets in the + // dlib library. + + set_title("Bayesian Network Utility"); + + // position the widget that is responsible for drawing the directed graph, the graph_drawer, + // just below the mbar (menu bar) widget. + graph_drawer.set_pos(5,mbar.bottom()+5); + set_size(750,400); + + // register the event handlers with their respective widgets + btn_calculate.set_click_handler (*this, &main_window::recalculate_probabilities); + cpt_grid.set_text_modified_handler (*this, &main_window::on_cpt_grid_modified); + graph_drawer.set_graph_modified_handler (*this, &main_window::on_graph_modified); + graph_drawer.set_node_deleted_handler (*this, &main_window::on_node_deleted); + graph_drawer.set_node_deselected_handler (*this, &main_window::on_node_deselected); + graph_drawer.set_node_selected_handler (*this, &main_window::on_node_selected); + sel_node_evidence.set_text_modified_handler (*this, &main_window::on_sel_node_evidence_modified); + sel_node_is_evidence.set_click_handler (*this, &main_window::on_evidence_toggled); + sel_node_num_values.set_text_modified_handler(*this, &main_window::on_sel_node_num_values_modified); + sel_node_text.set_text_modified_handler (*this, &main_window::on_sel_node_text_modified); + + // now set the text of some of our buttons and labels + btn_calculate.set_name("Recalculate posterior probability table"); + selected_node_rect.set_name("Selected node"); + sel_node_evidence_label.set_text("evidence value:"); + sel_node_is_evidence.set_name("is evidence"); + sel_node_num_values_label.set_text("Number of values: "); + sel_node_text_label.set_text("Node label:"); + + // Now setup the tabbed display. It will have two tabs, one for the conditional + // probability table and one for the posterior probability table. + tables.set_number_of_tabs(2); + tables.set_tab_name(0,"Conditional probability table"); + tables.set_tab_name(1,"Posterior probability table"); + cpt_group.add(cpt_grid,0,0); + ppt_group.add(ppt_grid,0,0); + tables.set_tab_group(0,cpt_group); + tables.set_tab_group(1,ppt_group); + + // Now setup the menu bar. We will have two menus. A File and Help menu. + mbar.set_number_of_menus(2); + mbar.set_menu_name(0,"File",'F'); + mbar.set_menu_name(1,"Help",'H'); + + // add the entries to the File menu. + mbar.menu(0).add_menu_item(menu_item_text("Open", *this, &main_window::on_menu_file_open, 'O')); + mbar.menu(0).add_menu_item(menu_item_separator()); + mbar.menu(0).add_menu_item(menu_item_text("Save", *this, &main_window::on_menu_file_save, 'S')); + mbar.menu(0).add_menu_item(menu_item_text("Save As",*this, &main_window::on_menu_file_save_as, 'a')); + mbar.menu(0).add_menu_item(menu_item_separator()); + mbar.menu(0).add_menu_item(menu_item_text("Quit", *this, &main_window::on_menu_file_quit, 'Q')); + + // Add the entries to the Help menu. + mbar.menu(1).add_menu_item(menu_item_text("Help", *this, &main_window::on_menu_help_help, 'e')); + mbar.menu(1).add_menu_item(menu_item_text("About", *this, &main_window::on_menu_help_about, 'A')); + + + // call our helper functions and window resize event to get the widgets + // to all arrange themselves correctly in our window. + no_node_selected(); + on_window_resized(); +} + +// ---------------------------------------------------------------------------------------- + +main_window:: +~main_window( +) +{ + // You should always call close_window() in the destructor of window + // objects to ensure that no events will be sent to this window while + // it is being destructed. + close_window(); +} + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// Private methods from the main_window object +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + +void main_window:: +load_selected_node_tables_into_ppt_grid ( +) +{ + // This function just takes the currently selected graph node and loads + // its posterior probabilities into the ppt_graph widget. + node_type& node = graph_drawer.graph_node(selected_node_index); + ppt_grid.set_grid_size(2,node.data.table().num_values()); + + // load the top row of the table into the grid. This row is the "title bar" row + // that tells you what each column contains. + for (unsigned long col = 0; col < node.data.table().num_values(); ++col) + { + ppt_grid.set_text(0,col,"P(node=" + cast_to_string(col) + ")"); + ppt_grid.set_background_color(0,col,rgb_pixel(150,150,250)); + ppt_grid.set_editable(0,col,false); + } + + // If we have a solution to the network on hand then load the probabilities + // from that into the table + if (solution) + { + // get the probability distribution for the currently selected node out + // of the solution. + const matrix prob = solution->probability(selected_node_index); + + // now load the probabilities into the ppt_grid so the user can see them. + for (unsigned long col = 0; col < node.data.table().num_values(); ++col) + { + ppt_grid.set_text(1,col,cast_to_string(prob(col))); + } + } + + // make the second row of the table non-editable have a color that indicates + // that to the user + for (unsigned long col = 0; col < node.data.table().num_values(); ++col) + { + ppt_grid.set_background_color(1,col,color_gray); + ppt_grid.set_editable(1,col,false); + } +} + +// ---------------------------------------------------------------------------------------- + +void main_window:: +load_selected_node_tables_into_cpt_grid ( +) +{ + // This function just takes the conditional probability table in the + // currently selected graph node and puts it into the cpt_grid widget. + + node_type& node = graph_drawer.graph_node(selected_node_index); + + initialize_node_cpt_if_necessary(selected_node_index); + cpt_grid_assignments.clear(); + + // figure out how many rows there should be in the cpt + unsigned long cpt_rows = 1; + for (unsigned long i = 0; i < node.number_of_parents(); ++i) + { + cpt_rows *= node.parent(i).data.table().num_values(); + } + + unsigned long cpt_cols = node.data.table().num_values(); + + cpt_grid.set_grid_size(cpt_rows+1, cpt_cols+ node.number_of_parents()); + const unsigned long num_cols = cpt_grid.number_of_columns(); + + // fill in the top row of the grid that shows which parent node the left hand columns go with + assignment a(node_first_parent_assignment(graph_drawer.graph(),selected_node_index)); + unsigned long col = 0; + a.reset(); + while (a.move_next()) + { + cpt_grid.set_text(0,col,cast_to_string(a.element().key()) + ": " + graph_drawer.node_label(a.element().key()) ); + cpt_grid.set_background_color(0,col,rgb_pixel(120,210,210)); + cpt_grid.set_editable(0,col,false); + ++col; + } + + // fill in the top row of the grid that shows which probability the right hand columns go with + for (col = node.number_of_parents(); col < num_cols; ++col) + { + cpt_grid.set_text(0,col,"P(node=" + cast_to_string(col-node.number_of_parents()) + ")"); + cpt_grid.set_background_color(0,col,rgb_pixel(150,150,250)); + cpt_grid.set_editable(0,col,false); + } + + // now loop over all the possible parent assignments for this node + const unsigned long num_values = node.data.table().num_values(); + unsigned long row = 1; + do + { + col = 0; + + // fill in the left side of the grid row that shows what the parent assignment is + a.reset(); + while (a.move_next()) + { + cpt_grid.set_text(row,col,cast_to_string(a.element().value())); + cpt_grid.set_background_color(row,col,rgb_pixel(180,255,255)); + cpt_grid.set_editable(row,col,false); + + ++col; + } + + // fill in the right side of the grid row that shows what the conditional probabilities are + for (unsigned long value = 0; value < num_values; ++value) + { + const double prob = node.data.table().probability(value,a); + cpt_grid.set_text(row,col,cast_to_string(prob)); + ++col; + } + + // save this assignment so we can use it later to modify the node's + // conditional probability table if the user modifies the cpt_grid + cpt_grid_assignments.push_back(a); + ++row; + } while (node_next_parent_assignment(graph_drawer.graph(),selected_node_index,a)); + +} + +// ---------------------------------------------------------------------------------------- + +void main_window:: +initialize_node_cpt_if_necessary ( + unsigned long index +) +{ + node_type& node = graph_drawer.graph_node(index); + + // if the cpt for this node isn't properly filled out then let's clear it out + // and populate it with some reasonable default values + if (node_cpt_filled_out(graph_drawer.graph(), index) == false) + { + node.data.table().empty_table(); + + const unsigned long num_values = node.data.table().num_values(); + + // loop over all the possible parent assignments for this node and fill them out + // with reasonable default values + assignment a(node_first_parent_assignment(graph_drawer.graph(), index)); + do + { + // set the first value to have probability 1 + node.data.table().set_probability(0, a, 1.0); + + // set all the other values to have probability 0 + for (unsigned long value = 1; value < num_values; ++value) + node.data.table().set_probability(value, a, 0); + + } while (node_next_parent_assignment(graph_drawer.graph(), index,a)); + } +} + +// ---------------------------------------------------------------------------------------- + +void main_window:: +no_node_selected ( +) +{ + // Make it so that no node is selected on the gui. Do this by disabling things + // and clearing out text fields and so forth. + + + node_is_selected = false; + tables.disable(); + sel_node_evidence.disable(); + sel_node_is_evidence.disable(); + sel_node_index.disable(); + sel_node_evidence_label.disable(); + sel_node_text_label.disable(); + sel_node_text.disable(); + sel_node_index.set_text("index:"); + sel_node_num_values_label.disable(); + sel_node_num_values.disable(); + cpt_grid.set_grid_size(0,0); + ppt_grid.set_grid_size(0,0); + + sel_node_is_evidence.set_unchecked(); + sel_node_text.set_text(""); + sel_node_num_values.set_text(""); + sel_node_evidence.set_text(""); + sel_node_num_values.set_background_color(color_default_bg); + sel_node_evidence.set_background_color(color_default_bg); +} + +// ---------------------------------------------------------------------------------------- + +void main_window:: +recalculate_probabilities ( +) +{ + // clear out the current solution + solution.reset(); + if (graph_is_connected(graph_drawer.graph()) == false) + { + message_box("Error","Your graph has nodes that are completely disconnected from the other nodes.\n" + "You must connect them somehow"); + } + else if (graph_drawer.graph().number_of_nodes() > 0) + { + if (graph_modified_since_last_recalc) + { + // make sure all the cpts are filled out + const unsigned long num_nodes = graph_drawer.graph().number_of_nodes(); + for (unsigned long i = 0; i < num_nodes; ++i) + { + initialize_node_cpt_if_necessary(i); + } + + // remake the join tree for this graph + create_moral_graph(graph_drawer.graph(), join_tree); + create_join_tree(join_tree, join_tree); + graph_modified_since_last_recalc = false; + } + + // create a solution to this bayesian network using the join tree algorithm + solution.reset(new bayesian_network_join_tree(graph_drawer.graph(), join_tree)); + + if (node_is_selected) + { + load_selected_node_tables_into_ppt_grid(); + } + } +} + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// Event handling methods from the main_window object +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + +// This event is called when the user selects a file with a saved +// bayesian network in it. +void main_window:: +on_open_file_selected ( + const std::string& file_name +) +{ + try + { + no_node_selected(); + ifstream fin(file_name.c_str(), ios::binary); + graph_drawer.load_graph(fin); + graph_file_name = file_name; + set_title("Bayesian Network Utility - " + right_substr(file_name,"\\/")); + } + catch (...) + { + message_box("Error", "Unable to load graph file " + file_name); + } +} + +// ---------------------------------------------------------------------------------------- + +// This event is called when the user selects from the menu bar File->Open +void main_window:: +on_menu_file_open ( +) +{ + // display a file chooser window and when the user choses a file + // call the on_open_file_selected() function + open_existing_file_box(*this, &main_window::on_open_file_selected); +} + +// ---------------------------------------------------------------------------------------- + +// This event is called when the user selects from the menu bar File->Save +void main_window:: +on_menu_file_save ( +) +{ + // if we don't currently have any file name associated with our graph + if (graph_file_name.size() == 0) + { + // display a file chooser window and when the user choses a file + // call the on_save_file_selected() function + save_file_box(*this, &main_window::on_save_file_selected); + } + else + { + // we know what file to open so just do that and save the graph to it + ofstream fout(graph_file_name.c_str(), ios::binary); + graph_drawer.save_graph(fout); + } +} + +// ---------------------------------------------------------------------------------------- + +// This event is called when the user choses which file to save the graph to +void main_window:: +on_save_file_selected ( + const std::string& file_name +) +{ + ofstream fout(file_name.c_str(), ios::binary); + graph_drawer.save_graph(fout); + graph_file_name = file_name; + set_title("Bayesian Network Utility - " + right_substr(file_name,"\\/")); +} + +// ---------------------------------------------------------------------------------------- + +// This event is called when the user selects from the menu bar File->Save As +void main_window:: +on_menu_file_save_as ( +) +{ + // display a file chooser window and when the user choses a file + // call the on_save_file_selected() function + save_file_box(*this, &main_window::on_save_file_selected); +} + +// ---------------------------------------------------------------------------------------- + +// This event is called when the user selects from the menu bar File->Quit +void main_window:: +on_menu_file_quit ( +) +{ + close_window(); +} + +// ---------------------------------------------------------------------------------------- + +// This event is called when the user selects from the menu bar Help->Help +void main_window:: +on_menu_help_help ( +) +{ + message_box("Help", + "To create new nodes right click on the drawing area.\n" + "To create edges select the parent node and then shift+left click on the child node.\n" + "To remove nodes or edges select them by left clicking and then press the delete key."); +} + +// ---------------------------------------------------------------------------------------- + +// This event is called when the user selects from the menu bar Help->About +void main_window:: +on_menu_help_about ( +) +{ + message_box("About","This application is the GUI front end to the dlib C++ Library's\n" + "Bayesian Network inference utilities\n\n" + "Version 1.2\n\n" + "See http://dlib.net for updates"); +} + +// ---------------------------------------------------------------------------------------- + +// This event is called when the user modifies the graph_drawer widget. That is, +// when the user adds or removes an edge or node in the graph. +void main_window:: +on_graph_modified ( +) +{ + // make note of the modification + graph_modified_since_last_recalc = true; + // clear out the solution object since we will need to recalculate it + // since the graph changed + solution.reset(); +} + +// ---------------------------------------------------------------------------------------- + +// This event is called when the user modifies the evidence value for a node +void main_window:: +on_sel_node_evidence_modified ( +) +{ + // make a reference to the node in the graph that is currently selected + node_type& node = graph_drawer.graph_node(selected_node_index); + unsigned long value; + try + { + // get the numerical value of the new evidence value. Here we are taking + // the string from the text field and casting it to an unsigned long. + value = sa = trim(sel_node_evidence.text()); + } + catch (string_cast_error&) + { + // if the user put something that isn't an integer into the + // text field then make it have a different background color + // so that they can easily see this. + sel_node_evidence.set_background_color(color_error); + return; + } + + // validate the input from the user and store it in the selected node + // if it is ok + if (value >= node.data.table().num_values()) + { + sel_node_evidence.set_background_color(color_error); + } + else + { + node.data.set_value(value); + sel_node_evidence.set_background_color(color_default_bg); + } + + // clear out the solution to the graph since we now need + // to recalculate it. + solution.reset(); +} + +// ---------------------------------------------------------------------------------------- + +// This event is called when the user modifies the number of evidence values for +// a node. +void main_window:: +on_sel_node_num_values_modified ( +) +{ + // make a reference to the node in the graph that is currently selected + node_type& node = graph_drawer.graph_node(selected_node_index); + + unsigned long num_values; + try + { + // get the number of values out of the text field. + num_values = sa = trim(sel_node_num_values.text()); + } + catch (string_cast_error&) + { + sel_node_num_values.set_background_color(color_error); + return; + } + + // validate the input from the user to make sure it is something reasonable + if (num_values < 2 || num_values > 100) + { + sel_node_num_values.set_background_color(color_error); + } + else + { + // update the graph + node.data.table().set_num_values(num_values); + graph_modified_since_last_recalc = true; + sel_node_num_values.set_background_color(color_default_bg); + + on_sel_node_evidence_modified(); + // also make sure the evidence value of this node makes sense still + if (node.data.is_evidence() && node.data.value() >= num_values) + { + // just set it to zero + node.data.set_value(0); + } + + } + + solution.reset(); + + // call these functions so that the conditional and posterior probability + // tables get updated + load_selected_node_tables_into_cpt_grid(); + load_selected_node_tables_into_ppt_grid(); +} + +// ---------------------------------------------------------------------------------------- + +// This event is called when the user modifies the cpt_grid (i.e. the conditional +// probability table widget) +void main_window:: +on_cpt_grid_modified(unsigned long row, unsigned long col) +{ + node_type& node = graph_drawer.graph_node(selected_node_index); + solution.reset(); + + double prob; + try + { + // get the new value out of the table + prob = sa = cpt_grid.text(row,col); + } + catch (string_cast_error&) + { + cpt_grid.set_background_color(row,col,color_error); + return; + } + + // validate the value + if (prob < 0 || prob > 1) + { + cpt_grid.set_background_color(row,col,color_error); + return; + } + + // the value of this node that is having its conditional probability + // updated + const unsigned long cur_val = col-node.number_of_parents(); + + node.data.table().set_probability(cur_val, cpt_grid_assignments[row-1], prob); + + // sum the probabilities in the cpt and modify the last one such that they all + // sum to 1. We are excluding either the first or last element from the sum + // because we are going to set it equal to 1-sum below. + double sum = 0; + if (cur_val != node.data.table().num_values()-1) + { + for (unsigned long i = 0; i < node.data.table().num_values()-1; ++i) + sum += node.data.table().probability(i, cpt_grid_assignments[row-1]); + } + else + { + for (unsigned long i = 1; i < node.data.table().num_values(); ++i) + sum += node.data.table().probability(i, cpt_grid_assignments[row-1]); + } + + // make sure all the probabilities sum to 1 + if (sum > 1.0) + { + cpt_grid.set_background_color(row,cpt_grid.number_of_columns()-1,color_error); + } + else + { + // edit one of the other elements in the table to ensure that the probabilities still sum to 1 + if (cur_val == node.data.table().num_values()-1) + { + node.data.table().set_probability(0, cpt_grid_assignments[row-1], 1-sum); + cpt_grid.set_text(row,node.number_of_parents(),cast_to_string(1-sum)); + } + else + { + node.data.table().set_probability(node.data.table().num_values()-1, cpt_grid_assignments[row-1], 1-sum); + cpt_grid.set_text(row,cpt_grid.number_of_columns()-1,cast_to_string(1-sum)); + } + + cpt_grid.set_background_color(row,cpt_grid.number_of_columns()-1,color_default_bg); + cpt_grid.set_background_color(row,col,color_default_bg); + } + +} + +// ---------------------------------------------------------------------------------------- + +// This event is called when the user resizes the main_window. Note that unlike the other +// events, this event is part of the drawable_window base class that main_window inherits from. +// So you won't see any statements in the constructor that say "register the main_window::on_window_resized function" +void main_window:: +on_window_resized () +{ + // when you override any of the drawable_window events you have to make sure you + // call the drawable_window's version of them because it needs to process + // the events as well. So we do that here. + drawable_window::on_window_resized(); + + // The rest of this function positions the widgets on the window + unsigned long width,height; + get_size(width,height); + + // Don't do anything if the user just made the window too small. That is, leave + // the widgets where they are. + if (width < 500 || height < 350) + return; + + // Set the size of the probability tables and the drawing area for the graph + graph_drawer.set_size(width-370,height-10-mbar.height()); + cpt_grid.set_size((width-graph_drawer.width())-35,height-237); + ppt_grid.set_size((width-graph_drawer.width())-35,height-237); + // tell the tabbed display to make itself just the right size to contain + // the two probability tables. + tables.fit_to_contents(); + + + // Now position all the widgets in the window. Note that much of the positioning + // is relative to other widgets. This part of the code I just figured out by + // trying stuff and rerunning the program to see if it looked nice. + sel_node_index.set_pos(graph_drawer.right()+14,graph_drawer.top()+18); + sel_node_text_label.set_pos(sel_node_index.left(),sel_node_index.bottom()+5); + sel_node_text.set_pos(sel_node_text_label.right()+5,sel_node_index.bottom()); + sel_node_num_values_label.set_pos(sel_node_index.left(), sel_node_text.bottom()+5); + sel_node_num_values.set_pos(sel_node_num_values_label.right(), sel_node_text.bottom()+5); + sel_node_is_evidence.set_pos(sel_node_index.left(),sel_node_num_values.bottom()+5); + sel_node_evidence_label.set_pos(sel_node_index.left(),sel_node_is_evidence.bottom()+5); + sel_node_evidence.set_pos(sel_node_evidence_label.right()+5,sel_node_is_evidence.bottom()); + tables.set_pos(sel_node_index.left(),sel_node_evidence.bottom()+5); + sel_node_evidence.set_width(tables.right()-sel_node_evidence.left()+1); + sel_node_text.set_width(tables.right()-sel_node_text.left()+1); + sel_node_num_values.set_width(tables.right()-sel_node_num_values.left()+1); + + + + // Tell the named rectangle to position itself such that it fits around the + // tabbed display that contains the probability tables and the label at the top of the + // screen. + selected_node_rect.wrap_around(sel_node_index.get_rect()+ + tables.get_rect()); + + // finally set the button to be at the bottom of the named rectangle + btn_calculate.set_pos(selected_node_rect.left(), selected_node_rect.bottom()+5); +} + +// ---------------------------------------------------------------------------------------- + +// This event is called by the graph_drawer widget when the user selects a node +void main_window:: +on_node_selected (unsigned long n) +{ + // make a reference to the selected node + node_type& node = graph_drawer.graph_node(n); + + + // enable all the widgets related to the selected node + selected_node_index = n; + node_is_selected = true; + tables.enable(); + sel_node_is_evidence.enable(); + sel_node_index.enable(); + sel_node_evidence_label.enable(); + sel_node_text_label.enable(); + sel_node_text.enable(); + sel_node_num_values_label.enable(); + sel_node_num_values.enable(); + + // make sure the num_values field of the node's cpt is set to something valid. + // So default it to 2 if it isn't set already. + if (node.data.table().num_values() < 2) + { + node.data.table().set_num_values(2); + graph_modified_since_last_recalc = true; + } + + // setup the evidence check box and input field + sel_node_index.set_text("index: " + cast_to_string(n)); + if (graph_drawer.graph_node(n).data.is_evidence()) + { + sel_node_is_evidence.set_checked(); + sel_node_evidence.enable(); + sel_node_evidence.set_text(cast_to_string(graph_drawer.graph_node(n).data.value())); + } + else + { + sel_node_is_evidence.set_unchecked(); + sel_node_evidence.disable(); + sel_node_evidence.set_text(""); + } + + sel_node_num_values.set_text(cast_to_string(node_num_values(graph_drawer.graph(),n))); + + sel_node_text.set_text(graph_drawer.node_label(n)); + + load_selected_node_tables_into_cpt_grid(); + load_selected_node_tables_into_ppt_grid(); +} + +// ---------------------------------------------------------------------------------------- + +// This event is called when the user toggles the "is evidence" check box +void main_window:: +on_evidence_toggled ( +) +{ + if (sel_node_is_evidence.is_checked()) + { + graph_drawer.graph_node(selected_node_index).data.set_as_evidence(); + sel_node_evidence.enable(); + sel_node_evidence.set_text(cast_to_string(graph_drawer.graph_node(selected_node_index).data.value())); + + graph_drawer.set_node_color(selected_node_index, color_evidence); + } + else + { + graph_drawer.graph_node(selected_node_index).data.set_as_nonevidence(); + sel_node_evidence.disable(); + sel_node_evidence.set_text(""); + sel_node_evidence.set_background_color(color_default_bg); + graph_drawer.set_node_color(selected_node_index, color_non_evidence); + } + solution.reset(); +} + +// ---------------------------------------------------------------------------------------- + +// This event is called when the user causes no node to be selected +void main_window:: +on_node_deselected ( unsigned long ) +{ + no_node_selected(); +} + +// ---------------------------------------------------------------------------------------- + +// This event is called when the user causes a node to be deleted +void main_window:: +on_node_deleted ( ) +{ + no_node_selected(); +} + +// ---------------------------------------------------------------------------------------- + +// This event is called when the user changes the text in the "node label" text field +void main_window:: +on_sel_node_text_modified ( +) +{ + // set the selected node's text to match whatever the user just typed in + graph_drawer.set_node_label(selected_node_index,sel_node_text.text()); +} + +// ---------------------------------------------------------------------------------------- + diff --git a/ml/dlib/examples/bridge_ex.cpp b/ml/dlib/examples/bridge_ex.cpp new file mode 100644 index 000000000..bc772ccbb --- /dev/null +++ b/ml/dlib/examples/bridge_ex.cpp @@ -0,0 +1,365 @@ +// The contents of this file are in the public domain. See LICENSE_FOR_EXAMPLE_PROGRAMS.txt + + +/* + This is an example showing how to use the bridge object from from the + dlib C++ Library to send messages via TCP/IP. + + In particular, this example will walk you through four progressively + more complex use cases of the bridge object. Note that this example + program assumes you are already familiar with the pipe object and at + least the contents of the pipe_ex_2.cpp example program. +*/ + + +// =========== Example program output =========== +/* + ---- Running example 1 ---- + dequeued value: 1 + dequeued value: 2 + dequeued value: 3 + + ---- Running example 2 ---- + dequeued value: 1 + dequeued value: 2 + dequeued value: 3 + + ---- Running example 3 ---- + dequeued int: 1 + dequeued int: 2 + dequeued struct: 3 some string + + ---- Running example 4 ---- + bridge 1 status: is_connected: true + bridge 1 status: foreign_ip: 127.0.0.1 + bridge 1 status: foreign_port: 43156 + bridge 2 status: is_connected: true + bridge 2 status: foreign_ip: 127.0.0.1 + bridge 2 status: foreign_port: 12345 + dequeued int: 1 + dequeued int: 2 + dequeued struct: 3 some string + bridge 1 status: is_connected: false + bridge 1 status: foreign_ip: 127.0.0.1 + bridge 1 status: foreign_port: 12345 +*/ + + +#include +#include +#include + +using namespace dlib; +using namespace std; + +// ---------------------------------------------------------------------------------------- + +void run_example_1(); +void run_example_2(); +void run_example_3(); +void run_example_4(); + +// ---------------------------------------------------------------------------------------- + +int main() +{ + run_example_1(); + run_example_2(); + run_example_3(); + run_example_4(); +} + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + +void run_example_1( +) +{ + cout << "\n ---- Running example 1 ---- " << endl; + + /* + The idea of the bridge is basically to allow two different dlib::pipe objects + to be connected together via a TCP connection. This is best illustrated by + the following short example. In it we create two pipes, in and out. When + an object is enqueued into the out pipe it will be automatically sent + through a TCP connection and once received at the other end it will be + inserted into the in pipe. + */ + dlib::pipe in(4), out(4); + + + // This bridge will listen on port 12345 for an incoming TCP connection. Then + // it will read data from that connection and put it into the in pipe. + bridge b2(listen_on_port(12345), receive(in)); + + // This bridge will initiate a TCP connection and then start dequeuing + // objects from out and transmitting them over the connection. + bridge b1(connect_to_ip_and_port("127.0.0.1", 12345), transmit(out)); + + // As an aside, in a real program, each of these bridges and pipes would be in a + // separate application. But to make this example self contained they are both + // right here. + + + + // Now let's put some things into the out pipe + int value = 1; + out.enqueue(value); + + value = 2; + out.enqueue(value); + + value = 3; + out.enqueue(value); + + + // Now those 3 ints can be dequeued from the in pipe. They will show up + // in the same order they were inserted into the out pipe. + in.dequeue(value); + cout << "dequeued value: "<< value << endl; + in.dequeue(value); + cout << "dequeued value: "<< value << endl; + in.dequeue(value); + cout << "dequeued value: "<< value << endl; +} + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + +void run_example_2( +) +{ + cout << "\n ---- Running example 2 ---- " << endl; + + /* + This example makes a simple echo server on port 12345. When an object + is inserted into the out pipe it will be sent over a TCP connection, get + put into the echo pipe and then immediately read out of the echo pipe and + sent back over the TCP connection where it will finally be placed into the in + pipe. + */ + + dlib::pipe in(4), out(4), echo(4); + + // Just like TCP connections, a bridge can send data both directions. The directionality + // of a pipe is indicated by the receive() and transmit() type decorations. Also, the order + // they are listed doesn't matter. + bridge echo_bridge(listen_on_port(12345), receive(echo), transmit(echo)); + + // Note that you can also specify the ip and port as a string by using connect_to(). + bridge b1(connect_to("127.0.0.1:12345"), transmit(out), receive(in)); + + + int value = 1; + out.enqueue(value); + + value = 2; + out.enqueue(value); + + value = 3; + out.enqueue(value); + + + in.dequeue(value); + cout << "dequeued value: "<< value << endl; + in.dequeue(value); + cout << "dequeued value: "<< value << endl; + in.dequeue(value); + cout << "dequeued value: "<< value << endl; +} + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + +struct my_example_object +{ + /* + All objects passing through a dlib::bridge must be serializable. This + means there must exist global functions called serialize() and deserialize() + which can convert an object into a bit stream and then reverse the process. + + This example object illustrates how this is done. + */ + + int value; + std::string str; +}; + +void serialize (const my_example_object& item, std::ostream& out) +{ + /* + serialize() just needs to write the state of item to the output stream. + You can do this however you like. Below, I'm using the serialize functions + for int and std::string which come with dlib. But again, you can do whatever + you want here. + */ + dlib::serialize(item.value, out); + dlib::serialize(item.str, out); +} + +void deserialize (my_example_object& item, std::istream& in) +{ + /* + deserialize() is just the inverse of serialize(). Again, you can do + whatever you want here so long as it correctly reconstructs item. This + also means that deserialize() must always consume as many bytes as serialize() + generates. + */ + dlib::deserialize(item.value, in); + dlib::deserialize(item.str, in); +} + +// ---------------------------------------------------------------------------------------- + +void run_example_3( +) +{ + cout << "\n ---- Running example 3 ---- " << endl; + + /* + In this example we will just send ints and my_example_object objects + over a TCP connection. Since we are sending more than one type of + object through a pipe we will need to use the type_safe_union. + */ + + typedef type_safe_union tsu_type; + + dlib::pipe in(4), out(4); + + // Note that we don't have to start the listening bridge first. If b2 + // fails to make a connection it will just keep trying until successful. + bridge b2(connect_to("127.0.0.1:12345"), receive(in)); + // We don't have to configure a bridge in it's constructor. If it's + // more convenient we can do so by calling reconfigure() instead. + bridge b1; + b1.reconfigure(listen_on_port(12345), transmit(out)); + + tsu_type msg; + + msg = 1; + out.enqueue(msg); + + msg = 2; + out.enqueue(msg); + + msg.get().value = 3; + msg.get().str = "some string"; + out.enqueue(msg); + + + // dequeue the three objects we sent and print them on the screen. + for (int i = 0; i < 3; ++i) + { + in.dequeue(msg); + if (msg.contains()) + { + cout << "dequeued int: "<< msg.get() << endl; + } + else if (msg.contains()) + { + cout << "dequeued struct: "<< msg.get().value << " " + << msg.get().str << endl; + } + } +} + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + +void run_example_4( +) +{ + cout << "\n ---- Running example 4 ---- " << endl; + + /* + This final example is the same as example 3 except we will also now be getting + status messages from the bridges. These bridge_status messages tell us the + state of the TCP connection associated with a bridge. Is it connected or not? + Who it is connected to? + + The way you get these status messages is by ensuring that your receive pipe is + capable of storing bridge_status objects. If it is then the bridge will + automatically insert bridge_status messages into your receive pipe whenever + there is a status change. + + There are only two kinds of status changes. The establishment of a connection + or the closing of a connection. Also, a connection which closes due to you + calling clear(), reconfigure(), or destructing a bridge does not generate a + status message since, in this case, you already know about it and just want + the bridge to destroy itself as quickly as possible. + */ + + + typedef type_safe_union tsu_type; + + dlib::pipe in(4), out(4); + dlib::pipe b1_status(4); + + // setup both bridges to have receive pipes capable of holding bridge_status messages. + bridge b1(listen_on_port(12345), transmit(out), receive(b1_status)); + // Note that we can also use a hostname with connect_to() instead of supplying an IP address. + bridge b2(connect_to("localhost:12345"), receive(in)); + + tsu_type msg; + bridge_status bs; + + // Once a connection is established it will generate a status message from each bridge. + // Let's get those and print them. + b1_status.dequeue(bs); + cout << "bridge 1 status: is_connected: " << boolalpha << bs.is_connected << endl; + cout << "bridge 1 status: foreign_ip: " << bs.foreign_ip << endl; + cout << "bridge 1 status: foreign_port: " << bs.foreign_port << endl; + + in.dequeue(msg); + bs = msg.get(); + cout << "bridge 2 status: is_connected: " << bs.is_connected << endl; + cout << "bridge 2 status: foreign_ip: " << bs.foreign_ip << endl; + cout << "bridge 2 status: foreign_port: " << bs.foreign_port << endl; + + + + msg = 1; + out.enqueue(msg); + + msg = 2; + out.enqueue(msg); + + msg.get().value = 3; + msg.get().str = "some string"; + out.enqueue(msg); + + + // Read the 3 things we sent over the connection. + for (int i = 0; i < 3; ++i) + { + in.dequeue(msg); + if (msg.contains()) + { + cout << "dequeued int: "<< msg.get() << endl; + } + else if (msg.contains()) + { + cout << "dequeued struct: "<< msg.get().value << " " + << msg.get().str << endl; + } + } + + // cause bridge 1 to shutdown completely. This will close the connection and + // therefore bridge 2 will generate a status message indicating the connection + // just closed. + b1.clear(); + in.dequeue(msg); + bs = msg.get(); + cout << "bridge 1 status: is_connected: " << bs.is_connected << endl; + cout << "bridge 1 status: foreign_ip: " << bs.foreign_ip << endl; + cout << "bridge 1 status: foreign_port: " << bs.foreign_port << endl; +} + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + diff --git a/ml/dlib/examples/bsp_ex.cpp b/ml/dlib/examples/bsp_ex.cpp new file mode 100644 index 000000000..7dffa68d6 --- /dev/null +++ b/ml/dlib/examples/bsp_ex.cpp @@ -0,0 +1,282 @@ +// The contents of this file are in the public domain. See LICENSE_FOR_EXAMPLE_PROGRAMS.txt +/* + + This is an example illustrating the use of the Bulk Synchronous Parallel (BSP) + processing tools from the dlib C++ Library. These tools allow you to easily setup a + number of processes running on different computers which cooperate to compute some + result. + + In this example, we will use the BSP tools to find the minimizer of a simple function. + In particular, we will setup a nested grid search where different parts of the grid are + searched in parallel by different processes. + + + To run this program you should do the following (supposing you want to use three BSP + nodes to do the grid search and, to make things easy, you will run them all on your + current computer): + + 1. Open three command windows and navigate each to the folder containing the + compiled bsp_ex.cpp program. Let's call these window 1, window 2, and window 3. + + 2. In window 1 execute this command: + ./bsp_ex -l12345 + This will start a listening BSP node that listens on port 12345. The BSP node + won't do anything until we tell all the nodes to start running in step 4 below. + + 3. In window 2 execute this command: + ./bsp_ex -l12346 + This starts another listening BSP node. Note that since we are running this + example all on one computer you need to use different listening port numbers + for each listening node. + + 4. In window 3 execute this command: + ./bsp_ex localhost:12345 localhost:12346 + This will start a BSP node that connects to the others and gets them all running. + Additionally, as you will see when we go over the code below, it will also print + the final output of the BSP process, which is the minimizer of our test function. + Once it terminates, all the other BSP nodes will also automatically terminate. +*/ + + + + + +#include +#include +#include + +#include + +using namespace std; +using namespace dlib; + +// ---------------------------------------------------------------------------------------- + +// These are the functions executed by the BSP nodes. They are defined below. +void bsp_job_node_0 (bsp_context& bsp, double& min_value, double& optimal_x); +void bsp_job_other_nodes (bsp_context& bsp, long grid_resolution); + +// ---------------------------------------------------------------------------------------- + +int main(int argc, char** argv) +{ + try + { + // Use the dlib command_line_parser to parse the command line. See the + // compress_stream_ex.cpp example program for an introduction to the command line + // parser. + command_line_parser parser; + parser.add_option("h","Display this help message."); + parser.add_option("l","Run as a listening BSP node.",1); + parser.parse(argc, argv); + parser.check_option_arg_range("l", 1, 65535); + + + // Print a help message if the user gives -h on the command line. + if (parser.option("h")) + { + // display all the command line options + cout << "Usage: bsp_ex (-l port | )\n"; + parser.print_options(); + return 0; + } + + + // If the command line contained -l + if (parser.option("l")) + { + // Get the argument to -l + const unsigned short listening_port = get_option(parser, "l", 0); + cout << "Listening on port " << listening_port << endl; + + const long grid_resolution = 100; + + // bsp_listen() starts a listening BSP job. This means that it will wait until + // someone calls bsp_connect() and connects to it before it starts running. + // However, once it starts it will call bsp_job_other_nodes() which will then + // do all the real work. + // + // The first argument is the port to listen on. The second argument is the + // function which it should run to do all the work. The other arguments are + // optional and allow you to pass values into the bsp_job_other_nodes() + // routine. In this case, we are passing the grid_resolution to + // bsp_job_other_nodes(). + bsp_listen(listening_port, bsp_job_other_nodes, grid_resolution); + } + else + { + if (parser.number_of_arguments() == 0) + { + cout << "You must give some listening BSP nodes as arguments to this program!" << endl; + return 0; + } + + // Take the hostname:port strings from the command line and put them into the + // vector of hosts. + std::vector hosts; + for (unsigned long i = 0; i < parser.number_of_arguments(); ++i) + hosts.push_back(parser[i]); + + double min_value, optimal_x; + + // Calling bsp_connect() does two things. First, it tells all the BSP jobs + // listed in the hosts vector to start running. Second, it starts a locally + // running BSP job that executes bsp_job_node_0() and passes it any arguments + // listed after bsp_job_node_0. So in this case it passes it the 3rd and 4th + // arguments. + // + // Note also that we use dlib::ref() which causes these arguments to be passed + // by reference. This means that bsp_job_node_0() will be able to modify them + // and we will see the results here in main() after bsp_connect() terminates. + bsp_connect(hosts, bsp_job_node_0, dlib::ref(min_value), dlib::ref(optimal_x)); + + // bsp_connect() and bsp_listen() block until all the BSP nodes have terminated. + // Therefore, we won't get to this part of the code until the BSP processing + // has finished. But once we do we can print the results like so: + cout << "optimal_x: "<< optimal_x << endl; + cout << "min_value: "<< min_value << endl; + } + + } + catch (std::exception& e) + { + cout << "error in main(): " << e.what() << endl; + } +} + +// ---------------------------------------------------------------------------------------- + +/* + We are going to use the BSP tools to find the minimum of f(x). Note that + it's minimizer is at x == 2.0. +*/ +double f (double x) +{ + return std::pow(x-2.0, 2.0); +} + +// ---------------------------------------------------------------------------------------- + +void bsp_job_node_0 (bsp_context& bsp, double& min_value, double& optimal_x) +{ + // This function is called by bsp_connect(). In general, any BSP node can do anything + // you want. However, in this example we use this node as a kind of controller for the + // other nodes. In particular, since we are doing a nested grid search, this node's + // job will be to collect results from other nodes and then decide which part of the + // number line subsequent iterations should focus on. + // + // Also, each BSP node has a node ID number. You can determine it by calling + // bsp.node_id(). However, the node spawned by a call to bsp_connect() always has a + // node ID of 0 (hence the name of this function). Additionally, all functions + // executing a BSP task always take a bsp_context as their first argument. This object + // is the interface that allows BSP jobs to communicate with each other. + + + // Now let's get down to work. Recall that we are trying to find the x value that + // minimizes the f(x) defined above. The grid search will start out by considering the + // range [-1e100, 1e100] on the number line. It will progressively narrow this window + // until it has located the minimizer of f(x) to within 1e-15 of its true value. + double left = -1e100; + double right = 1e100; + + min_value = std::numeric_limits::infinity(); + double interval_width = std::abs(right-left); + + // keep going until the window is smaller than 1e-15. + while (right-left > 1e-15) + { + // At the start of each loop, we broadcast the current window to all the other BSP + // nodes. They will each search a separate part of the window and then report back + // the smallest values they found in their respective sub-windows. + // + // Also, you can send/broadcast/receive anything that has global serialize() and + // deserialize() routines defined for it. Dlib comes with serialization functions + // for a lot of types by default, so we don't have to define anything for this + // example program. However, if you want to send an object you defined then you + // will need to write your own serialization functions. See the documentation for + // dlib's serialize() routine or the bridge_ex.cpp example program for an example. + bsp.broadcast(left); + bsp.broadcast(right); + + // Receive the smallest values found from the other BSP nodes. + for (unsigned int k = 1; k < bsp.number_of_nodes(); ++k) + { + // The other nodes will send std::pairs of x/f(x) values. So that is what we + // receive. + std::pair val; + bsp.receive(val); + // save the smallest result. + if (val.second < min_value) + { + min_value = val.second; + optimal_x = val.first; + } + } + + // Now narrow the search window by half. + interval_width *= 0.5; + left = optimal_x - interval_width/2; + right = optimal_x + interval_width/2; + } +} + +// ---------------------------------------------------------------------------------------- + +void bsp_job_other_nodes (bsp_context& bsp, long grid_resolution) +{ + // This is the BSP job called by bsp_listen(). In these jobs we will receive window + // ranges from the controller node, search our sub-window, and then report back the + // location of the best x value we found. + + double left, right; + + // The try_receive() function will either return true with the next message or return + // false if there aren't any more messages in flight between nodes and all other BSP + // nodes are blocked on calls to receive or have terminated. That is, try_receive() + // only returns false if waiting for a message would result in all the BSP nodes + // waiting forever. + // + // Therefore, try_receive() serves both as a message receiving tool as well as an + // implicit form of barrier synchronization. In this case, we use it to know when to + // terminate. That is, we know it is time to terminate if all the messages between + // nodes have been received and all nodes are inactive due to either termination or + // being blocked on a receive call. This will happen once the controller node above + // terminates since it will result in all the other nodes inevitably becoming blocked + // on this try_receive() line with no messages to process. + while (bsp.try_receive(left)) + { + bsp.receive(right); + + // Compute a sub-window range for us to search. We use our node's ID value and the + // total number of nodes to select a subset of the [left, right] window. We will + // store the grid points from our sub-window in values_to_check. + const double l = (bsp.node_id()-1)/(bsp.number_of_nodes()-1.0); + const double r = bsp.node_id() /(bsp.number_of_nodes()-1.0); + const double width = right-left; + // Select grid_resolution number of points which are linearly spaced throughout our + // sub-window. + const matrix values_to_check = linspace(left+l*width, left+r*width, grid_resolution); + + // Search all the points in values_to_check and figure out which one gives the + // minimum value of f(). + double best_x = 0; + double best_val = std::numeric_limits::infinity(); + for (long j = 0; j < values_to_check.size(); ++j) + { + double temp = f(values_to_check(j)); + if (temp < best_val) + { + best_val = temp; + best_x = values_to_check(j); + } + } + + // Report back the identity of the best point we found in our sub-window. Note + // that the second argument to send(), the 0, is the node ID to send to. In this + // case we send our results back to the controller node. + bsp.send(make_pair(best_x, best_val), 0); + } +} + +// ---------------------------------------------------------------------------------------- + diff --git a/ml/dlib/examples/compress_stream_ex.cpp b/ml/dlib/examples/compress_stream_ex.cpp new file mode 100644 index 000000000..502400e5e --- /dev/null +++ b/ml/dlib/examples/compress_stream_ex.cpp @@ -0,0 +1,245 @@ +// The contents of this file are in the public domain. See LICENSE_FOR_EXAMPLE_PROGRAMS.txt +/* + + This is an example illustrating the use of the compress_stream and + cmd_line_parser components from the dlib C++ Library. + + This example implements a simple command line compression utility. + + + The output from the program when the -h option is given is: + + Usage: compress_stream_ex (-c|-d|-l) --in input_file --out output_file + Options: + -c Indicates that we want to compress a file. + -d Indicates that we want to decompress a file. + --in This option takes one argument which specifies the name of the + file we want to compress/decompress. + --out This option takes one argument which specifies the name of the + output file. + + Miscellaneous Options: + -h Display this help message. + -l Set the compression level [1-3], 3 is max compression, default + is 2. + +*/ + + + + +#include +#include +#include +#include +#include + +// I am making a typedefs for the versions of compress_stream I want to use. +typedef dlib::compress_stream::kernel_1da cs1; +typedef dlib::compress_stream::kernel_1ea cs2; +typedef dlib::compress_stream::kernel_1ec cs3; + + +using namespace std; +using namespace dlib; + + +int main(int argc, char** argv) +{ + try + { + command_line_parser parser; + + // first I will define the command line options I want. + // Add a -c option and tell the parser what the option is for. + parser.add_option("c","Indicates that we want to compress a file."); + parser.add_option("d","Indicates that we want to decompress a file."); + // add a --in option that takes 1 argument + parser.add_option("in","This option takes one argument which specifies the name of the file we want to compress/decompress.",1); + // add a --out option that takes 1 argument + parser.add_option("out","This option takes one argument which specifies the name of the output file.",1); + // In the code below, we use the parser.print_options() method to print all our + // options to the screen. We can tell it that we would like some options to be + // grouped together by calling set_group_name() before adding those options. In + // general, you can make as many groups as you like by calling set_group_name(). + // However, here we make only one named group. + parser.set_group_name("Miscellaneous Options"); + parser.add_option("h","Display this help message."); + parser.add_option("l","Set the compression level [1-3], 3 is max compression, default is 2.",1); + + + // now I will parse the command line + parser.parse(argc,argv); + + + // Now I will use the parser to validate some things about the command line. + // If any of the following checks fail then an exception will be thrown and it will + // contain a message that tells the user what the problem was. + + // First I want to check that none of the options were given on the command line + // more than once. To do this I define an array that contains the options + // that shouldn't appear more than once and then I just call check_one_time_options() + const char* one_time_opts[] = {"c", "d", "in", "out", "h", "l"}; + parser.check_one_time_options(one_time_opts); + // Here I'm checking that the user didn't pick both the c and d options at the + // same time. + parser.check_incompatible_options("c", "d"); + + // Here I'm checking that the argument to the l option is an integer in the range 1 to 3. + // That is, it should be convertible to an int by dlib::string_assign and be either + // 1, 2, or 3. Note that if you wanted to allow floating point values in the range 1 to + // 3 then you could give a range 1.0 to 3.0 or explicitly supply a type of float or double + // to the template argument of the check_option_arg_range() function. + parser.check_option_arg_range("l", 1, 3); + + // The 'l' option is a sub-option of the 'c' option. That is, you can only select the + // compression level when compressing. This command below checks that the listed + // sub options are always given in the presence of their parent options. + const char* c_sub_opts[] = {"l"}; + parser.check_sub_options("c", c_sub_opts); + + // check if the -h option was given on the command line + if (parser.option("h")) + { + // display all the command line options + cout << "Usage: compress_stream_ex (-c|-d|-l) --in input_file --out output_file\n"; + // This function prints out a nicely formatted list of + // all the options the parser has + parser.print_options(); + return 0; + } + + // Figure out what the compression level should be. If the user didn't supply + // this command line option then a value of 2 will be used. + int compression_level = get_option(parser,"l",2); + + + // make sure one of the c or d options was given + if (!parser.option("c") && !parser.option("d")) + { + cout << "Error in command line:\n You must specify either the c option or the d option.\n"; + cout << "\nTry the -h option for more information." << endl; + return 0; + } + + + string in_file; + string out_file; + + // check if the user told us the input file and if they did then + // get the file name + if (parser.option("in")) + { + in_file = parser.option("in").argument(); + } + else + { + cout << "Error in command line:\n You must specify an input file.\n"; + cout << "\nTry the -h option for more information." << endl; + return 0; + } + + + // check if the user told us the output file and if they did then + // get the file name + if (parser.option("out")) + { + out_file = parser.option("out").argument(); + } + else + { + cout << "Error in command line:\n You must specify an output file.\n"; + cout << "\nTry the -h option for more information." << endl; + return 0; + } + + + // open the files we will be reading from and writing to + ifstream fin(in_file.c_str(),ios::binary); + ofstream fout(out_file.c_str(),ios::binary); + + // make sure the files opened correctly + if (!fin) + { + cout << "Error opening file " << in_file << ".\n"; + return 0; + } + + if (!fout) + { + cout << "Error creating file " << out_file << ".\n"; + return 0; + } + + + + // now perform the actual compression or decompression. + if (parser.option("c")) + { + // save the compression level to the output file + serialize(compression_level, fout); + + switch (compression_level) + { + case 1: + { + cs1 compressor; + compressor.compress(fin,fout); + }break; + case 2: + { + cs2 compressor; + compressor.compress(fin,fout); + }break; + case 3: + { + cs3 compressor; + compressor.compress(fin,fout); + }break; + } + } + else + { + // obtain the compression level from the input file + deserialize(compression_level, fin); + + switch (compression_level) + { + case 1: + { + cs1 compressor; + compressor.decompress(fin,fout); + }break; + case 2: + { + cs2 compressor; + compressor.decompress(fin,fout); + }break; + case 3: + { + cs3 compressor; + compressor.decompress(fin,fout); + }break; + default: + { + cout << "Error in compressed file, invalid compression level" << endl; + }break; + } + } + + + + + } + catch (exception& e) + { + // Note that this will catch any cmd_line_parse_error exceptions and print + // the default message. + cout << e.what() << endl; + } +} + + + + + diff --git a/ml/dlib/examples/config.txt b/ml/dlib/examples/config.txt new file mode 100644 index 000000000..da21d170c --- /dev/null +++ b/ml/dlib/examples/config.txt @@ -0,0 +1,30 @@ +# This is an example config file. Note that # is used to create a comment. + +# At its most basic level a config file is just a bunch of key/value pairs. +# So for example: +key1 = value2 +dlib = a C++ library + +# You can also define "sub blocks" in your config files like so +user1 +{ + # Inside a sub block you can list more key/value pairs. + id = 42 + name = davis + + # you can also nest sub-blocks as deep as you want + details + { + editor = vim + home_dir = /home/davis + } +} +user2 { + id = 1234 + name = joe + details { + editor = emacs + home_dir = /home/joe + } +} + diff --git a/ml/dlib/examples/config_reader_ex.cpp b/ml/dlib/examples/config_reader_ex.cpp new file mode 100644 index 000000000..02ad1cc68 --- /dev/null +++ b/ml/dlib/examples/config_reader_ex.cpp @@ -0,0 +1,146 @@ +// The contents of this file are in the public domain. See LICENSE_FOR_EXAMPLE_PROGRAMS.txt +/* + + This is an example illustrating the use of the config_reader component + from the dlib C++ Library. + + This example uses the config_reader to load a config file and then + prints out the values of various fields in the file. +*/ + + +#include +#include +#include +#include + + +using namespace std; +using namespace dlib; + +// ---------------------------------------------------------------------------------------- +// For reference, the contents of the config file used in this example is reproduced below: +/* + +# This is an example config file. Note that # is used to create a comment. + +# At its most basic level a config file is just a bunch of key/value pairs. +# So for example: +key1 = value2 +dlib = a C++ library + +# You can also define "sub blocks" in your config files like so +user1 +{ + # Inside a sub block you can list more key/value pairs. + id = 42 + name = davis + + # you can also nest sub-blocks as deep as you want + details + { + editor = vim + home_dir = /home/davis + } +} +user2 { + id = 1234 + name = joe + details { + editor = emacs + home_dir = /home/joe + } +} + +*/ +// ---------------------------------------------------------------------------------------- + +void print_config_reader_contents ( + const config_reader& cr, + int depth = 0 +); +/* + This is a simple function that recursively walks through everything in + a config reader and prints it to the screen. +*/ + +// ---------------------------------------------------------------------------------------- + +int main() +{ + try + { + config_reader cr("config.txt"); + + // Use our recursive function to print everything in the config file. + print_config_reader_contents(cr); + + // Now let's access some of the fields of the config file directly. You + // use [] for accessing key values and .block() for accessing sub-blocks. + + // Print out the string value assigned to key1 in the config file + cout << cr["key1"] << endl; + + // Print out the name field inside the user1 sub-block + cout << cr.block("user1")["name"] << endl; + // Now print out the editor field in the details block + cout << cr.block("user1").block("details")["editor"] << endl; + + + // Note that you can use get_option() to easily convert fields into + // non-string types. For example, the config file has an integer id + // field that can be converted into an int like so: + int id1 = get_option(cr,"user1.id",0); + int id2 = get_option(cr,"user2.id",0); + cout << "user1's id is " << id1 << endl; + cout << "user2's id is " << id2 << endl; + // The third argument to get_option() is the default value returned if + // the config reader doesn't contain a corresponding entry. So for + // example, the following prints 321 since there is no user3. + int id3 = get_option(cr,"user3.id",321); + cout << "user3's id is " << id3 << endl; + + } + catch (exception& e) + { + // Finally, note that the config_reader throws exceptions if the config + // file is corrupted or if you ask it for a key or block that doesn't exist. + // Here we print out any such error messages. + cout << e.what() << endl; + } +} + +// ---------------------------------------------------------------------------------------- + +void print_config_reader_contents ( + const config_reader& cr, + int depth +) +{ + // Make a string with depth*4 spaces in it. + const string padding(depth*4, ' '); + + // We can obtain a list of all the keys and sub-blocks defined + // at the current level in the config reader like so: + vector keys, blocks; + cr.get_keys(keys); + cr.get_blocks(blocks); + + // Now print all the key/value pairs + for (unsigned long i = 0; i < keys.size(); ++i) + cout << padding << keys[i] << " = " << cr[keys[i]] << endl; + + // Now print all the sub-blocks. + for (unsigned long i = 0; i < blocks.size(); ++i) + { + // First print the block name + cout << padding << blocks[i] << " { " << endl; + // Now recursively print the contents of the sub block. Note that the cr.block() + // function returns another config_reader that represents the sub-block. + print_config_reader_contents(cr.block(blocks[i]), depth+1); + cout << padding << "}" << endl; + } +} + +// ---------------------------------------------------------------------------------------- + diff --git a/ml/dlib/examples/custom_trainer_ex.cpp b/ml/dlib/examples/custom_trainer_ex.cpp new file mode 100644 index 000000000..39af53f39 --- /dev/null +++ b/ml/dlib/examples/custom_trainer_ex.cpp @@ -0,0 +1,277 @@ +// The contents of this file are in the public domain. See LICENSE_FOR_EXAMPLE_PROGRAMS.txt +/* + This example program shows you how to create your own custom binary classification + trainer object and use it with the multiclass classification tools in the dlib C++ + library. This example assumes you have already become familiar with the concepts + introduced in the multiclass_classification_ex.cpp example program. + + + In this example we will create a very simple trainer object that takes a binary + classification problem and produces a decision rule which says a test point has the + same class as whichever centroid it is closest to. + + The multiclass training dataset will consist of four classes. Each class will be a blob + of points in one of the quadrants of the cartesian plane. For fun, we will use + std::string labels and therefore the labels of these classes will be the following: + "upper_left", + "upper_right", + "lower_left", + "lower_right" +*/ + +#include + +#include +#include + +#include + +using namespace std; +using namespace dlib; + +// Our data will be 2-dimensional data. So declare an appropriate type to contain these points. +typedef matrix sample_type; + +// ---------------------------------------------------------------------------------------- + +struct custom_decision_function +{ + /*! + WHAT THIS OBJECT REPRESENTS + This object is the representation of our binary decision rule. + !*/ + + // centers of the two classes + sample_type positive_center, negative_center; + + double operator() ( + const sample_type& x + ) const + { + // if x is closer to the positive class then return +1 + if (length(positive_center - x) < length(negative_center - x)) + return +1; + else + return -1; + } +}; + +// Later on in this example we will save our decision functions to disk. This +// pair of routines is needed for this functionality. +void serialize (const custom_decision_function& item, std::ostream& out) +{ + // write the state of item to the output stream + serialize(item.positive_center, out); + serialize(item.negative_center, out); +} + +void deserialize (custom_decision_function& item, std::istream& in) +{ + // read the data from the input stream and store it in item + deserialize(item.positive_center, in); + deserialize(item.negative_center, in); +} + +// ---------------------------------------------------------------------------------------- + +class simple_custom_trainer +{ + /*! + WHAT THIS OBJECT REPRESENTS + This is our example custom binary classifier trainer object. It simply + computes the means of the +1 and -1 classes, puts them into our + custom_decision_function, and returns the results. + + Below we define the train() function. I have also included the + requires/ensures definition for a generic binary classifier's train() + !*/ +public: + + + custom_decision_function train ( + const std::vector& samples, + const std::vector& labels + ) const + /*! + requires + - is_binary_classification_problem(samples, labels) == true + (e.g. labels consists of only +1 and -1 values, samples.size() == labels.size()) + ensures + - returns a decision function F with the following properties: + - if (new_x is a sample predicted have +1 label) then + - F(new_x) >= 0 + - else + - F(new_x) < 0 + !*/ + { + sample_type positive_center, negative_center; + + // compute sums of each class + positive_center = 0; + negative_center = 0; + for (unsigned long i = 0; i < samples.size(); ++i) + { + if (labels[i] == +1) + positive_center += samples[i]; + else // this is a -1 sample + negative_center += samples[i]; + } + + // divide by number of +1 samples + positive_center /= sum(mat(labels) == +1); + // divide by number of -1 samples + negative_center /= sum(mat(labels) == -1); + + custom_decision_function df; + df.positive_center = positive_center; + df.negative_center = negative_center; + + return df; + } +}; + +// ---------------------------------------------------------------------------------------- + +void generate_data ( + std::vector& samples, + std::vector& labels +); +/*! + ensures + - make some four class data as described above. + - each class will have 50 samples in it +!*/ + +// ---------------------------------------------------------------------------------------- + +int main() +{ + std::vector samples; + std::vector labels; + + // First, get our labeled set of training data + generate_data(samples, labels); + + cout << "samples.size(): "<< samples.size() << endl; + + // Define the trainer we will use. The second template argument specifies the type + // of label used, which is string in this case. + typedef one_vs_one_trainer, string> ovo_trainer; + + + ovo_trainer trainer; + + // Now tell the one_vs_one_trainer that, by default, it should use the simple_custom_trainer + // to solve the individual binary classification subproblems. + trainer.set_trainer(simple_custom_trainer()); + + // Next, to make things a little more interesting, we will setup the one_vs_one_trainer + // to use kernel ridge regression to solve the upper_left vs lower_right binary classification + // subproblem. + typedef radial_basis_kernel rbf_kernel; + krr_trainer rbf_trainer; + rbf_trainer.set_kernel(rbf_kernel(0.1)); + trainer.set_trainer(rbf_trainer, "upper_left", "lower_right"); + + + // Now let's do 5-fold cross-validation using the one_vs_one_trainer we just setup. + // As an aside, always shuffle the order of the samples before doing cross validation. + // For a discussion of why this is a good idea see the svm_ex.cpp example. + randomize_samples(samples, labels); + cout << "cross validation: \n" << cross_validate_multiclass_trainer(trainer, samples, labels, 5) << endl; + // This dataset is very easy and everything is correctly classified. Therefore, the output of + // cross validation is the following confusion matrix. + /* + 50 0 0 0 + 0 50 0 0 + 0 0 50 0 + 0 0 0 50 + */ + + + // We can also obtain the decision rule as always. + one_vs_one_decision_function df = trainer.train(samples, labels); + + cout << "predicted label: "<< df(samples[0]) << ", true label: "<< labels[0] << endl; + cout << "predicted label: "<< df(samples[90]) << ", true label: "<< labels[90] << endl; + // The output is: + /* + predicted label: upper_right, true label: upper_right + predicted label: lower_left, true label: lower_left + */ + + + // Finally, let's save our multiclass decision rule to disk. Remember that we have + // to specify the types of binary decision function used inside the one_vs_one_decision_function. + one_vs_one_decision_function > // This is the output of the rbf_trainer + > df2, df3; + + df2 = df; + // save to a file called df.dat + serialize("df.dat") << df2; + + // load the function back in from disk and store it in df3. + deserialize("df.dat") >> df3; + + + // Test df3 to see that this worked. + cout << endl; + cout << "predicted label: "<< df3(samples[0]) << ", true label: "<< labels[0] << endl; + cout << "predicted label: "<< df3(samples[90]) << ", true label: "<< labels[90] << endl; + // Test df3 on the samples and labels and print the confusion matrix. + cout << "test deserialized function: \n" << test_multiclass_decision_function(df3, samples, labels) << endl; + +} + +// ---------------------------------------------------------------------------------------- + +void generate_data ( + std::vector& samples, + std::vector& labels +) +{ + const long num = 50; + + sample_type m; + + dlib::rand rnd; + + + // add some points in the upper right quadrant + m = 10, 10; + for (long i = 0; i < num; ++i) + { + samples.push_back(m + randm(2,1,rnd)); + labels.push_back("upper_right"); + } + + // add some points in the upper left quadrant + m = -10, 10; + for (long i = 0; i < num; ++i) + { + samples.push_back(m + randm(2,1,rnd)); + labels.push_back("upper_left"); + } + + // add some points in the lower right quadrant + m = 10, -10; + for (long i = 0; i < num; ++i) + { + samples.push_back(m + randm(2,1,rnd)); + labels.push_back("lower_right"); + } + + // add some points in the lower left quadrant + m = -10, -10; + for (long i = 0; i < num; ++i) + { + samples.push_back(m + randm(2,1,rnd)); + labels.push_back("lower_left"); + } + +} + +// ---------------------------------------------------------------------------------------- + diff --git a/ml/dlib/examples/dir_nav_ex.cpp b/ml/dlib/examples/dir_nav_ex.cpp new file mode 100644 index 000000000..2f51f2d1b --- /dev/null +++ b/ml/dlib/examples/dir_nav_ex.cpp @@ -0,0 +1,75 @@ +// The contents of this file are in the public domain. See LICENSE_FOR_EXAMPLE_PROGRAMS.txt +/* + + This is an example illustrating the use of the dir_nav component from the dlib C++ Library. + It prints a listing of all directories and files in the users + current working directory or the directory specified on the command line. + +*/ + + +#include +#include +#include +#include +#include + +using namespace std; +using namespace dlib; + + +int main(int argc, char** argv) +{ + try + { + string loc; + if (argc == 2) + loc = argv[1]; + else + loc = "."; // if no argument is given then use the current working dir. + + directory test(loc); + + + cout << "directory: " << test.name() << endl; + cout << "full path: " << test.full_name() << endl; + cout << "is root: " << ((test.is_root())?"yes":"no") << endl; + + // get all directories and files in test + std::vector dirs = test.get_dirs(); + std::vector files = test.get_files(); + + // sort the files and directories + sort(files.begin(), files.end()); + sort(dirs.begin(), dirs.end()); + + cout << "\n\n\n"; + + // print all the subdirectories + for (unsigned long i = 0; i < dirs.size(); ++i) + cout << " " << dirs[i].name() << "\n"; + + // print all the subfiles + for (unsigned long i = 0; i < files.size(); ++i) + cout << setw(13) << files[i].size() << " " << files[i].name() << "\n"; + + + cout << "\n\nnumber of dirs: " << dirs.size() << endl; + cout << "number of files: " << files.size() << endl; + + } + catch (file::file_not_found& e) + { + cout << "file not found or accessible: " << e.info << endl; + } + catch (directory::dir_not_found& e) + { + cout << "dir not found or accessible: " << e.info << endl; + } + catch (directory::listing_error& e) + { + cout << "listing error: " << e.info << endl; + } +} + + diff --git a/ml/dlib/examples/dnn_face_recognition_ex.cpp b/ml/dlib/examples/dnn_face_recognition_ex.cpp new file mode 100644 index 000000000..4c0a2a02b --- /dev/null +++ b/ml/dlib/examples/dnn_face_recognition_ex.cpp @@ -0,0 +1,220 @@ +// The contents of this file are in the public domain. See LICENSE_FOR_EXAMPLE_PROGRAMS.txt +/* + This is an example illustrating the use of the deep learning tools from the dlib C++ + Library. In it, we will show how to do face recognition. This example uses the + pretrained dlib_face_recognition_resnet_model_v1 model which is freely available from + the dlib web site. This model has a 99.38% accuracy on the standard LFW face + recognition benchmark, which is comparable to other state-of-the-art methods for face + recognition as of February 2017. + + In this example, we will use dlib to do face clustering. Included in the examples + folder is an image, bald_guys.jpg, which contains a bunch of photos of action movie + stars Vin Diesel, The Rock, Jason Statham, and Bruce Willis. We will use dlib to + automatically find their faces in the image and then to automatically determine how + many people there are (4 in this case) as well as which faces belong to each person. + + Finally, this example uses a network with the loss_metric loss. Therefore, if you want + to learn how to train your own models, or to get a general introduction to this loss + layer, you should read the dnn_metric_learning_ex.cpp and + dnn_metric_learning_on_images_ex.cpp examples. +*/ + +#include +#include +#include +#include +#include +#include + +using namespace dlib; +using namespace std; + +// ---------------------------------------------------------------------------------------- + +// The next bit of code defines a ResNet network. It's basically copied +// and pasted from the dnn_imagenet_ex.cpp example, except we replaced the loss +// layer with loss_metric and made the network somewhat smaller. Go read the introductory +// dlib DNN examples to learn what all this stuff means. +// +// Also, the dnn_metric_learning_on_images_ex.cpp example shows how to train this network. +// The dlib_face_recognition_resnet_model_v1 model used by this example was trained using +// essentially the code shown in dnn_metric_learning_on_images_ex.cpp except the +// mini-batches were made larger (35x15 instead of 5x5), the iterations without progress +// was set to 10000, and the training dataset consisted of about 3 million images instead of +// 55. Also, the input layer was locked to images of size 150. +template